mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-25 18:50:07 +01:00
Various synchronous methods (D-Bus calls) in libnm's NMClient API were deprecated. The problem is that NMClient contains a cache of D-Bus objects, and it gets updated by asynchronous events (D-Bus signals). Those events get only processed when iterating the GMainContext, but they are ordered. When we perform a pseudo blocking D-Bus call with g_dbus_connection_call_sync(), then GDBus creates a temporary GMainContext, sends the request and iterates the internal context blocking for the response. That is, this reply is not synchrounized with the events that update the NMClient cache. That is a problem for methods like nm_remote_connection_delete(), because you call blocking delete, but afterwards the object is still in the NMClient cache. That's why most blocking methods are deprecated. While such blocking calls are therefore problematic, they can still be very convenient to call from a simple script, a test tool or the python REPL. See "examples/python/gi/nm-wg-set" which calls nm_remote_connection_get_secrets(), and it would be (unnecessarily) cumbersome to do the correct thing or using async API. In particular, nm_remote_connection_get_secrets() doesn't retrieve an object that is in the NMClient cache in the first place. Sure, the result is out of order with the cache, but it's not obviously related and in most cases it wouldn't matter to the user. So undeprecate this function again. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1345
843 lines
31 KiB
C
843 lines
31 KiB
C
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
/*
|
|
* Copyright (C) 2007 - 2008 Novell, Inc.
|
|
* Copyright (C) 2007 - 2011 Red Hat, Inc.
|
|
*/
|
|
|
|
#include "libnm-client-impl/nm-default-libnm.h"
|
|
|
|
#include "nm-remote-connection.h"
|
|
|
|
#include "libnm-glib-aux/nm-dbus-aux.h"
|
|
#include "nm-dbus-interface.h"
|
|
#include "nm-utils.h"
|
|
#include "nm-setting-connection.h"
|
|
#include "libnm-core-intern/nm-core-internal.h"
|
|
#include "nm-remote-connection-private.h"
|
|
#include "nm-object-private.h"
|
|
#include "nm-dbus-helpers.h"
|
|
|
|
/**
|
|
* SECTION:nm-remote-connection
|
|
* @short_description: A connection managed by NetworkManager server
|
|
*
|
|
* A #NMRemoteConnection represents a connection that is exported via
|
|
* NetworkManager D-Bus interface.
|
|
**/
|
|
|
|
/*****************************************************************************/
|
|
|
|
NM_GOBJECT_PROPERTIES_DEFINE(NMRemoteConnection,
|
|
PROP_UNSAVED,
|
|
PROP_FLAGS,
|
|
PROP_FILENAME,
|
|
PROP_VISIBLE, );
|
|
|
|
typedef struct {
|
|
GCancellable *get_settings_cancellable;
|
|
|
|
char *filename;
|
|
guint32 flags;
|
|
bool unsaved;
|
|
|
|
bool visible : 1;
|
|
bool is_initialized : 1;
|
|
} NMRemoteConnectionPrivate;
|
|
|
|
struct _NMRemoteConnection {
|
|
NMObject parent;
|
|
NMRemoteConnectionPrivate _priv;
|
|
};
|
|
|
|
struct _NMRemoteConnectionClass {
|
|
NMObjectClass parent_class;
|
|
};
|
|
|
|
static void nm_remote_connection_connection_iface_init(NMConnectionInterface *iface);
|
|
|
|
G_DEFINE_TYPE_WITH_CODE(NMRemoteConnection,
|
|
nm_remote_connection,
|
|
NM_TYPE_OBJECT,
|
|
G_IMPLEMENT_INTERFACE(NM_TYPE_CONNECTION,
|
|
nm_remote_connection_connection_iface_init);)
|
|
|
|
#define NM_REMOTE_CONNECTION_GET_PRIVATE(self) \
|
|
_NM_GET_PRIVATE(self, NMRemoteConnection, NM_IS_REMOTE_CONNECTION, NMObject)
|
|
|
|
/*****************************************************************************/
|
|
|
|
/**
|
|
* nm_remote_connection_update2:
|
|
* @connection: the #NMRemoteConnection
|
|
* @settings: (allow-none): optional connection to update the settings.
|
|
* @flags: update-flags
|
|
* @args: (allow-none): optional arguments.
|
|
* @cancellable: a #GCancellable, or %NULL
|
|
* @callback: callback to be called when the commit operation completes
|
|
* @user_data: caller-specific data passed to @callback
|
|
*
|
|
* Asynchronously calls the Update2() D-Bus method.
|
|
*
|
|
* Since: 1.12
|
|
**/
|
|
void
|
|
nm_remote_connection_update2(NMRemoteConnection *connection,
|
|
GVariant *settings,
|
|
NMSettingsUpdate2Flags flags,
|
|
GVariant *args,
|
|
GCancellable *cancellable,
|
|
GAsyncReadyCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
g_return_if_fail(NM_IS_REMOTE_CONNECTION(connection));
|
|
g_return_if_fail(!settings || g_variant_is_of_type(settings, NM_VARIANT_TYPE_CONNECTION));
|
|
g_return_if_fail(!args || g_variant_is_of_type(args, G_VARIANT_TYPE("a{sv}")));
|
|
g_return_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable));
|
|
|
|
if (!settings)
|
|
settings = nm_g_variant_singleton_aLsaLsvII();
|
|
if (!args)
|
|
args = nm_g_variant_singleton_aLsvI();
|
|
|
|
_nm_client_dbus_call(_nm_object_get_client(connection),
|
|
connection,
|
|
nm_remote_connection_update2,
|
|
cancellable,
|
|
callback,
|
|
user_data,
|
|
_nm_object_get_path(connection),
|
|
NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
|
|
"Update2",
|
|
g_variant_new("(@a{sa{sv}}u@a{sv})", settings, (guint32) flags, args),
|
|
G_VARIANT_TYPE("(a{sv})"),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
|
|
nm_dbus_connection_call_finish_variant_strip_dbus_error_cb);
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_update2_finish:
|
|
* @connection: the #NMRemoteConnection
|
|
* @result: the result passed to the #GAsyncReadyCallback
|
|
* @error: location for a #GError, or %NULL
|
|
*
|
|
* Gets the result of a call to nm_remote_connection_commit_changes_async().
|
|
*
|
|
* Returns: (transfer full): on success, a #GVariant of type "a{sv}" with the result. On failure,
|
|
* %NULL.
|
|
**/
|
|
GVariant *
|
|
nm_remote_connection_update2_finish(NMRemoteConnection *connection,
|
|
GAsyncResult *result,
|
|
GError **error)
|
|
{
|
|
gs_unref_variant GVariant *ret = NULL;
|
|
GVariant *v_result;
|
|
|
|
g_return_val_if_fail(NM_IS_REMOTE_CONNECTION(connection), NULL);
|
|
g_return_val_if_fail(nm_g_task_is_valid(result, connection, nm_remote_connection_update2),
|
|
NULL);
|
|
|
|
ret = g_task_propagate_pointer(G_TASK(result), error);
|
|
if (!ret)
|
|
return NULL;
|
|
|
|
g_variant_get(ret, "(@a{sv})", &v_result);
|
|
|
|
return v_result;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
/**
|
|
* nm_remote_connection_commit_changes:
|
|
* @connection: the #NMRemoteConnection
|
|
* @save_to_disk: whether to persist the changes to disk
|
|
* @cancellable: a #GCancellable, or %NULL
|
|
* @error: location for a #GError, or %NULL
|
|
*
|
|
* Send any local changes to the settings and properties of @connection to
|
|
* NetworkManager. If @save_to_disk is %TRUE, the updated connection will be saved to
|
|
* disk; if %FALSE, then only the in-memory representation will be changed.
|
|
*
|
|
* Returns: %TRUE on success, %FALSE on error, in which case @error will be set.
|
|
*
|
|
* Deprecated: 1.22: Use nm_remote_connection_commit_changes_async() or GDBusConnection.
|
|
**/
|
|
gboolean
|
|
nm_remote_connection_commit_changes(NMRemoteConnection *connection,
|
|
gboolean save_to_disk,
|
|
GCancellable *cancellable,
|
|
GError **error)
|
|
{
|
|
gs_unref_variant GVariant *ret = NULL;
|
|
|
|
g_return_val_if_fail(NM_IS_REMOTE_CONNECTION(connection), FALSE);
|
|
g_return_val_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable), FALSE);
|
|
|
|
ret = _nm_client_dbus_call_sync(
|
|
_nm_object_get_client(connection),
|
|
cancellable,
|
|
_nm_object_get_path(connection),
|
|
NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
|
|
"Update2",
|
|
g_variant_new("(@a{sa{sv}}u@a{sv})",
|
|
nm_connection_to_dbus(NM_CONNECTION(connection), NM_CONNECTION_SERIALIZE_ALL),
|
|
(guint32) (save_to_disk ? NM_SETTINGS_UPDATE2_FLAG_TO_DISK
|
|
: NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY),
|
|
nm_g_variant_singleton_aLsvI()),
|
|
G_VARIANT_TYPE("(a{sv})"),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
|
|
TRUE,
|
|
error);
|
|
if (!ret)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_commit_changes_async:
|
|
* @connection: the #NMRemoteConnection
|
|
* @save_to_disk: whether to save the changes to persistent storage
|
|
* @cancellable: a #GCancellable, or %NULL
|
|
* @callback: callback to be called when the commit operation completes
|
|
* @user_data: caller-specific data passed to @callback
|
|
*
|
|
* Asynchronously sends any local changes to the settings and properties of
|
|
* @connection to NetworkManager. If @save is %TRUE, the updated connection will
|
|
* be saved to disk; if %FALSE, then only the in-memory representation will be
|
|
* changed.
|
|
**/
|
|
void
|
|
nm_remote_connection_commit_changes_async(NMRemoteConnection *connection,
|
|
gboolean save_to_disk,
|
|
GCancellable *cancellable,
|
|
GAsyncReadyCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
g_return_if_fail(NM_IS_REMOTE_CONNECTION(connection));
|
|
g_return_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable));
|
|
|
|
nm_remote_connection_update2(
|
|
connection,
|
|
nm_connection_to_dbus(NM_CONNECTION(connection), NM_CONNECTION_SERIALIZE_ALL),
|
|
save_to_disk ? NM_SETTINGS_UPDATE2_FLAG_TO_DISK : NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY,
|
|
NULL,
|
|
cancellable,
|
|
callback,
|
|
user_data);
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_commit_changes_finish:
|
|
* @connection: the #NMRemoteConnection
|
|
* @result: the result passed to the #GAsyncReadyCallback
|
|
* @error: location for a #GError, or %NULL
|
|
*
|
|
* Gets the result of a call to nm_remote_connection_commit_changes_async().
|
|
*
|
|
* Returns: %TRUE on success, %FALSE on error, in which case @error will be set.
|
|
**/
|
|
gboolean
|
|
nm_remote_connection_commit_changes_finish(NMRemoteConnection *connection,
|
|
GAsyncResult *result,
|
|
GError **error)
|
|
{
|
|
gs_unref_variant GVariant *v_result = NULL;
|
|
|
|
v_result = nm_remote_connection_update2_finish(connection, result, error);
|
|
return !!v_result;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
/**
|
|
* nm_remote_connection_save:
|
|
* @connection: the #NMRemoteConnection
|
|
* @cancellable: a #GCancellable, or %NULL
|
|
* @error: location for a #GError, or %NULL
|
|
*
|
|
* Saves the connection to disk if the connection has changes that have not yet
|
|
* been written to disk, or if the connection has never been saved.
|
|
*
|
|
* Returns: %TRUE on success, %FALSE on error, in which case @error will be set.
|
|
*
|
|
* Deprecated: 1.22: Use nm_remote_connection_save_async() or GDBusConnection.
|
|
**/
|
|
gboolean
|
|
nm_remote_connection_save(NMRemoteConnection *connection, GCancellable *cancellable, GError **error)
|
|
{
|
|
g_return_val_if_fail(NM_IS_REMOTE_CONNECTION(connection), FALSE);
|
|
g_return_val_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable), FALSE);
|
|
|
|
return _nm_client_dbus_call_sync_void(_nm_object_get_client(connection),
|
|
cancellable,
|
|
_nm_object_get_path(connection),
|
|
NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
|
|
"Save",
|
|
g_variant_new("()"),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
|
|
TRUE,
|
|
error);
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_save_async:
|
|
* @connection: the #NMRemoteConnection
|
|
* @cancellable: a #GCancellable, or %NULL
|
|
* @callback: callback to be called when the save operation completes
|
|
* @user_data: caller-specific data passed to @callback
|
|
*
|
|
* Saves the connection to disk if the connection has changes that have not yet
|
|
* been written to disk, or if the connection has never been saved.
|
|
**/
|
|
void
|
|
nm_remote_connection_save_async(NMRemoteConnection *connection,
|
|
GCancellable *cancellable,
|
|
GAsyncReadyCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
g_return_if_fail(NM_IS_REMOTE_CONNECTION(connection));
|
|
g_return_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable));
|
|
|
|
_nm_client_dbus_call(_nm_object_get_client(connection),
|
|
connection,
|
|
nm_remote_connection_save_async,
|
|
cancellable,
|
|
callback,
|
|
user_data,
|
|
_nm_object_get_path(connection),
|
|
NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
|
|
"Save",
|
|
g_variant_new("()"),
|
|
G_VARIANT_TYPE("()"),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
|
|
nm_dbus_connection_call_finish_void_strip_dbus_error_cb);
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_save_finish:
|
|
* @connection: the #NMRemoteConnection
|
|
* @result: the result passed to the #GAsyncReadyCallback
|
|
* @error: location for a #GError, or %NULL
|
|
*
|
|
* Gets the result of a call to nm_remote_connection_save_async().
|
|
*
|
|
* Returns: %TRUE on success, %FALSE on error, in which case @error will be set.
|
|
**/
|
|
gboolean
|
|
nm_remote_connection_save_finish(NMRemoteConnection *connection,
|
|
GAsyncResult *result,
|
|
GError **error)
|
|
{
|
|
g_return_val_if_fail(NM_IS_REMOTE_CONNECTION(connection), FALSE);
|
|
g_return_val_if_fail(nm_g_task_is_valid(result, connection, nm_remote_connection_save_async),
|
|
FALSE);
|
|
|
|
return g_task_propagate_boolean(G_TASK(result), error);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
/**
|
|
* nm_remote_connection_delete:
|
|
* @connection: the #NMRemoteConnection
|
|
* @cancellable: a #GCancellable, or %NULL
|
|
* @error: location for a #GError, or %NULL
|
|
*
|
|
* Deletes the connection.
|
|
*
|
|
* Returns: %TRUE on success, %FALSE on error, in which case @error will be set.
|
|
*
|
|
* Deprecated: 1.22: Use nm_remote_connection_delete_async() or GDBusConnection.
|
|
**/
|
|
gboolean
|
|
nm_remote_connection_delete(NMRemoteConnection *connection,
|
|
GCancellable *cancellable,
|
|
GError **error)
|
|
{
|
|
g_return_val_if_fail(NM_IS_REMOTE_CONNECTION(connection), FALSE);
|
|
|
|
return _nm_client_dbus_call_sync_void(_nm_object_get_client(connection),
|
|
cancellable,
|
|
_nm_object_get_path(connection),
|
|
NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
|
|
"Delete",
|
|
g_variant_new("()"),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
|
|
TRUE,
|
|
error);
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_delete_async:
|
|
* @connection: the #NMRemoteConnection
|
|
* @cancellable: a #GCancellable, or %NULL
|
|
* @callback: callback to be called when the delete operation completes
|
|
* @user_data: caller-specific data passed to @callback
|
|
*
|
|
* Asynchronously deletes the connection.
|
|
**/
|
|
void
|
|
nm_remote_connection_delete_async(NMRemoteConnection *connection,
|
|
GCancellable *cancellable,
|
|
GAsyncReadyCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
g_return_if_fail(NM_IS_REMOTE_CONNECTION(connection));
|
|
g_return_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable));
|
|
|
|
_nm_client_dbus_call(_nm_object_get_client(connection),
|
|
connection,
|
|
nm_remote_connection_delete_async,
|
|
cancellable,
|
|
callback,
|
|
user_data,
|
|
_nm_object_get_path(connection),
|
|
NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
|
|
"Delete",
|
|
g_variant_new("()"),
|
|
G_VARIANT_TYPE("()"),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
|
|
nm_dbus_connection_call_finish_void_strip_dbus_error_cb);
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_delete_finish:
|
|
* @connection: the #NMRemoteConnection
|
|
* @result: the result passed to the #GAsyncReadyCallback
|
|
* @error: location for a #GError, or %NULL
|
|
*
|
|
* Gets the result of a call to nm_remote_connection_delete_async().
|
|
*
|
|
* Returns: %TRUE on success, %FALSE on error, in which case @error will be set.
|
|
**/
|
|
gboolean
|
|
nm_remote_connection_delete_finish(NMRemoteConnection *connection,
|
|
GAsyncResult *result,
|
|
GError **error)
|
|
{
|
|
g_return_val_if_fail(NM_IS_REMOTE_CONNECTION(connection), FALSE);
|
|
g_return_val_if_fail(nm_g_task_is_valid(result, connection, nm_remote_connection_delete_async),
|
|
FALSE);
|
|
|
|
return g_task_propagate_boolean(G_TASK(result), error);
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_get_secrets:
|
|
* @connection: the #NMRemoteConnection
|
|
* @setting_name: the #NMSetting object name to get secrets for
|
|
* @cancellable: a #GCancellable, or %NULL
|
|
* @error: location for a #GError, or %NULL
|
|
*
|
|
* Request the connection's secrets. Note that this is a blocking D-Bus call,
|
|
* not a simple property accessor.
|
|
*
|
|
* Returns: (transfer full): a #GVariant of type %NM_VARIANT_TYPE_CONNECTION containing
|
|
* @connection's secrets, or %NULL on error.
|
|
*
|
|
* Warning: NMClient contains a cache of objects on D-Bus. This cache gets updated
|
|
* with D-Bus signals when iterating the GMainContext. This function performs a
|
|
* (pseudo) blocking D-Bus call. Aside blocking, the result will not be in sync
|
|
* and not be ordered with the content of the NMClient cache.
|
|
* This function used to be deprecated between 1.22 and 1.38 releases.
|
|
**/
|
|
GVariant *
|
|
nm_remote_connection_get_secrets(NMRemoteConnection *connection,
|
|
const char *setting_name,
|
|
GCancellable *cancellable,
|
|
GError **error)
|
|
{
|
|
gs_unref_variant GVariant *ret = NULL;
|
|
GVariant *secrets;
|
|
|
|
g_return_val_if_fail(NM_IS_REMOTE_CONNECTION(connection), NULL);
|
|
g_return_val_if_fail(setting_name, NULL);
|
|
g_return_val_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable), NULL);
|
|
|
|
ret = _nm_client_dbus_call_sync(_nm_object_get_client(connection),
|
|
cancellable,
|
|
_nm_object_get_path(connection),
|
|
NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
|
|
"GetSecrets",
|
|
g_variant_new("(s)", setting_name),
|
|
G_VARIANT_TYPE("(a{sa{sv}})"),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
|
|
TRUE,
|
|
error);
|
|
if (!ret)
|
|
return NULL;
|
|
|
|
g_variant_get(ret, "(@a{sa{sv}})", &secrets);
|
|
|
|
return secrets;
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_get_secrets_async:
|
|
* @connection: the #NMRemoteConnection
|
|
* @setting_name: the #NMSetting object name to get secrets for
|
|
* @cancellable: a #GCancellable, or %NULL
|
|
* @callback: callback to be called when the secret request completes
|
|
* @user_data: caller-specific data passed to @callback
|
|
*
|
|
* Asynchronously requests the connection's secrets.
|
|
**/
|
|
void
|
|
nm_remote_connection_get_secrets_async(NMRemoteConnection *connection,
|
|
const char *setting_name,
|
|
GCancellable *cancellable,
|
|
GAsyncReadyCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
g_return_if_fail(NM_IS_REMOTE_CONNECTION(connection));
|
|
g_return_if_fail(setting_name);
|
|
g_return_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable));
|
|
|
|
_nm_client_dbus_call(_nm_object_get_client(connection),
|
|
connection,
|
|
nm_remote_connection_get_secrets_async,
|
|
cancellable,
|
|
callback,
|
|
user_data,
|
|
_nm_object_get_path(connection),
|
|
NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
|
|
"GetSecrets",
|
|
g_variant_new("(s)", setting_name),
|
|
G_VARIANT_TYPE("(a{sa{sv}})"),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
|
|
nm_dbus_connection_call_finish_variant_strip_dbus_error_cb);
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_get_secrets_finish:
|
|
* @connection: the #NMRemoteConnection
|
|
* @result: the result passed to the #GAsyncReadyCallback
|
|
* @error: location for a #GError, or %NULL
|
|
*
|
|
* Gets the result of a call to nm_remote_connection_get_secrets_async().
|
|
*
|
|
* Returns: (transfer full): a #GVariant of type %NM_VARIANT_TYPE_CONNECTION
|
|
* containing @connection's secrets, or %NULL on error.
|
|
**/
|
|
GVariant *
|
|
nm_remote_connection_get_secrets_finish(NMRemoteConnection *connection,
|
|
GAsyncResult *result,
|
|
GError **error)
|
|
{
|
|
gs_unref_variant GVariant *ret = NULL;
|
|
GVariant *secrets;
|
|
|
|
g_return_val_if_fail(NM_IS_REMOTE_CONNECTION(connection), NULL);
|
|
g_return_val_if_fail(
|
|
nm_g_task_is_valid(result, connection, nm_remote_connection_get_secrets_async),
|
|
FALSE);
|
|
|
|
ret = g_task_propagate_pointer(G_TASK(result), error);
|
|
if (!ret)
|
|
return NULL;
|
|
|
|
g_variant_get(ret, "(@a{sa{sv}})", &secrets);
|
|
|
|
return secrets;
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_get_unsaved:
|
|
* @connection: the #NMRemoteConnection
|
|
*
|
|
* Returns: %TRUE if the remote connection contains changes that have not
|
|
* been saved to disk, %FALSE if the connection is the same as its on-disk
|
|
* representation.
|
|
**/
|
|
gboolean
|
|
nm_remote_connection_get_unsaved(NMRemoteConnection *connection)
|
|
{
|
|
g_return_val_if_fail(NM_IS_REMOTE_CONNECTION(connection), FALSE);
|
|
|
|
return NM_REMOTE_CONNECTION_GET_PRIVATE(connection)->unsaved;
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_get_flags:
|
|
* @connection: the #NMRemoteConnection
|
|
*
|
|
* Returns: the flags of the connection of type #NMSettingsConnectionFlags.
|
|
*
|
|
* Since: 1.12
|
|
**/
|
|
NMSettingsConnectionFlags
|
|
nm_remote_connection_get_flags(NMRemoteConnection *connection)
|
|
{
|
|
g_return_val_if_fail(NM_IS_REMOTE_CONNECTION(connection), FALSE);
|
|
|
|
return (NMSettingsConnectionFlags) NM_REMOTE_CONNECTION_GET_PRIVATE(connection)->flags;
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_get_filename:
|
|
* @connection: the #NMRemoteConnection
|
|
*
|
|
* Returns: file that stores the connection in case the connection is file-backed.
|
|
*
|
|
* Since: 1.12
|
|
**/
|
|
const char *
|
|
nm_remote_connection_get_filename(NMRemoteConnection *connection)
|
|
{
|
|
g_return_val_if_fail(NM_IS_REMOTE_CONNECTION(connection), NULL);
|
|
|
|
return NM_REMOTE_CONNECTION_GET_PRIVATE(connection)->filename;
|
|
}
|
|
|
|
/**
|
|
* nm_remote_connection_get_visible:
|
|
* @connection: the #NMRemoteConnection
|
|
*
|
|
* Checks if the connection is visible to the current user. If the
|
|
* connection is not visible then it is essentially useless; it will
|
|
* not contain any settings, and operations such as
|
|
* nm_remote_connection_save() and nm_remote_connection_delete() will
|
|
* always fail. (#NMRemoteSettings will not normally return
|
|
* non-visible connections to callers, but it is possible for a
|
|
* connection's visibility to change after you already have a
|
|
* reference to it.)
|
|
*
|
|
* Returns: %TRUE if the remote connection is visible to the current
|
|
* user, %FALSE if not.
|
|
**/
|
|
gboolean
|
|
nm_remote_connection_get_visible(NMRemoteConnection *connection)
|
|
{
|
|
g_return_val_if_fail(NM_IS_REMOTE_CONNECTION(connection), FALSE);
|
|
|
|
return NM_REMOTE_CONNECTION_GET_PRIVATE(connection)->visible;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
GCancellable *
|
|
_nm_remote_settings_get_settings_prepare(NMRemoteConnection *self)
|
|
{
|
|
NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE(self);
|
|
|
|
nm_clear_g_cancellable(&priv->get_settings_cancellable);
|
|
priv->get_settings_cancellable = g_cancellable_new();
|
|
return priv->get_settings_cancellable;
|
|
}
|
|
|
|
void
|
|
_nm_remote_settings_get_settings_commit(NMRemoteConnection *self, GVariant *settings)
|
|
{
|
|
NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE(self);
|
|
GError *error = NULL;
|
|
gboolean visible = FALSE;
|
|
gboolean changed = FALSE;
|
|
|
|
g_clear_object(&priv->get_settings_cancellable);
|
|
|
|
if (!priv->is_initialized) {
|
|
changed = TRUE;
|
|
priv->is_initialized = TRUE;
|
|
}
|
|
|
|
if (settings) {
|
|
if (!_nm_connection_replace_settings((NMConnection *) self,
|
|
settings,
|
|
NM_SETTING_PARSE_FLAGS_BEST_EFFORT,
|
|
&error)) {
|
|
NML_NMCLIENT_LOG_E(_nm_object_get_client(self),
|
|
"[%s] failure to update settings: %s",
|
|
_nm_object_get_path(self),
|
|
error->message);
|
|
g_clear_error(&error);
|
|
} else
|
|
visible = TRUE;
|
|
} else
|
|
nm_connection_clear_settings(NM_CONNECTION(self));
|
|
|
|
if (priv->visible != visible) {
|
|
priv->visible = visible;
|
|
_nm_client_queue_notify_object(_nm_object_get_client(self),
|
|
self,
|
|
obj_properties[PROP_VISIBLE]);
|
|
changed = TRUE;
|
|
}
|
|
|
|
if (changed)
|
|
_nm_client_notify_object_changed(_nm_object_get_client(self), _nm_object_get_dbobj(self));
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static gboolean
|
|
is_ready(NMObject *nmobj)
|
|
{
|
|
NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE(nmobj);
|
|
|
|
if (!priv->is_initialized)
|
|
return FALSE;
|
|
|
|
return NM_OBJECT_CLASS(nm_remote_connection_parent_class)->is_ready(nmobj);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
register_client(NMObject *nmobj, NMClient *client, NMLDBusObject *dbobj)
|
|
{
|
|
NM_OBJECT_CLASS(nm_remote_connection_parent_class)->register_client(nmobj, client, dbobj);
|
|
nm_connection_set_path(NM_CONNECTION(nmobj), dbobj->dbus_path->str);
|
|
_nm_client_get_settings_call(client, dbobj);
|
|
}
|
|
|
|
static void
|
|
unregister_client(NMObject *nmobj, NMClient *client, NMLDBusObject *dbobj)
|
|
{
|
|
nm_clear_g_cancellable(&NM_REMOTE_CONNECTION_GET_PRIVATE(nmobj)->get_settings_cancellable);
|
|
NM_OBJECT_CLASS(nm_remote_connection_parent_class)->unregister_client(nmobj, client, dbobj);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
|
{
|
|
switch (prop_id) {
|
|
case PROP_UNSAVED:
|
|
g_value_set_boolean(value, NM_REMOTE_CONNECTION_GET_PRIVATE(object)->unsaved);
|
|
break;
|
|
case PROP_FLAGS:
|
|
g_value_set_uint(value, NM_REMOTE_CONNECTION_GET_PRIVATE(object)->flags);
|
|
break;
|
|
case PROP_FILENAME:
|
|
g_value_set_string(value, NM_REMOTE_CONNECTION_GET_PRIVATE(object)->filename);
|
|
break;
|
|
case PROP_VISIBLE:
|
|
g_value_set_boolean(value, NM_REMOTE_CONNECTION_GET_PRIVATE(object)->visible);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
nm_remote_connection_init(NMRemoteConnection *self)
|
|
{}
|
|
|
|
static void
|
|
dispose(GObject *object)
|
|
{
|
|
NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE(object);
|
|
|
|
nm_clear_g_free(&priv->filename);
|
|
|
|
G_OBJECT_CLASS(nm_remote_connection_parent_class)->dispose(object);
|
|
}
|
|
|
|
const NMLDBusMetaIface _nml_dbus_meta_iface_nm_settings_connection = NML_DBUS_META_IFACE_INIT_PROP(
|
|
NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
|
|
nm_remote_connection_get_type,
|
|
NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_30,
|
|
NML_DBUS_META_IFACE_DBUS_PROPERTIES(
|
|
NML_DBUS_META_PROPERTY_INIT_S("Filename",
|
|
PROP_FILENAME,
|
|
NMRemoteConnection,
|
|
_priv.filename),
|
|
NML_DBUS_META_PROPERTY_INIT_U("Flags", PROP_FLAGS, NMRemoteConnection, _priv.flags),
|
|
NML_DBUS_META_PROPERTY_INIT_B("Unsaved",
|
|
PROP_UNSAVED,
|
|
NMRemoteConnection,
|
|
_priv.unsaved), ), );
|
|
|
|
static void
|
|
nm_remote_connection_class_init(NMRemoteConnectionClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
NMObjectClass *nm_object_class = NM_OBJECT_CLASS(klass);
|
|
|
|
object_class->get_property = get_property;
|
|
object_class->dispose = dispose;
|
|
|
|
nm_object_class->is_ready = is_ready;
|
|
nm_object_class->register_client = register_client;
|
|
nm_object_class->unregister_client = unregister_client;
|
|
|
|
/**
|
|
* NMRemoteConnection:unsaved:
|
|
*
|
|
* %TRUE if the remote connection contains changes that have not been saved
|
|
* to disk, %FALSE if the connection is the same as its on-disk representation.
|
|
**/
|
|
obj_properties[PROP_UNSAVED] = g_param_spec_boolean(NM_REMOTE_CONNECTION_UNSAVED,
|
|
"",
|
|
"",
|
|
FALSE,
|
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
|
|
|
/**
|
|
* NMRemoteConnection:flags:
|
|
*
|
|
* The flags of the connection as unsigned integer. The values
|
|
* correspond to the #NMSettingsConnectionFlags enum.
|
|
*
|
|
* Since: 1.12
|
|
**/
|
|
obj_properties[PROP_FLAGS] = g_param_spec_uint(NM_REMOTE_CONNECTION_FLAGS,
|
|
"",
|
|
"",
|
|
0,
|
|
G_MAXUINT32,
|
|
0,
|
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
|
|
|
/**
|
|
* NMRemoteConnection:filename:
|
|
*
|
|
* File that stores the connection in case the connection is
|
|
* file-backed.
|
|
*
|
|
* Since: 1.12
|
|
**/
|
|
obj_properties[PROP_FILENAME] = g_param_spec_string(NM_REMOTE_CONNECTION_FILENAME,
|
|
"",
|
|
"",
|
|
NULL,
|
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
|
|
|
/**
|
|
* NMRemoteConnection:visible:
|
|
*
|
|
* %TRUE if the remote connection is visible to the current user, %FALSE if
|
|
* not. If the connection is not visible then it is essentially useless; it
|
|
* will not contain any settings, and operations such as
|
|
* nm_remote_connection_save() and nm_remote_connection_delete() will always
|
|
* fail. (#NMRemoteSettings will not normally return non-visible connections
|
|
* to callers, but it is possible for a connection's visibility to change
|
|
* after you already have a reference to it.)
|
|
**/
|
|
obj_properties[PROP_VISIBLE] = g_param_spec_boolean(NM_REMOTE_CONNECTION_VISIBLE,
|
|
"",
|
|
"",
|
|
FALSE,
|
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
|
|
|
_nml_dbus_meta_class_init_with_properties(object_class,
|
|
&_nml_dbus_meta_iface_nm_settings_connection);
|
|
}
|
|
|
|
static void
|
|
nm_remote_connection_connection_iface_init(NMConnectionInterface *iface)
|
|
{}
|