mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-27 04:40:09 +01:00
It's nicely trivial and independent. Move it to a separate place, to avoid cluttering the more complicated code and to make it testable. Also, use binary search to find the value by string.
1532 lines
48 KiB
C
1532 lines
48 KiB
C
// SPDX-License-Identifier: LGPL-2.1+
|
|
/*
|
|
* Copyright (C) 2007 - 2008 Novell, Inc.
|
|
* Copyright (C) 2007 - 2014 Red Hat, Inc.
|
|
*/
|
|
|
|
#include "nm-default.h"
|
|
|
|
#include "nm-manager.h"
|
|
|
|
#include "nm-utils.h"
|
|
#include "nm-checkpoint.h"
|
|
#include "nm-libnm-core-intern/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 "c-list/src/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;
|
|
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 wait_for_active_connection_lst_head;
|
|
|
|
CList wait_for_checkpoint_lst_head;
|
|
|
|
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;
|
|
|
|
NM_GOBJECT_PROPERTIES_DEFINE (NMManager,
|
|
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,
|
|
);
|
|
|
|
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 {
|
|
CList lst;
|
|
NMManager *self;
|
|
char *checkpoint_path;
|
|
GTask *task;
|
|
gulong cancelled_id;
|
|
} CheckpointInfo;
|
|
|
|
static CheckpointInfo *
|
|
_wait_for_checkpoint_find_info (NMManager *manager, const char *path)
|
|
{
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
|
CheckpointInfo *info;
|
|
|
|
c_list_for_each_entry (info, &priv->wait_for_checkpoint_lst_head, lst) {
|
|
if (nm_streq (path, info->checkpoint_path))
|
|
return info;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
_wait_for_checkpoint_complete (CheckpointInfo *info,
|
|
NMCheckpoint *checkpoint,
|
|
GError *error)
|
|
{
|
|
c_list_unlink_stale (&info->lst);
|
|
|
|
nm_clear_g_signal_handler (g_task_get_cancellable (info->task), &info->cancelled_id);
|
|
|
|
if (!checkpoint)
|
|
g_task_return_error (info->task, error);
|
|
else
|
|
g_task_return_pointer (info->task, g_object_ref (checkpoint), g_object_unref);
|
|
|
|
g_object_unref (info->task);
|
|
g_object_unref (info->self);
|
|
g_free (info->checkpoint_path);
|
|
nm_g_slice_free (info);
|
|
}
|
|
|
|
static void
|
|
nm_manager_init (NMManager *manager)
|
|
{
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
|
|
|
c_list_init (&priv->wait_for_active_connection_lst_head);
|
|
c_list_init (&priv->wait_for_checkpoint_lst_head);
|
|
|
|
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 = _wait_for_checkpoint_find_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"));
|
|
_wait_for_checkpoint_complete (info, NULL, add_error);
|
|
g_error_free (add_error);
|
|
}
|
|
}
|
|
|
|
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 void
|
|
get_permissions_reply (GObject *object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
NMManager *self;
|
|
NMManagerPrivate *priv;
|
|
gs_unref_variant GVariant *ret = NULL;
|
|
gs_unref_variant GVariant *permissions = NULL;
|
|
gs_free_error GError *error = NULL;
|
|
|
|
ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error);
|
|
if (!ret) {
|
|
if (nm_utils_error_is_cancelled (error, FALSE))
|
|
return;
|
|
} else {
|
|
g_variant_get (ret,
|
|
"(@a{ss})",
|
|
&permissions);
|
|
}
|
|
|
|
self = user_data;
|
|
priv = NM_MANAGER_GET_PRIVATE (self);
|
|
|
|
g_clear_object (&priv->perm_call_cancellable);
|
|
|
|
update_permissions (self, permissions);
|
|
}
|
|
|
|
static void
|
|
manager_recheck_permissions (NMDBusManager *_unused_proxy, gpointer user_data)
|
|
{
|
|
NMManager *self = NM_MANAGER (user_data);
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
|
const char *name_owner;
|
|
|
|
/* If a request is already pending, then we cancel it. We anyway
|
|
* need to make a new request, to be sure that we picked up on all
|
|
* the latest changes since the "CheckPermission" signal.
|
|
*
|
|
* However, we cannot accept more than one "GetPermissions" request
|
|
* in flight. That is because NetworkManager needs to ask PolicyKit
|
|
* for each permission individually, and some of these permission
|
|
* requests might be answered before others. Hence, the collection
|
|
* of all permissions is not taken at one point in time. Hence, when
|
|
* we would allow for multiple GetPermissions requests in-flight,
|
|
* we wouldn't know which response reflects the latest state. */
|
|
nm_clear_g_cancellable (&priv->perm_call_cancellable);
|
|
|
|
name_owner = _nm_object_get_dbus_name_owner (self);
|
|
if (!name_owner)
|
|
return;
|
|
|
|
priv->perm_call_cancellable = g_cancellable_new ();
|
|
g_dbus_connection_call (_nm_object_get_dbus_connection (self),
|
|
name_owner,
|
|
NM_DBUS_PATH,
|
|
NM_DBUS_INTERFACE,
|
|
"GetPermissions",
|
|
g_variant_new ("()"),
|
|
G_VARIANT_TYPE ("(a{ss})"),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
|
|
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 _nml_coerce_property_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 (GDBusConnection *dbus_connection,
|
|
const char *name_owner,
|
|
gboolean enable,
|
|
GError **error)
|
|
{
|
|
gs_unref_variant GVariant *ret = NULL;
|
|
|
|
ret = g_dbus_connection_call_sync (dbus_connection,
|
|
name_owner,
|
|
NM_DBUS_PATH,
|
|
NM_DBUS_INTERFACE,
|
|
"Enable",
|
|
g_variant_new ("(b)", enable),
|
|
G_VARIANT_TYPE ("()"),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
|
|
NULL,
|
|
error);
|
|
if (!ret) {
|
|
if (error)
|
|
g_dbus_error_strip_remote_error (*error);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
const char *
|
|
nm_manager_connectivity_check_get_uri (NMManager *manager)
|
|
{
|
|
return nmdbus_manager_get_connectivity_check_uri (NM_MANAGER_GET_PRIVATE (manager)->proxy);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void
|
|
_nm_manager_set_connectivity_hack (NMManager *manager,
|
|
guint32 connectivity)
|
|
{
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
|
|
|
if ((NMConnectivityState) connectivity != priv->connectivity) {
|
|
priv->connectivity = (NMConnectivityState) connectivity;
|
|
_notify (manager, PROP_CONNECTIVITY);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* 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;
|
|
guint i;
|
|
|
|
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)) {
|
|
return candidate;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static NMCheckpoint *
|
|
get_checkpoint_by_path (NMManager *manager, const char *object_path)
|
|
{
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
|
NMCheckpoint *candidate;
|
|
guint i;
|
|
|
|
for (i = 0; i < priv->checkpoints->len; i++) {
|
|
candidate = priv->checkpoints->pdata[i];
|
|
if (nm_streq (nm_object_get_path (NM_OBJECT (candidate)), object_path))
|
|
return candidate;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
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 enum {
|
|
ACTIVATE_TYPE_ACTIVATE_CONNECTION,
|
|
ACTIVATE_TYPE_ADD_AND_ACTIVATE_CONNECTION,
|
|
ACTIVATE_TYPE_ADD_AND_ACTIVATE_CONNECTION2,
|
|
} ActivateType;
|
|
|
|
typedef struct {
|
|
CList lst;
|
|
NMManager *manager;
|
|
GTask *task;
|
|
char *active_path;
|
|
GVariant *add_and_activate_output;
|
|
gulong cancelled_id;
|
|
ActivateType activate_type;
|
|
} ActivateInfo;
|
|
|
|
_NMActivateResult *
|
|
_nm_activate_result_new (NMActiveConnection *active,
|
|
GVariant *add_and_activate_output)
|
|
{
|
|
_NMActivateResult *r;
|
|
|
|
nm_assert (!add_and_activate_output || g_variant_is_of_type (add_and_activate_output, G_VARIANT_TYPE ("a{sv}")));
|
|
nm_assert (!add_and_activate_output || !g_variant_is_floating (add_and_activate_output));
|
|
|
|
r = g_slice_new (_NMActivateResult);
|
|
*r = (_NMActivateResult) {
|
|
.active = g_object_ref (active),
|
|
.add_and_activate_output = g_steal_pointer (&add_and_activate_output),
|
|
};
|
|
return r;
|
|
}
|
|
|
|
void
|
|
_nm_activate_result_free (_NMActivateResult *result)
|
|
{
|
|
nm_g_object_unref (result->active);
|
|
nm_g_variant_unref (result->add_and_activate_output);
|
|
g_slice_free (_NMActivateResult, result);
|
|
}
|
|
|
|
static void
|
|
activate_info_complete (ActivateInfo *info,
|
|
NMActiveConnection *active,
|
|
GError *error)
|
|
{
|
|
nm_assert (info);
|
|
nm_assert (info->task);
|
|
nm_assert (G_IS_TASK (info->task));
|
|
nm_assert ((!error) != (!active));
|
|
|
|
c_list_unlink_stale (&info->lst);
|
|
|
|
nm_clear_g_signal_handler (g_task_get_cancellable (info->task), &info->cancelled_id);
|
|
|
|
if (error)
|
|
g_task_return_error (info->task, error);
|
|
else {
|
|
g_task_return_pointer (info->task,
|
|
_nm_activate_result_new (active,
|
|
g_steal_pointer (&info->add_and_activate_output)),
|
|
(GDestroyNotify) _nm_activate_result_free);
|
|
}
|
|
|
|
nm_g_variant_unref (info->add_and_activate_output);
|
|
g_free (info->active_path);
|
|
g_object_unref (info->task);
|
|
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
|
|
_wait_for_active_connections_check (NMManager *self)
|
|
{
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
|
CList *iter;
|
|
NMActiveConnection *candidate;
|
|
const GPtrArray *devices;
|
|
NMDevice *device;
|
|
GDBusObjectManager *object_manager;
|
|
|
|
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.
|
|
*/
|
|
again:
|
|
c_list_for_each (iter, &priv->wait_for_active_connection_lst_head) {
|
|
ActivateInfo *info = c_list_entry (iter, ActivateInfo, lst);
|
|
gs_unref_object GDBusObject *dbus_obj = NULL;
|
|
|
|
nm_assert (info->active_path);
|
|
|
|
/* 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) {
|
|
activate_info_complete (info,
|
|
NULL,
|
|
g_error_new_literal (NM_CLIENT_ERROR,
|
|
NM_CLIENT_ERROR_OBJECT_CREATION_FAILED,
|
|
_("Active connection removed before it was initialized")));
|
|
goto again;
|
|
}
|
|
|
|
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);
|
|
goto again;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_wait_for_active_connection_cancelled_cb (GCancellable *cancellable,
|
|
gpointer user_data)
|
|
{
|
|
ActivateInfo *info = user_data;
|
|
gs_free_error GError *error = NULL;
|
|
|
|
if (!g_cancellable_set_error_if_cancelled (cancellable, &error))
|
|
return;
|
|
|
|
activate_info_complete (info, NULL, g_steal_pointer (&error));
|
|
}
|
|
|
|
void
|
|
nm_manager_wait_for_active_connection (NMManager *self,
|
|
const char *active_path,
|
|
const char *connection_path,
|
|
GVariant *add_and_activate_output_take,
|
|
GTask *task_take)
|
|
{
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
|
gs_unref_object GTask *task = task_take;
|
|
gs_unref_variant GVariant *add_and_activate_output = add_and_activate_output_take;
|
|
ActivateInfo *info;
|
|
GCancellable *cancellable;
|
|
|
|
nm_assert (NM_IS_MANAGER (self));
|
|
nm_assert (active_path);
|
|
nm_assert (G_IS_TASK (task));
|
|
|
|
/* FIXME: there is no timeout for how long we wait. But this entire
|
|
* code will be reworked, also that we have a suitable GMainContext
|
|
* where we can schedule the timeout (we shouldn't use g_main_context_default()). */
|
|
|
|
info = g_slice_new (ActivateInfo);
|
|
*info = (ActivateInfo) {
|
|
.manager = g_object_ref (self),
|
|
.task = g_steal_pointer (&task),
|
|
.active_path = g_strdup (active_path),
|
|
.add_and_activate_output = g_steal_pointer (&add_and_activate_output),
|
|
};
|
|
c_list_link_tail (&priv->wait_for_active_connection_lst_head, &info->lst);
|
|
|
|
cancellable = g_task_get_cancellable (info->task);
|
|
if (cancellable) {
|
|
info->cancelled_id = g_signal_connect (cancellable,
|
|
"cancelled",
|
|
G_CALLBACK (_wait_for_active_connection_cancelled_cb),
|
|
info);
|
|
if (g_cancellable_is_cancelled (cancellable)) {
|
|
_wait_for_active_connection_cancelled_cb (cancellable, info);
|
|
return;
|
|
}
|
|
}
|
|
|
|
_wait_for_active_connections_check (self);
|
|
}
|
|
|
|
static void
|
|
device_ac_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
|
|
{
|
|
_wait_for_active_connections_check (user_data);
|
|
}
|
|
|
|
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)
|
|
{
|
|
_wait_for_active_connections_check (user_data);
|
|
}
|
|
|
|
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);
|
|
_wait_for_active_connections_check (self);
|
|
}
|
|
|
|
static void
|
|
active_connection_removed (NMManager *self, NMActiveConnection *ac)
|
|
{
|
|
g_signal_handlers_disconnect_by_func (ac, G_CALLBACK (ac_devices_changed), self);
|
|
_wait_for_active_connections_check (self);
|
|
}
|
|
|
|
static void
|
|
checkpoint_added (NMManager *manager, NMCheckpoint *checkpoint)
|
|
{
|
|
CheckpointInfo *info;
|
|
|
|
info = _wait_for_checkpoint_find_info (manager, nm_object_get_path (NM_OBJECT (checkpoint)));
|
|
if (info)
|
|
_wait_for_checkpoint_complete (info, checkpoint, NULL);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
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;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
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
|
|
_wait_for_checkpoint_cancelled_cb (GCancellable *cancellable,
|
|
gpointer user_data)
|
|
{
|
|
CheckpointInfo *info = user_data;
|
|
gs_free_error GError *error = NULL;
|
|
|
|
if (!g_cancellable_set_error_if_cancelled (cancellable, &error))
|
|
return;
|
|
|
|
_wait_for_checkpoint_complete (info, NULL, g_steal_pointer (&error));
|
|
}
|
|
|
|
void
|
|
nm_manager_wait_for_checkpoint (NMManager *self,
|
|
const char *checkpoint_path,
|
|
GTask *task_take)
|
|
{
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
|
gs_unref_object GTask *task = task_take;
|
|
CheckpointInfo *info;
|
|
GCancellable *cancellable;
|
|
NMCheckpoint *checkpoint;
|
|
|
|
checkpoint = get_checkpoint_by_path (self, checkpoint_path);
|
|
if (checkpoint) {
|
|
g_task_return_pointer (task, g_object_ref (checkpoint), g_object_unref);
|
|
return;
|
|
}
|
|
|
|
/* FIXME: there is no timeout for how long we wait. But this entire
|
|
* code will be reworked, also that we have a suitable GMainContext
|
|
* where we can schedule the timeout (we shouldn't use g_main_context_default()). */
|
|
|
|
info = g_slice_new (CheckpointInfo);
|
|
*info = (CheckpointInfo) {
|
|
.self = g_object_ref (self),
|
|
.task = g_steal_pointer (&task),
|
|
.checkpoint_path = g_strdup (checkpoint_path),
|
|
};
|
|
c_list_link_tail (&priv->wait_for_checkpoint_lst_head, &info->lst);
|
|
|
|
cancellable = g_task_get_cancellable (info->task);
|
|
if (cancellable) {
|
|
info->cancelled_id = g_signal_connect (cancellable,
|
|
"cancelled",
|
|
G_CALLBACK (_wait_for_checkpoint_cancelled_cb),
|
|
info);
|
|
if (g_cancellable_is_cancelled (cancellable)) {
|
|
_wait_for_checkpoint_cancelled_cb (cancellable, info);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
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 *self = NM_MANAGER (initable);
|
|
gs_unref_variant GVariant *permissions = NULL;
|
|
const char *name_owner;
|
|
|
|
if (!nm_manager_parent_initable_iface->init (initable, cancellable, error))
|
|
g_return_val_if_reached (FALSE);
|
|
|
|
name_owner = _nm_object_get_dbus_name_owner (self);
|
|
if (name_owner) {
|
|
gs_unref_variant GVariant *ret = NULL;
|
|
|
|
ret = g_dbus_connection_call_sync (_nm_object_get_dbus_connection (self),
|
|
name_owner,
|
|
NM_DBUS_PATH,
|
|
NM_DBUS_INTERFACE,
|
|
"GetPermissions",
|
|
g_variant_new ("()"),
|
|
G_VARIANT_TYPE ("(a{ss})"),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
|
|
cancellable,
|
|
NULL);
|
|
if (ret) {
|
|
g_variant_get (ret,
|
|
"(@a{ss})",
|
|
&permissions);
|
|
}
|
|
}
|
|
update_permissions (self, permissions);
|
|
|
|
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_parent_inited (GObject *source, GAsyncResult *result, gpointer user_data)
|
|
{
|
|
NMManagerInitData *init_data = user_data;
|
|
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;
|
|
}
|
|
|
|
manager_recheck_permissions (NULL, 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);
|
|
if (cancellable)
|
|
g_simple_async_result_set_check_cancellable (init_data->result, cancellable);
|
|
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_assert (c_list_is_empty (&priv->wait_for_active_connection_lst_head));
|
|
nm_assert (c_list_is_empty (&priv->wait_for_checkpoint_lst_head));
|
|
|
|
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;
|
|
}
|
|
|
|
nm_clear_pointer (&priv->checkpoints, g_ptr_array_unref);
|
|
|
|
free_active_connections (manager);
|
|
g_clear_object (&priv->primary_connection);
|
|
g_clear_object (&priv->activating_connection);
|
|
|
|
g_clear_object (&priv->proxy);
|
|
|
|
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;
|
|
const char *name_owner;
|
|
|
|
switch (prop_id) {
|
|
case PROP_NETWORKING_ENABLED:
|
|
b = g_value_get_boolean (value);
|
|
if (priv->networking_enabled != b) {
|
|
if ((name_owner = _nm_object_get_dbus_name_owner (object))) {
|
|
_nm_manager_networking_set_enabled (_nm_object_get_dbus_connection (object),
|
|
name_owner,
|
|
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));
|
|
|
|
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;
|
|
|
|
obj_properties[PROP_VERSION] =
|
|
g_param_spec_string (NM_MANAGER_VERSION, "", "",
|
|
NULL,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_STATE] =
|
|
g_param_spec_enum (NM_CLIENT_STATE, "", "",
|
|
NM_TYPE_STATE,
|
|
NM_STATE_UNKNOWN,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_STARTUP] =
|
|
g_param_spec_boolean (NM_MANAGER_STARTUP, "", "",
|
|
FALSE,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_NETWORKING_ENABLED] =
|
|
g_param_spec_boolean (NM_MANAGER_NETWORKING_ENABLED, "", "",
|
|
TRUE,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_WIRELESS_ENABLED] =
|
|
g_param_spec_boolean (NM_MANAGER_WIRELESS_ENABLED, "", "",
|
|
FALSE,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_WIRELESS_HARDWARE_ENABLED] =
|
|
g_param_spec_boolean (NM_MANAGER_WIRELESS_HARDWARE_ENABLED, "", "",
|
|
TRUE,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_WWAN_ENABLED] =
|
|
g_param_spec_boolean (NM_MANAGER_WWAN_ENABLED, "", "",
|
|
FALSE,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_WWAN_HARDWARE_ENABLED] =
|
|
g_param_spec_boolean (NM_MANAGER_WWAN_HARDWARE_ENABLED, "", "",
|
|
FALSE,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_WIMAX_ENABLED] =
|
|
g_param_spec_boolean (NM_MANAGER_WIMAX_ENABLED, "", "",
|
|
FALSE,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_WIMAX_HARDWARE_ENABLED] =
|
|
g_param_spec_boolean (NM_MANAGER_WIMAX_HARDWARE_ENABLED, "", "",
|
|
FALSE,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_ACTIVE_CONNECTIONS] =
|
|
g_param_spec_boxed (NM_MANAGER_ACTIVE_CONNECTIONS, "", "",
|
|
G_TYPE_PTR_ARRAY,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_CONNECTIVITY] =
|
|
g_param_spec_enum (NM_CLIENT_CONNECTIVITY, "", "",
|
|
NM_TYPE_CONNECTIVITY_STATE,
|
|
NM_CONNECTIVITY_UNKNOWN,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_CONNECTIVITY_CHECK_AVAILABLE] =
|
|
g_param_spec_boolean (NM_MANAGER_CONNECTIVITY_CHECK_AVAILABLE, "", "",
|
|
FALSE,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_CONNECTIVITY_CHECK_ENABLED] =
|
|
g_param_spec_boolean (NM_MANAGER_CONNECTIVITY_CHECK_ENABLED, "", "",
|
|
FALSE,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_PRIMARY_CONNECTION] =
|
|
g_param_spec_object (NM_MANAGER_PRIMARY_CONNECTION, "", "",
|
|
NM_TYPE_ACTIVE_CONNECTION,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_ACTIVATING_CONNECTION] =
|
|
g_param_spec_object (NM_MANAGER_ACTIVATING_CONNECTION, "", "",
|
|
NM_TYPE_ACTIVE_CONNECTION,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[PROP_DEVICES] =
|
|
g_param_spec_boxed (NM_MANAGER_DEVICES, "", "",
|
|
G_TYPE_PTR_ARRAY,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_properties[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
|
|
**/
|
|
obj_properties[PROP_METERED] =
|
|
g_param_spec_uint (NM_MANAGER_METERED, "", "",
|
|
0, G_MAXUINT32, NM_METERED_UNKNOWN,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
obj_properties[PROP_ALL_DEVICES] =
|
|
g_param_spec_boxed (NM_MANAGER_ALL_DEVICES, "", "",
|
|
G_TYPE_PTR_ARRAY,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
|
|
|
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;
|
|
}
|