NetworkManager/libnm/nm-manager.c
Thomas Haller b6efac9ec2 c-list: re-import latest version of c-list.h from upstream
Most notably, it renames
  c_list_unlink_init() -> c_list_unlink()
  c_list_unlink() -> c_list_unlink_stale()

  $ sed -e 's/\<c_list_unlink\>/c_list_unlink_old/g' \
        -e 's/\<c_list_unlink_init\>/c_list_unlink/g' \
        -e 's/\<c_list_unlink_old\>/c_list_unlink_stale/g' \
        $(git grep -l c_list_unlink -- ':(exclude)shared/nm-utils/c-list.h') \
        -i
2017-11-28 11:26:39 +01:00

2045 lines
65 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2007 - 2008 Novell, Inc.
* Copyright 2007 - 2014 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-manager.h"
#include <string.h>
#include "nm-utils.h"
#include "nm-checkpoint.h"
#include "nm-common-macros.h"
#include "nm-device-ethernet.h"
#include "nm-device-wifi.h"
#include "nm-core-internal.h"
#include "nm-object-private.h"
#include "nm-active-connection.h"
#include "nm-vpn-connection.h"
#include "nm-dbus-helpers.h"
#include "nm-utils/c-list.h"
#include "introspection/org.freedesktop.NetworkManager.h"
void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled);
static void nm_manager_initable_iface_init (GInitableIface *iface);
static void nm_manager_async_initable_iface_init (GAsyncInitableIface *iface);
static GInitableIface *nm_manager_parent_initable_iface;
static GAsyncInitableIface *nm_manager_parent_async_initable_iface;
G_DEFINE_TYPE_WITH_CODE (NMManager, nm_manager, NM_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_manager_initable_iface_init);
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_manager_async_initable_iface_init);
)
#define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate))
typedef struct {
NMDBusManager *proxy;
GCancellable *props_cancellable;
char *version;
NMState state;
gboolean startup;
GPtrArray *devices;
GPtrArray *all_devices;
GPtrArray *active_connections;
GPtrArray *checkpoints;
GSList *added_checkpoints;
NMConnectivityState connectivity;
NMActiveConnection *primary_connection;
NMActiveConnection *activating_connection;
NMMetered metered;
GCancellable *perm_call_cancellable;
GHashTable *permissions;
/* Activations waiting for their NMActiveConnection
* to appear and then their callback to be called.
*/
CList pending_activations;
gboolean networking_enabled;
gboolean wireless_enabled;
gboolean wireless_hw_enabled;
gboolean wwan_enabled;
gboolean wwan_hw_enabled;
gboolean wimax_enabled;
gboolean wimax_hw_enabled;
gboolean connectivity_check_available;
gboolean connectivity_check_enabled;
} NMManagerPrivate;
enum {
PROP_0,
PROP_VERSION,
PROP_STATE,
PROP_STARTUP,
PROP_NETWORKING_ENABLED,
PROP_WIRELESS_ENABLED,
PROP_WIRELESS_HARDWARE_ENABLED,
PROP_WWAN_ENABLED,
PROP_WWAN_HARDWARE_ENABLED,
PROP_WIMAX_ENABLED,
PROP_WIMAX_HARDWARE_ENABLED,
PROP_ACTIVE_CONNECTIONS,
PROP_CONNECTIVITY,
PROP_CONNECTIVITY_CHECK_AVAILABLE,
PROP_CONNECTIVITY_CHECK_ENABLED,
PROP_PRIMARY_CONNECTION,
PROP_ACTIVATING_CONNECTION,
PROP_DEVICES,
PROP_CHECKPOINTS,
PROP_METERED,
PROP_ALL_DEVICES,
LAST_PROP
};
enum {
DEVICE_ADDED,
DEVICE_REMOVED,
ANY_DEVICE_ADDED,
ANY_DEVICE_REMOVED,
ACTIVE_CONNECTION_ADDED,
ACTIVE_CONNECTION_REMOVED,
CHECKPOINT_ADDED,
CHECKPOINT_REMOVED,
PERMISSION_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
/*****************************************************************************/
typedef struct {
NMManager *manager;
GSimpleAsyncResult *simple;
char *path;
} CheckpointInfo;
static CheckpointInfo *
find_checkpoint_info (NMManager *manager, const char *path)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
CheckpointInfo *info;
GSList *iter;
for (iter = priv->added_checkpoints; iter; iter = g_slist_next (iter)) {
info = iter->data;
if (nm_streq (path, info->path))
return info;
}
return NULL;
}
static void
checkpoint_info_complete (NMManager *self,
CheckpointInfo *info,
NMCheckpoint *checkpoint,
GError *error)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
g_return_if_fail (info);
if (checkpoint) {
g_simple_async_result_set_op_res_gpointer (info->simple,
g_object_ref (checkpoint),
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->simple);
priv->added_checkpoints = g_slist_remove (priv->added_checkpoints, info);
g_free (info->path);
g_slice_free (CheckpointInfo, info);
}
static void
nm_manager_init (NMManager *manager)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
c_list_init (&priv->pending_activations);
priv->state = NM_STATE_UNKNOWN;
priv->connectivity = NM_CONNECTIVITY_UNKNOWN;
priv->permissions = g_hash_table_new (nm_direct_hash, NULL);
priv->devices = g_ptr_array_new ();
priv->all_devices = g_ptr_array_new ();
priv->active_connections = g_ptr_array_new ();
}
static void
poke_wireless_devices_with_rf_status (NMManager *manager)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
int i;
for (i = 0; i < priv->all_devices->len; i++) {
NMDevice *device = g_ptr_array_index (priv->all_devices, i);
if (NM_IS_DEVICE_WIFI (device))
_nm_device_wifi_set_wireless_enabled (NM_DEVICE_WIFI (device), priv->wireless_enabled);
}
}
static void
wireless_enabled_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
{
poke_wireless_devices_with_rf_status (NM_MANAGER (object));
}
static void manager_recheck_permissions (NMDBusManager *proxy, gpointer user_data);
static void
init_dbus (NMObject *object)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object);
const NMPropertiesInfo property_info[] = {
{ NM_MANAGER_VERSION, &priv->version },
{ NM_MANAGER_STATE, &priv->state },
{ NM_MANAGER_STARTUP, &priv->startup },
{ NM_MANAGER_NETWORKING_ENABLED, &priv->networking_enabled },
{ NM_MANAGER_WIRELESS_ENABLED, &priv->wireless_enabled },
{ NM_MANAGER_WIRELESS_HARDWARE_ENABLED, &priv->wireless_hw_enabled },
{ NM_MANAGER_WWAN_ENABLED, &priv->wwan_enabled },
{ NM_MANAGER_WWAN_HARDWARE_ENABLED, &priv->wwan_hw_enabled },
{ NM_MANAGER_WIMAX_ENABLED, &priv->wimax_enabled },
{ NM_MANAGER_WIMAX_HARDWARE_ENABLED, &priv->wimax_hw_enabled },
{ NM_MANAGER_ACTIVE_CONNECTIONS, &priv->active_connections, NULL, NM_TYPE_ACTIVE_CONNECTION, "active-connection" },
{ NM_MANAGER_CONNECTIVITY, &priv->connectivity },
{ NM_MANAGER_CONNECTIVITY_CHECK_AVAILABLE, &priv->connectivity_check_available },
{ NM_MANAGER_CONNECTIVITY_CHECK_ENABLED, &priv->connectivity_check_enabled },
{ NM_MANAGER_PRIMARY_CONNECTION, &priv->primary_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
{ NM_MANAGER_ACTIVATING_CONNECTION, &priv->activating_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
{ NM_MANAGER_DEVICES, &priv->devices, NULL, NM_TYPE_DEVICE, "device" },
{ NM_MANAGER_CHECKPOINTS, &priv->checkpoints, NULL, NM_TYPE_CHECKPOINT, "checkpoint" },
{ NM_MANAGER_METERED, &priv->metered },
{ NM_MANAGER_ALL_DEVICES, &priv->all_devices, NULL, NM_TYPE_DEVICE, "any-device" },
{ NULL },
};
NM_OBJECT_CLASS (nm_manager_parent_class)->init_dbus (object);
priv->proxy = NMDBUS_MANAGER (_nm_object_get_proxy (object, NM_DBUS_INTERFACE));
_nm_object_register_properties (object,
NM_DBUS_INTERFACE,
property_info);
/* Permissions */
g_signal_connect_object (priv->proxy, "check-permissions",
G_CALLBACK (manager_recheck_permissions), object, 0);
}
static void
object_creation_failed (NMObject *object, const char *failed_path)
{
NMManager *self = NM_MANAGER (object);
CheckpointInfo *info;
GError *add_error;
info = find_checkpoint_info (self, failed_path);
if (info) {
add_error = g_error_new_literal (NM_CLIENT_ERROR,
NM_CLIENT_ERROR_OBJECT_CREATION_FAILED,
_("Checkpoint was removed before it was initialized"));
checkpoint_info_complete (self, info, NULL, add_error);
g_error_free (add_error);
}
}
static NMClientPermission
nm_permission_to_client (const char *nm)
{
if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK;
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI;
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN;
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX;
else if (!strcmp (nm, NM_AUTH_PERMISSION_SLEEP_WAKE))
return NM_CLIENT_PERMISSION_SLEEP_WAKE;
else if (!strcmp (nm, NM_AUTH_PERMISSION_NETWORK_CONTROL))
return NM_CLIENT_PERMISSION_NETWORK_CONTROL;
else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED))
return NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED;
else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN))
return NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN;
else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM))
return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM;
else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN))
return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN;
else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME))
return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME;
else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS))
return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS;
else if (!strcmp (nm, NM_AUTH_PERMISSION_RELOAD))
return NM_CLIENT_PERMISSION_RELOAD;
else if (!strcmp (nm, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK))
return NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK;
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS;
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK;
return NM_CLIENT_PERMISSION_NONE;
}
static NMClientPermissionResult
nm_permission_result_to_client (const char *nm)
{
if (!strcmp (nm, "yes"))
return NM_CLIENT_PERMISSION_RESULT_YES;
else if (!strcmp (nm, "no"))
return NM_CLIENT_PERMISSION_RESULT_NO;
else if (!strcmp (nm, "auth"))
return NM_CLIENT_PERMISSION_RESULT_AUTH;
return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
}
static void
update_permissions (NMManager *self, GVariant *permissions)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GHashTableIter iter;
gpointer key, value;
NMClientPermission perm;
NMClientPermissionResult perm_result;
GList *keys, *keys_iter;
/* get list of old permissions for change notification */
keys = g_hash_table_get_keys (priv->permissions);
g_hash_table_remove_all (priv->permissions);
if (permissions) {
GVariantIter viter;
const char *pkey, *pvalue;
/* Process new permissions */
g_variant_iter_init (&viter, permissions);
while (g_variant_iter_next (&viter, "{&s&s}", &pkey, &pvalue)) {
perm = nm_permission_to_client (pkey);
perm_result = nm_permission_result_to_client (pvalue);
if (perm) {
g_hash_table_insert (priv->permissions,
GUINT_TO_POINTER (perm),
GUINT_TO_POINTER (perm_result));
/* Remove this permission from the list of previous permissions
* we'll be sending NM_CLIENT_PERMISSION_RESULT_UNKNOWN for
* in the change signal since it is still a known permission.
*/
keys = g_list_remove (keys, GUINT_TO_POINTER (perm));
}
}
}
/* Signal changes in all updated permissions */
g_hash_table_iter_init (&iter, priv->permissions);
while (g_hash_table_iter_next (&iter, &key, &value)) {
g_signal_emit (self, signals[PERMISSION_CHANGED], 0,
GPOINTER_TO_UINT (key),
GPOINTER_TO_UINT (value));
}
/* And signal changes in all permissions that used to be valid but for
* some reason weren't received in the last request (if any).
*/
for (keys_iter = keys; keys_iter; keys_iter = g_list_next (keys_iter)) {
g_signal_emit (self, signals[PERMISSION_CHANGED], 0,
GPOINTER_TO_UINT (keys_iter->data),
NM_CLIENT_PERMISSION_RESULT_UNKNOWN);
}
g_list_free (keys);
}
static gboolean
get_permissions_sync (NMManager *self, GError **error)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GVariant *permissions;
if (nmdbus_manager_call_get_permissions_sync (priv->proxy,
&permissions,
NULL, error)) {
update_permissions (self, permissions);
g_variant_unref (permissions);
return TRUE;
} else {
if (error && *error)
g_dbus_error_strip_remote_error (*error);
update_permissions (self, NULL);
return FALSE;
}
}
static void
get_permissions_reply (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
NMManager *self;
NMManagerPrivate *priv;
GVariant *permissions = NULL;
GError *error = NULL;
/* WARNING: this may be called after the manager is disposed, so we can't
* look at self/priv until after we've determined that that isn't the case.
*/
nmdbus_manager_call_get_permissions_finish (NMDBUS_MANAGER (object),
&permissions,
result, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
/* @self has been disposed. */
g_error_free (error);
return;
}
self = user_data;
priv = NM_MANAGER_GET_PRIVATE (self);
update_permissions (self, permissions);
g_clear_pointer (&permissions, g_variant_unref);
g_clear_error (&error);
g_clear_object (&priv->perm_call_cancellable);
}
static void
manager_recheck_permissions (NMDBusManager *proxy, gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
if (priv->perm_call_cancellable)
return;
priv->perm_call_cancellable = g_cancellable_new ();
nmdbus_manager_call_get_permissions (priv->proxy,
priv->perm_call_cancellable,
get_permissions_reply,
self);
}
const char *
nm_manager_get_version (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
return nm_str_not_empty (NM_MANAGER_GET_PRIVATE (manager)->version);
}
NMState
nm_manager_get_state (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN);
return NM_MANAGER_GET_PRIVATE (manager)->state;
}
gboolean
nm_manager_get_startup (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN);
return NM_MANAGER_GET_PRIVATE (manager)->startup;
}
gboolean
nm_manager_networking_get_enabled (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
return NM_MANAGER_GET_PRIVATE (manager)->networking_enabled;
}
gboolean
nm_manager_networking_set_enabled (NMManager *manager, gboolean enable, GError **error)
{
gboolean ret;
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
ret = nmdbus_manager_call_enable_sync (NM_MANAGER_GET_PRIVATE (manager)->proxy,
enable,
NULL, error);
if (error && *error)
g_dbus_error_strip_remote_error (*error);
return ret;
}
gboolean
nm_manager_wireless_get_enabled (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
return NM_MANAGER_GET_PRIVATE (manager)->wireless_enabled;
}
void
nm_manager_wireless_set_enabled (NMManager *manager, gboolean enabled)
{
g_return_if_fail (NM_IS_MANAGER (manager));
_nm_object_set_property (NM_OBJECT (manager),
NM_DBUS_INTERFACE,
"WirelessEnabled",
"b", enabled);
}
gboolean
nm_manager_wireless_hardware_get_enabled (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
return NM_MANAGER_GET_PRIVATE (manager)->wireless_hw_enabled;
}
gboolean
nm_manager_wwan_get_enabled (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
return NM_MANAGER_GET_PRIVATE (manager)->wwan_enabled;
}
void
nm_manager_wwan_set_enabled (NMManager *manager, gboolean enabled)
{
g_return_if_fail (NM_IS_MANAGER (manager));
_nm_object_set_property (NM_OBJECT (manager),
NM_DBUS_INTERFACE,
"WwanEnabled",
"b", enabled);
}
gboolean
nm_manager_wwan_hardware_get_enabled (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
return NM_MANAGER_GET_PRIVATE (manager)->wwan_hw_enabled;
}
gboolean
nm_manager_wimax_get_enabled (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
return NM_MANAGER_GET_PRIVATE (manager)->wimax_enabled;
}
void
nm_manager_wimax_set_enabled (NMManager *manager, gboolean enabled)
{
g_return_if_fail (NM_IS_MANAGER (manager));
_nm_object_set_property (NM_OBJECT (manager),
NM_DBUS_INTERFACE,
"WimaxEnabled",
"b", enabled);
}
gboolean
nm_manager_wimax_hardware_get_enabled (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
return NM_MANAGER_GET_PRIVATE (manager)->wimax_hw_enabled;
}
gboolean
nm_manager_connectivity_check_get_available (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
return NM_MANAGER_GET_PRIVATE (manager)->connectivity_check_available;
}
gboolean
nm_manager_connectivity_check_get_enabled (NMManager *manager)
{
return NM_MANAGER_GET_PRIVATE (manager)->connectivity_check_enabled;
}
void
nm_manager_connectivity_check_set_enabled (NMManager *manager, gboolean enabled)
{
g_return_if_fail (NM_IS_MANAGER (manager));
_nm_object_set_property (NM_OBJECT (manager),
NM_DBUS_INTERFACE,
"ConnectivityCheckEnabled",
"b", enabled);
}
gboolean
nm_manager_get_logging (NMManager *manager, char **level, char **domains, GError **error)
{
gboolean ret;
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
g_return_val_if_fail (level == NULL || *level == NULL, FALSE);
g_return_val_if_fail (domains == NULL || *domains == NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (!level && !domains)
return TRUE;
ret = nmdbus_manager_call_get_logging_sync (NM_MANAGER_GET_PRIVATE (manager)->proxy,
level, domains,
NULL, error);
if (error && *error)
g_dbus_error_strip_remote_error (*error);
return ret;
}
gboolean
nm_manager_set_logging (NMManager *manager, const char *level, const char *domains, GError **error)
{
gboolean ret;
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (!level && !domains)
return TRUE;
if (!level)
level = "";
if (!domains)
domains = "";
ret = nmdbus_manager_call_set_logging_sync (NM_MANAGER_GET_PRIVATE (manager)->proxy,
level, domains,
NULL, error);
if (error && *error)
g_dbus_error_strip_remote_error (*error);
return ret;
}
NMClientPermissionResult
nm_manager_get_permission_result (NMManager *manager, NMClientPermission permission)
{
gpointer result;
g_return_val_if_fail (NM_IS_MANAGER (manager), NM_CLIENT_PERMISSION_RESULT_UNKNOWN);
result = g_hash_table_lookup (NM_MANAGER_GET_PRIVATE (manager)->permissions,
GUINT_TO_POINTER (permission));
return GPOINTER_TO_UINT (result);
}
NMConnectivityState
nm_manager_get_connectivity (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), NM_CONNECTIVITY_UNKNOWN);
return NM_MANAGER_GET_PRIVATE (manager)->connectivity;
}
NMConnectivityState
nm_manager_check_connectivity (NMManager *manager,
GCancellable *cancellable,
GError **error)
{
NMManagerPrivate *priv;
guint32 connectivity;
g_return_val_if_fail (NM_IS_MANAGER (manager), NM_CONNECTIVITY_UNKNOWN);
priv = NM_MANAGER_GET_PRIVATE (manager);
if (nmdbus_manager_call_check_connectivity_sync (priv->proxy,
&connectivity,
cancellable, error)) {
if (connectivity != priv->connectivity) {
priv->connectivity = connectivity;
g_object_notify (G_OBJECT (manager), NM_MANAGER_CONNECTIVITY);
}
return connectivity;
}
else {
if (error && *error)
g_dbus_error_strip_remote_error (*error);
return NM_CONNECTIVITY_UNKNOWN;
}
}
static void
check_connectivity_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GSimpleAsyncResult *simple = user_data;
guint32 connectivity;
GError *error = NULL;
NMManager *manager;
NMManagerPrivate *priv;
if (nmdbus_manager_call_check_connectivity_finish (NMDBUS_MANAGER (object),
&connectivity,
result, &error)) {
g_simple_async_result_set_op_res_gssize (simple, connectivity);
manager = NM_MANAGER (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
priv = NM_MANAGER_GET_PRIVATE (manager);
if (connectivity != priv->connectivity) {
priv->connectivity = connectivity;
g_object_notify (G_OBJECT (manager), NM_MANAGER_CONNECTIVITY);
}
} else {
g_dbus_error_strip_remote_error (error);
g_simple_async_result_take_error (simple, error);
}
g_simple_async_result_complete (simple);
g_object_unref (simple);
}
void
nm_manager_check_connectivity_async (NMManager *manager,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
NMManagerPrivate *priv;
GSimpleAsyncResult *simple;
g_return_if_fail (NM_IS_MANAGER (manager));
priv = NM_MANAGER_GET_PRIVATE (manager);
simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data,
nm_manager_check_connectivity_async);
nmdbus_manager_call_check_connectivity (priv->proxy,
cancellable,
check_connectivity_cb, simple);
}
NMConnectivityState
nm_manager_check_connectivity_finish (NMManager *manager,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_check_connectivity_async), NM_CONNECTIVITY_UNKNOWN);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return NM_CONNECTIVITY_UNKNOWN;
return (NMConnectivityState) g_simple_async_result_get_op_res_gssize (simple);
}
/*****************************************************************************/
/* Devices */
/*****************************************************************************/
const GPtrArray *
nm_manager_get_devices (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
return NM_MANAGER_GET_PRIVATE (manager)->devices;
}
const GPtrArray *
nm_manager_get_all_devices (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
return NM_MANAGER_GET_PRIVATE (manager)->all_devices;
}
NMDevice *
nm_manager_get_device_by_path (NMManager *manager, const char *object_path)
{
const GPtrArray *devices;
int i;
NMDevice *device = NULL;
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
g_return_val_if_fail (object_path, NULL);
devices = nm_manager_get_devices (manager);
for (i = 0; i < devices->len; i++) {
NMDevice *candidate = g_ptr_array_index (devices, i);
if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), object_path)) {
device = candidate;
break;
}
}
return device;
}
NMDevice *
nm_manager_get_device_by_iface (NMManager *manager, const char *iface)
{
const GPtrArray *devices;
int i;
NMDevice *device = NULL;
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
g_return_val_if_fail (iface, NULL);
devices = nm_manager_get_devices (manager);
for (i = 0; i < devices->len; i++) {
NMDevice *candidate = g_ptr_array_index (devices, i);
if (!strcmp (nm_device_get_iface (candidate), iface)) {
device = candidate;
break;
}
}
return device;
}
/*****************************************************************************/
/* Active Connections */
/*****************************************************************************/
const GPtrArray *
nm_manager_get_active_connections (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
return NM_MANAGER_GET_PRIVATE (manager)->active_connections;
}
NMActiveConnection *
nm_manager_get_primary_connection (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
return NM_MANAGER_GET_PRIVATE (manager)->primary_connection;
}
NMActiveConnection *
nm_manager_get_activating_connection (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
return NM_MANAGER_GET_PRIVATE (manager)->activating_connection;
}
typedef struct {
CList lst;
NMManager *manager;
GSimpleAsyncResult *simple;
GCancellable *cancellable;
gulong cancelled_id;
char *active_path;
char *new_connection_path;
} ActivateInfo;
static void
activate_info_complete (ActivateInfo *info,
NMActiveConnection *active,
GError *error)
{
if (active)
g_simple_async_result_set_op_res_gpointer (info->simple, g_object_ref (active), g_object_unref);
else
g_simple_async_result_set_from_error (info->simple, error);
g_simple_async_result_complete (info->simple);
c_list_unlink_stale (&info->lst);
g_free (info->active_path);
g_free (info->new_connection_path);
g_object_unref (info->simple);
if (info->cancellable) {
if (info->cancelled_id)
g_signal_handler_disconnect (info->cancellable, info->cancelled_id);
g_object_unref (info->cancellable);
}
g_slice_free (ActivateInfo, info);
}
static NMActiveConnection *
find_active_connection_by_path (NMManager *self, const char *ac_path)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
int i;
for (i = 0; i < priv->active_connections->len; i++) {
NMActiveConnection *candidate = g_ptr_array_index (priv->active_connections, i);
const char *candidate_path = nm_object_get_path (NM_OBJECT (candidate));
if (g_strcmp0 (ac_path, candidate_path) == 0)
return candidate;
}
return NULL;
}
static void
recheck_pending_activations (NMManager *self)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
CList *iter, *safe;
NMActiveConnection *candidate;
const GPtrArray *devices;
NMDevice *device;
GDBusObjectManager *object_manager = NULL;
GError *error;
object_manager = _nm_object_get_dbus_object_manager (NM_OBJECT (self));
/* For each pending activation, look for an active connection that has the
* pending activation's object path, where the active connection and its
* device have both updated their properties to point to each other, and
* call the pending connection's callback.
*/
c_list_for_each_safe (iter, safe, &priv->pending_activations) {
ActivateInfo *info = c_list_entry (iter, ActivateInfo, lst);
gs_unref_object GDBusObject *dbus_obj = NULL;
if (!info->active_path)
continue;
/* Check that the object manager still knows about the object.
* It could be that it vanished before we even learned its name. */
dbus_obj = g_dbus_object_manager_get_object (object_manager, info->active_path);
if (!dbus_obj) {
error = g_error_new_literal (NM_CLIENT_ERROR,
NM_CLIENT_ERROR_OBJECT_CREATION_FAILED,
_("Active connection removed before it was initialized"));
activate_info_complete (info, NULL, error);
g_clear_error (&error);
break;
}
candidate = find_active_connection_by_path (self, info->active_path);
if (!candidate)
continue;
/* Check that the AC and device are both ready */
devices = nm_active_connection_get_devices (candidate);
if (devices->len == 0)
continue;
if (!NM_IS_VPN_CONNECTION (candidate)) {
device = devices->pdata[0];
if (nm_device_get_active_connection (device) != candidate)
continue;
}
activate_info_complete (info, candidate, NULL);
break;
}
}
static void
activation_cancelled (GCancellable *cancellable,
gpointer user_data)
{
ActivateInfo *info = user_data;
GError *error = NULL;
if (!g_cancellable_set_error_if_cancelled (cancellable, &error))
return;
activate_info_complete (info, NULL, error);
g_clear_error (&error);
}
static void
activate_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
ActivateInfo *info = user_data;
GError *error = NULL;
if (nmdbus_manager_call_activate_connection_finish (NMDBUS_MANAGER (object),
&info->active_path,
result, &error)) {
if (info->cancellable) {
info->cancelled_id = g_signal_connect (info->cancellable, "cancelled",
G_CALLBACK (activation_cancelled), info);
}
recheck_pending_activations (info->manager);
} else {
g_dbus_error_strip_remote_error (error);
activate_info_complete (info, NULL, error);
g_clear_error (&error);
}
}
void
nm_manager_activate_connection_async (NMManager *manager,
NMConnection *connection,
NMDevice *device,
const char *specific_object,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
NMManagerPrivate *priv;
ActivateInfo *info;
g_return_if_fail (NM_IS_MANAGER (manager));
if (device)
g_return_if_fail (NM_IS_DEVICE (device));
if (connection)
g_return_if_fail (NM_IS_CONNECTION (connection));
priv = NM_MANAGER_GET_PRIVATE (manager);
info = g_slice_new0 (ActivateInfo);
info->manager = manager;
info->simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data,
nm_manager_activate_connection_async);
info->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
c_list_link_tail (&priv->pending_activations, &info->lst);
nmdbus_manager_call_activate_connection (priv->proxy,
connection ? nm_connection_get_path (connection) : "/",
device ? nm_object_get_path (NM_OBJECT (device)) : "/",
specific_object ? specific_object : "/",
cancellable,
activate_cb, info);
}
NMActiveConnection *
nm_manager_activate_connection_finish (NMManager *manager,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_activate_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));
}
static void
add_activate_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
ActivateInfo *info = user_data;
GError *error = NULL;
if (nmdbus_manager_call_add_and_activate_connection_finish (NMDBUS_MANAGER (object),
NULL,
&info->active_path,
result, &error)) {
if (info->cancellable) {
info->cancelled_id = g_signal_connect (info->cancellable, "cancelled",
G_CALLBACK (activation_cancelled), info);
}
recheck_pending_activations (info->manager);
} else {
g_dbus_error_strip_remote_error (error);
activate_info_complete (info, NULL, error);
g_clear_error (&error);
}
}
void
nm_manager_add_and_activate_connection_async (NMManager *manager,
NMConnection *partial,
NMDevice *device,
const char *specific_object,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
NMManagerPrivate *priv;
GVariant *dict = NULL;
ActivateInfo *info;
g_return_if_fail (NM_IS_MANAGER (manager));
g_return_if_fail (NM_IS_DEVICE (device));
if (partial)
g_return_if_fail (NM_IS_CONNECTION (partial));
priv = NM_MANAGER_GET_PRIVATE (manager);
info = g_slice_new0 (ActivateInfo);
info->manager = manager;
info->simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data,
nm_manager_add_and_activate_connection_async);
info->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
c_list_link_tail (&priv->pending_activations, &info->lst);
if (partial)
dict = nm_connection_to_dbus (partial, NM_CONNECTION_SERIALIZE_ALL);
if (!dict)
dict = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0);
nmdbus_manager_call_add_and_activate_connection (priv->proxy,
dict,
nm_object_get_path (NM_OBJECT (device)),
specific_object ? specific_object : "/",
cancellable,
add_activate_cb, info);
}
NMActiveConnection *
nm_manager_add_and_activate_connection_finish (NMManager *manager,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_add_and_activate_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));
}
static void
device_ac_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
{
NMManager *self = user_data;
recheck_pending_activations (self);
}
static void
device_added (NMManager *self, NMDevice *device)
{
g_signal_connect_object (device, "notify::" NM_DEVICE_ACTIVE_CONNECTION,
G_CALLBACK (device_ac_changed), self, 0);
}
static void
device_removed (NMManager *self, NMDevice *device)
{
g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_ac_changed), self);
}
static void
ac_devices_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
{
NMManager *self = user_data;
recheck_pending_activations (self);
}
static void
active_connection_added (NMManager *self, NMActiveConnection *ac)
{
g_signal_connect_object (ac, "notify::" NM_ACTIVE_CONNECTION_DEVICES,
G_CALLBACK (ac_devices_changed), self, 0);
recheck_pending_activations (self);
}
static void
active_connection_removed (NMManager *self, NMActiveConnection *ac)
{
g_signal_handlers_disconnect_by_func (ac, G_CALLBACK (ac_devices_changed), self);
recheck_pending_activations (self);
}
static void
checkpoint_added (NMManager *manager, NMCheckpoint *checkpoint)
{
CheckpointInfo *info;
info = find_checkpoint_info (manager, nm_object_get_path (NM_OBJECT (checkpoint)));
if (info)
checkpoint_info_complete (manager, info, checkpoint, NULL);
}
static void
checkpoint_removed (NMManager *manager, NMCheckpoint *checkpoint)
{
}
gboolean
nm_manager_deactivate_connection (NMManager *manager,
NMActiveConnection *active,
GCancellable *cancellable,
GError **error)
{
const char *path;
gboolean ret;
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (active), FALSE);
path = nm_object_get_path (NM_OBJECT (active));
ret = nmdbus_manager_call_deactivate_connection_sync (NM_MANAGER_GET_PRIVATE (manager)->proxy,
path,
cancellable, error);
if (error && *error)
g_dbus_error_strip_remote_error (*error);
return ret;
}
static void
deactivated_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GSimpleAsyncResult *simple = user_data;
GError *error = NULL;
if (nmdbus_manager_call_deactivate_connection_finish (NMDBUS_MANAGER (object),
result, &error))
g_simple_async_result_set_op_res_gboolean (simple, TRUE);
else {
g_dbus_error_strip_remote_error (error);
g_simple_async_result_take_error (simple, error);
}
g_simple_async_result_complete (simple);
g_object_unref (simple);
}
void
nm_manager_deactivate_connection_async (NMManager *manager,
NMActiveConnection *active,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
const char *path;
GSimpleAsyncResult *simple;
g_return_if_fail (NM_IS_MANAGER (manager));
g_return_if_fail (NM_IS_ACTIVE_CONNECTION (active));
simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data,
nm_manager_deactivate_connection_async);
path = nm_object_get_path (NM_OBJECT (active));
nmdbus_manager_call_deactivate_connection (NM_MANAGER_GET_PRIVATE (manager)->proxy,
path,
cancellable,
deactivated_cb, simple);
}
gboolean
nm_manager_deactivate_connection_finish (NMManager *manager,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_deactivate_connection_async), FALSE);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return FALSE;
else
return g_simple_async_result_get_op_res_gboolean (simple);
}
/*****************************************************************************/
static void
free_active_connections (NMManager *manager)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
int i;
if (!priv->active_connections)
return;
/* Break circular refs */
for (i = 0; i < priv->active_connections->len; i++)
g_object_run_dispose (G_OBJECT (priv->active_connections->pdata[i]));
g_ptr_array_unref (priv->active_connections);
priv->active_connections = NULL;
}
/*****************************************************************************/
static const char **
get_device_paths (const GPtrArray *devices)
{
const char **array;
guint i;
array = g_new (const char *, devices->len + 1);
for (i = 0; i < devices->len; i++)
array[i] = nm_object_get_path (NM_OBJECT (devices->pdata[i]));
array[i] = NULL;
return array;
}
const GPtrArray *
nm_manager_get_checkpoints (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
return NM_MANAGER_GET_PRIVATE (manager)->checkpoints;
}
static void
checkpoint_created_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
CheckpointInfo *info = user_data;
GError *error = NULL;
nmdbus_manager_call_checkpoint_create_finish (NMDBUS_MANAGER (object),
&info->path, result, &error);
if (error) {
g_dbus_error_strip_remote_error (error);
checkpoint_info_complete (info->manager, info, NULL, error);
g_clear_error (&error);
}
}
void
nm_manager_checkpoint_create_async (NMManager *manager,
const GPtrArray *devices,
guint32 rollback_timeout,
NMCheckpointCreateFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
gs_free const char **paths = NULL;
CheckpointInfo *info;
g_return_if_fail (NM_IS_MANAGER (manager));
info = g_slice_new0 (CheckpointInfo);
info->manager = manager;
info->simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data,
nm_manager_checkpoint_create_async);
paths = get_device_paths (devices);
nmdbus_manager_call_checkpoint_create (NM_MANAGER_GET_PRIVATE (manager)->proxy,
paths,
rollback_timeout,
flags,
cancellable,
checkpoint_created_cb,
info);
priv->added_checkpoints = g_slist_append (priv->added_checkpoints, info);
}
NMCheckpoint *
nm_manager_checkpoint_create_finish (NMManager *manager,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), 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));
}
static void
checkpoint_destroy_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GSimpleAsyncResult *simple = user_data;
GError *error = NULL;
if (nmdbus_manager_call_checkpoint_destroy_finish (NMDBUS_MANAGER (object),
result, &error))
g_simple_async_result_set_op_res_gboolean (simple, TRUE);
else {
g_dbus_error_strip_remote_error (error);
g_simple_async_result_take_error (simple, error);
}
g_simple_async_result_complete (simple);
g_object_unref (simple);
}
void
nm_manager_checkpoint_destroy_async (NMManager *manager,
NMCheckpoint *checkpoint,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
const char *path;
GSimpleAsyncResult *simple;
g_return_if_fail (NM_IS_MANAGER (manager));
g_return_if_fail (NM_IS_CHECKPOINT (checkpoint));
simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data,
nm_manager_checkpoint_destroy_async);
path = nm_object_get_path (NM_OBJECT (checkpoint));
nmdbus_manager_call_checkpoint_destroy (NM_MANAGER_GET_PRIVATE (manager)->proxy,
path,
cancellable,
checkpoint_destroy_cb, simple);
}
gboolean
nm_manager_checkpoint_destroy_finish (NMManager *manager,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager),
nm_manager_checkpoint_destroy_async),
FALSE);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return FALSE;
else
return g_simple_async_result_get_op_res_gboolean (simple);
}
static void
checkpoint_rollback_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GSimpleAsyncResult *simple = user_data;
GError *error = NULL;
GVariant *variant = NULL;
GVariantIter iter;
GHashTable *hash;
const char *path;
guint r;
if (nmdbus_manager_call_checkpoint_rollback_finish (NMDBUS_MANAGER (object),
&variant,
result,
&error)) {
hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, NULL);
g_variant_iter_init (&iter, variant);
while (g_variant_iter_next (&iter, "{&su}", &path, &r))
g_hash_table_insert (hash, g_strdup (path), GUINT_TO_POINTER (r));
g_simple_async_result_set_op_res_gpointer (simple, hash, (GDestroyNotify) g_hash_table_unref);
} else {
g_dbus_error_strip_remote_error (error);
g_simple_async_result_take_error (simple, error);
}
g_simple_async_result_complete (simple);
g_object_unref (simple);
}
void
nm_manager_checkpoint_rollback_async (NMManager *manager,
NMCheckpoint *checkpoint,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
const char *path;
GSimpleAsyncResult *simple;
g_return_if_fail (NM_IS_MANAGER (manager));
g_return_if_fail (NM_IS_CHECKPOINT (checkpoint));
simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data,
nm_manager_checkpoint_rollback_async);
path = nm_object_get_path (NM_OBJECT (checkpoint));
nmdbus_manager_call_checkpoint_rollback (NM_MANAGER_GET_PRIVATE (manager)->proxy,
path,
cancellable,
checkpoint_rollback_cb, simple);
}
GHashTable *
nm_manager_checkpoint_rollback_finish (NMManager *manager,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager),
nm_manager_checkpoint_rollback_async),
NULL);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
else
return g_simple_async_result_get_op_res_gpointer (simple);
}
/*****************************************************************************/
static void
constructed (GObject *object)
{
G_OBJECT_CLASS (nm_manager_parent_class)->constructed (object);
g_signal_connect (object, "notify::" NM_MANAGER_WIRELESS_ENABLED,
G_CALLBACK (wireless_enabled_cb), NULL);
}
static gboolean
init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
{
NMManager *manager = NM_MANAGER (initable);
GError *local_error = NULL;
if (!nm_manager_parent_initable_iface->init (initable, cancellable, error)) {
/* Never happens. */
g_return_val_if_reached (FALSE);
}
if (!get_permissions_sync (manager, &local_error)) {
g_warning ("Unable to get permissions: %s\n", local_error->message);
g_error_free (local_error);
}
return TRUE;
}
typedef struct {
NMManager *manager;
GCancellable *cancellable;
GSimpleAsyncResult *result;
} NMManagerInitData;
static void
init_async_complete (NMManagerInitData *init_data)
{
g_simple_async_result_complete (init_data->result);
g_object_unref (init_data->result);
g_clear_object (&init_data->cancellable);
g_slice_free (NMManagerInitData, init_data);
}
static void
init_async_got_permissions (GObject *object, GAsyncResult *result, gpointer user_data)
{
NMManager *manager = user_data;
GVariant *permissions;
if (nmdbus_manager_call_get_permissions_finish (NMDBUS_MANAGER (object),
&permissions,
result, NULL)) {
update_permissions (manager, permissions);
g_variant_unref (permissions);
} else
update_permissions (manager, NULL);
g_object_unref (manager);
}
static void
init_async_parent_inited (GObject *source, GAsyncResult *result, gpointer user_data)
{
NMManagerInitData *init_data = user_data;
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (init_data->manager);
GError *error = NULL;
if (!nm_manager_parent_async_initable_iface->init_finish (G_ASYNC_INITABLE (source), result, &error)) {
g_simple_async_result_take_error (init_data->result, error);
init_async_complete (init_data);
return;
}
nmdbus_manager_call_get_permissions (priv->proxy,
init_data->cancellable,
init_async_got_permissions,
g_object_ref (init_data->manager));
init_async_complete (init_data);
}
static void
init_async (GAsyncInitable *initable, int io_priority,
GCancellable *cancellable, GAsyncReadyCallback callback,
gpointer user_data)
{
NMManagerInitData *init_data;
init_data = g_slice_new0 (NMManagerInitData);
init_data->manager = NM_MANAGER (initable);
init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
user_data, init_async);
g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
nm_manager_parent_async_initable_iface->init_async (initable, io_priority, cancellable,
init_async_parent_inited, init_data);
}
static gboolean
init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return FALSE;
else
return TRUE;
}
static void
dispose (GObject *object)
{
NMManager *manager = NM_MANAGER (object);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object);
nm_clear_g_cancellable (&priv->perm_call_cancellable);
if (priv->devices) {
g_ptr_array_unref (priv->devices);
priv->devices = NULL;
}
if (priv->all_devices) {
g_ptr_array_unref (priv->all_devices);
priv->all_devices = NULL;
}
free_active_connections (manager);
g_clear_object (&priv->primary_connection);
g_clear_object (&priv->activating_connection);
g_clear_object (&priv->proxy);
/* Each activation should hold a ref on @manager, so if we're being disposed,
* there shouldn't be any pending.
*/
g_warn_if_fail (c_list_is_empty (&priv->pending_activations));
g_hash_table_destroy (priv->permissions);
priv->permissions = NULL;
G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object);
}
static void
finalize (GObject *object)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object);
g_free (priv->version);
G_OBJECT_CLASS (nm_manager_parent_class)->finalize (object);
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object);
gboolean b;
switch (prop_id) {
case PROP_NETWORKING_ENABLED:
b = g_value_get_boolean (value);
if (priv->networking_enabled != b) {
nm_manager_networking_set_enabled (NM_MANAGER (object), b, NULL);
/* Let the property value flip when we get the change signal from NM */
}
break;
case PROP_WIRELESS_ENABLED:
b = g_value_get_boolean (value);
if (priv->wireless_enabled != b) {
nm_manager_wireless_set_enabled (NM_MANAGER (object), b);
/* Let the property value flip when we get the change signal from NM */
}
break;
case PROP_WWAN_ENABLED:
b = g_value_get_boolean (value);
if (priv->wwan_enabled != b) {
nm_manager_wwan_set_enabled (NM_MANAGER (object), b);
/* Let the property value flip when we get the change signal from NM */
}
break;
case PROP_WIMAX_ENABLED:
b = g_value_get_boolean (value);
if (priv->wimax_enabled != b) {
nm_manager_wimax_set_enabled (NM_MANAGER (object), b);
/* Let the property value flip when we get the change signal from NM */
}
break;
case PROP_CONNECTIVITY_CHECK_ENABLED:
b = g_value_get_boolean (value);
if (priv->connectivity_check_enabled != b) {
nm_manager_connectivity_check_set_enabled (NM_MANAGER (object), b);
/* Let the property value flip when we get the change signal from NM */
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
NMManager *self = NM_MANAGER (object);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
switch (prop_id) {
case PROP_VERSION:
g_value_set_string (value, nm_manager_get_version (self));
break;
case PROP_STATE:
g_value_set_enum (value, nm_manager_get_state (self));
break;
case PROP_STARTUP:
g_value_set_boolean (value, nm_manager_get_startup (self));
break;
case PROP_NETWORKING_ENABLED:
g_value_set_boolean (value, nm_manager_networking_get_enabled (self));
break;
case PROP_WIRELESS_ENABLED:
g_value_set_boolean (value, priv->wireless_enabled);
break;
case PROP_WIRELESS_HARDWARE_ENABLED:
g_value_set_boolean (value, priv->wireless_hw_enabled);
break;
case PROP_WWAN_ENABLED:
g_value_set_boolean (value, priv->wwan_enabled);
break;
case PROP_WWAN_HARDWARE_ENABLED:
g_value_set_boolean (value, priv->wwan_hw_enabled);
break;
case PROP_WIMAX_ENABLED:
g_value_set_boolean (value, priv->wimax_enabled);
break;
case PROP_WIMAX_HARDWARE_ENABLED:
g_value_set_boolean (value, priv->wimax_hw_enabled);
break;
case PROP_ACTIVE_CONNECTIONS:
g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_active_connections (self)));
break;
case PROP_CONNECTIVITY:
g_value_set_enum (value, priv->connectivity);
break;
case PROP_CONNECTIVITY_CHECK_AVAILABLE:
g_value_set_boolean (value, priv->connectivity_check_available);
break;
case PROP_CONNECTIVITY_CHECK_ENABLED:
g_value_set_boolean (value, priv->connectivity_check_enabled);
break;
case PROP_PRIMARY_CONNECTION:
g_value_set_object (value, priv->primary_connection);
break;
case PROP_ACTIVATING_CONNECTION:
g_value_set_object (value, priv->activating_connection);
break;
case PROP_DEVICES:
g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_devices (self)));
break;
case PROP_CHECKPOINTS:
g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_checkpoints (self)));
break;
case PROP_METERED:
g_value_set_uint (value, priv->metered);
break;
case PROP_ALL_DEVICES:
g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_all_devices (self)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_manager_class_init (NMManagerClass *manager_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (manager_class);
NMObjectClass *nm_object_class = NM_OBJECT_CLASS (manager_class);
g_type_class_add_private (manager_class, sizeof (NMManagerPrivate));
/* virtual methods */
object_class->constructed = constructed;
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->dispose = dispose;
object_class->finalize = finalize;
nm_object_class->init_dbus = init_dbus;
nm_object_class->object_creation_failed = object_creation_failed;
manager_class->device_added = device_added;
manager_class->device_removed = device_removed;
manager_class->active_connection_added = active_connection_added;
manager_class->active_connection_removed = active_connection_removed;
manager_class->checkpoint_added = checkpoint_added;
manager_class->checkpoint_removed = checkpoint_removed;
/* properties */
g_object_class_install_property
(object_class, PROP_VERSION,
g_param_spec_string (NM_MANAGER_VERSION, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_STATE,
g_param_spec_enum (NM_CLIENT_STATE, "", "",
NM_TYPE_STATE,
NM_STATE_UNKNOWN,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_STARTUP,
g_param_spec_boolean (NM_MANAGER_STARTUP, "", "",
FALSE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_NETWORKING_ENABLED,
g_param_spec_boolean (NM_MANAGER_NETWORKING_ENABLED, "", "",
TRUE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_WIRELESS_ENABLED,
g_param_spec_boolean (NM_MANAGER_WIRELESS_ENABLED, "", "",
FALSE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_WIRELESS_HARDWARE_ENABLED,
g_param_spec_boolean (NM_MANAGER_WIRELESS_HARDWARE_ENABLED, "", "",
TRUE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_WWAN_ENABLED,
g_param_spec_boolean (NM_MANAGER_WWAN_ENABLED, "", "",
FALSE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_WWAN_HARDWARE_ENABLED,
g_param_spec_boolean (NM_MANAGER_WWAN_HARDWARE_ENABLED, "", "",
FALSE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_WIMAX_ENABLED,
g_param_spec_boolean (NM_MANAGER_WIMAX_ENABLED, "", "",
FALSE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_WIMAX_HARDWARE_ENABLED,
g_param_spec_boolean (NM_MANAGER_WIMAX_HARDWARE_ENABLED, "", "",
FALSE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_ACTIVE_CONNECTIONS,
g_param_spec_boxed (NM_MANAGER_ACTIVE_CONNECTIONS, "", "",
G_TYPE_PTR_ARRAY,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_CONNECTIVITY,
g_param_spec_enum (NM_CLIENT_CONNECTIVITY, "", "",
NM_TYPE_CONNECTIVITY_STATE,
NM_CONNECTIVITY_UNKNOWN,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_CONNECTIVITY_CHECK_AVAILABLE,
g_param_spec_boolean (NM_MANAGER_CONNECTIVITY_CHECK_AVAILABLE, "", "",
FALSE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_CONNECTIVITY_CHECK_ENABLED,
g_param_spec_boolean (NM_MANAGER_CONNECTIVITY_CHECK_ENABLED, "", "",
FALSE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_PRIMARY_CONNECTION,
g_param_spec_object (NM_MANAGER_PRIMARY_CONNECTION, "", "",
NM_TYPE_ACTIVE_CONNECTION,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_ACTIVATING_CONNECTION,
g_param_spec_object (NM_MANAGER_ACTIVATING_CONNECTION, "", "",
NM_TYPE_ACTIVE_CONNECTION,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_DEVICES,
g_param_spec_boxed (NM_MANAGER_DEVICES, "", "",
G_TYPE_PTR_ARRAY,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_CHECKPOINTS,
g_param_spec_boxed (NM_MANAGER_CHECKPOINTS, "", "",
G_TYPE_PTR_ARRAY,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMManager:metered:
*
* Whether the connectivity is metered.
*
* Since: 1.2
**/
g_object_class_install_property
(object_class, PROP_METERED,
g_param_spec_uint (NM_MANAGER_METERED, "", "",
0, G_MAXUINT32, NM_METERED_UNKNOWN,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_ALL_DEVICES,
g_param_spec_boxed (NM_MANAGER_ALL_DEVICES, "", "",
G_TYPE_PTR_ARRAY,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/* signals */
signals[DEVICE_ADDED] =
g_signal_new ("device-added",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMManagerClass, device_added),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
signals[DEVICE_REMOVED] =
g_signal_new ("device-removed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMManagerClass, device_removed),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
signals[ANY_DEVICE_ADDED] =
g_signal_new ("any-device-added",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
signals[ANY_DEVICE_REMOVED] =
g_signal_new ("any-device-removed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
signals[ACTIVE_CONNECTION_ADDED] =
g_signal_new ("active-connection-added",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMManagerClass, active_connection_added),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
signals[ACTIVE_CONNECTION_REMOVED] =
g_signal_new ("active-connection-removed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMManagerClass, active_connection_removed),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
signals[CHECKPOINT_ADDED] =
g_signal_new ("checkpoint-added",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMManagerClass, checkpoint_added),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
signals[CHECKPOINT_REMOVED] =
g_signal_new ("checkpoint-removed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMManagerClass, checkpoint_removed),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
signals[PERMISSION_CHANGED] =
g_signal_new ("permission-changed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
}
static void
nm_manager_initable_iface_init (GInitableIface *iface)
{
nm_manager_parent_initable_iface = g_type_interface_peek_parent (iface);
iface->init = init_sync;
}
static void
nm_manager_async_initable_iface_init (GAsyncInitableIface *iface)
{
nm_manager_parent_async_initable_iface = g_type_interface_peek_parent (iface);
iface->init_async = init_async;
iface->init_finish = init_finish;
}