mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-07 06:40:18 +01:00
Convert to using interface indexes as the primary method of identifying devices inside NetworkManager. Indexes are (?) stable, but devices can be renamed at any time. Device object paths now refer to the device index rather than the name, and you can map those two manually if you like by looking in the /sys/class/net/<name>/ifindex file. Also moves most netlink-related code to nm-netlink.c, and cleans up nm-netlink-monitor.c to use interface indexes rather than names. git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2731 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
552 lines
13 KiB
C
552 lines
13 KiB
C
/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
|
|
|
|
#include <string.h>
|
|
|
|
#include "nm-manager.h"
|
|
#include "nm-utils.h"
|
|
#include "nm-dbus-manager.h"
|
|
#include "nm-device-interface.h"
|
|
#include "nm-device-802-11-wireless.h"
|
|
#include "NetworkManagerSystem.h"
|
|
#include "NetworkManagerDbus.h"
|
|
|
|
static gboolean impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err);
|
|
static gboolean impl_manager_sleep (NMManager *manager, gboolean sleep, GError **err);
|
|
|
|
/* Legacy 0.6 compatibility interface */
|
|
|
|
static gboolean impl_manager_legacy_sleep (NMManager *manager, GError **err);
|
|
static gboolean impl_manager_legacy_wake (NMManager *manager, GError **err);
|
|
static gboolean impl_manager_legacy_state (NMManager *manager, GError **err);
|
|
|
|
#include "nm-manager-glue.h"
|
|
|
|
static void nm_manager_connections_destroy (NMManager *manager);
|
|
static void manager_state_changed (NMManager *manager);
|
|
static void manager_set_wireless_enabled (NMManager *manager, gboolean enabled);
|
|
|
|
typedef struct {
|
|
GSList *devices;
|
|
GSList *connections;
|
|
gboolean wireless_enabled;
|
|
gboolean sleeping;
|
|
} NMManagerPrivate;
|
|
|
|
#define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate))
|
|
|
|
G_DEFINE_TYPE (NMManager, nm_manager, G_TYPE_OBJECT)
|
|
|
|
enum {
|
|
DEVICE_ADDED,
|
|
DEVICE_REMOVED,
|
|
STATE_CHANGE,
|
|
CONNECTION_ADDED,
|
|
CONNECTION_REMOVED,
|
|
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
static guint signals[LAST_SIGNAL] = { 0 };
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_STATE,
|
|
PROP_WIRELESS_ENABLED,
|
|
|
|
LAST_PROP
|
|
};
|
|
|
|
static void
|
|
nm_manager_init (NMManager *manager)
|
|
{
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
|
|
|
priv->wireless_enabled = TRUE;
|
|
priv->sleeping = FALSE;
|
|
}
|
|
|
|
static void
|
|
finalize (GObject *object)
|
|
{
|
|
NMManager *manager = NM_MANAGER (object);
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
|
|
|
nm_manager_connections_destroy (manager);
|
|
|
|
while (g_slist_length (priv->devices))
|
|
nm_manager_remove_device (manager, NM_DEVICE (priv->devices->data));
|
|
|
|
G_OBJECT_CLASS (nm_manager_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
set_property (GObject *object, guint prop_id,
|
|
const GValue *value, GParamSpec *pspec)
|
|
{
|
|
switch (prop_id) {
|
|
case PROP_WIRELESS_ENABLED:
|
|
manager_set_wireless_enabled (NM_MANAGER (object), g_value_get_boolean (value));
|
|
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)
|
|
{
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object);
|
|
|
|
switch (prop_id) {
|
|
case PROP_STATE:
|
|
g_value_set_uint (value, nm_manager_get_state (NM_MANAGER (object)));
|
|
break;
|
|
case PROP_WIRELESS_ENABLED:
|
|
g_value_set_boolean (value, priv->wireless_enabled);
|
|
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);
|
|
|
|
g_type_class_add_private (manager_class, sizeof (NMManagerPrivate));
|
|
|
|
/* virtual methods */
|
|
object_class->set_property = set_property;
|
|
object_class->get_property = get_property;
|
|
object_class->finalize = finalize;
|
|
|
|
/* properties */
|
|
g_object_class_install_property
|
|
(object_class, PROP_STATE,
|
|
g_param_spec_uint (NM_MANAGER_STATE,
|
|
"State",
|
|
"Current state",
|
|
0, 5, 0, /* FIXME */
|
|
G_PARAM_READABLE));
|
|
|
|
g_object_class_install_property
|
|
(object_class, PROP_WIRELESS_ENABLED,
|
|
g_param_spec_boolean (NM_MANAGER_WIRELESS_ENABLED,
|
|
"WirelessEnabled",
|
|
"Is wireless enabled",
|
|
TRUE,
|
|
G_PARAM_READWRITE));
|
|
|
|
/* 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,
|
|
g_cclosure_marshal_VOID__OBJECT,
|
|
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,
|
|
g_cclosure_marshal_VOID__OBJECT,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_OBJECT);
|
|
|
|
signals[STATE_CHANGE] =
|
|
g_signal_new ("state-change",
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (NMManagerClass, state_change),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__UINT,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_UINT);
|
|
|
|
signals[CONNECTION_ADDED] =
|
|
g_signal_new ("connection-added",
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (NMManagerClass, connection_added),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__POINTER,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_POINTER);
|
|
|
|
signals[CONNECTION_REMOVED] =
|
|
g_signal_new ("connection-removed",
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (NMManagerClass, connection_removed),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__POINTER,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_POINTER);
|
|
|
|
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (manager_class),
|
|
&dbus_glib_nm_manager_object_info);
|
|
}
|
|
|
|
NMManager *
|
|
nm_manager_new (void)
|
|
{
|
|
GObject *object;
|
|
DBusGConnection *connection;
|
|
|
|
object = g_object_new (NM_TYPE_MANAGER, NULL);
|
|
|
|
connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ());
|
|
dbus_g_connection_register_g_object (connection,
|
|
NM_DBUS_PATH,
|
|
object);
|
|
|
|
return NM_MANAGER (object);
|
|
}
|
|
|
|
static void
|
|
nm_manager_connections_destroy (NMManager *manager)
|
|
{
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
|
|
|
g_slist_foreach (priv->connections, (GFunc) nm_connection_destroy, NULL);
|
|
g_slist_free (priv->connections);
|
|
priv->connections = NULL;
|
|
}
|
|
|
|
static void
|
|
manager_state_changed (NMManager *manager)
|
|
{
|
|
g_signal_emit (manager, signals[STATE_CHANGE], 0, nm_manager_get_state (manager));
|
|
}
|
|
|
|
static void
|
|
manager_set_wireless_enabled (NMManager *manager, gboolean enabled)
|
|
{
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
|
GSList *iter;
|
|
|
|
if (priv->wireless_enabled == enabled)
|
|
return;
|
|
|
|
priv->wireless_enabled = enabled;
|
|
|
|
/* Tear down all wireless devices */
|
|
for (iter = priv->devices; iter; iter = iter->next) {
|
|
if (NM_IS_DEVICE_802_11_WIRELESS (iter->data)) {
|
|
if (enabled)
|
|
nm_device_bring_up (NM_DEVICE (iter->data), FALSE);
|
|
else
|
|
nm_device_bring_down (NM_DEVICE (iter->data), FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
manager_device_added (NMManager *manager, NMDevice *device)
|
|
{
|
|
g_signal_emit (manager, signals[DEVICE_ADDED], 0, device);
|
|
}
|
|
|
|
static void
|
|
manager_device_state_changed (NMDevice *device, NMDeviceState state, gpointer user_data)
|
|
{
|
|
NMManager *manager = NM_MANAGER (user_data);
|
|
|
|
/* Only these state changes can modify the manager state */
|
|
switch (state) {
|
|
case NM_DEVICE_STATE_ACTIVATED:
|
|
case NM_DEVICE_STATE_FAILED:
|
|
case NM_DEVICE_STATE_CANCELLED:
|
|
case NM_DEVICE_STATE_DOWN:
|
|
case NM_DEVICE_STATE_DISCONNECTED:
|
|
manager_state_changed (manager);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
nm_manager_add_device (NMManager *manager, NMDevice *device)
|
|
{
|
|
NMManagerPrivate *priv;
|
|
|
|
g_return_if_fail (NM_IS_MANAGER (manager));
|
|
g_return_if_fail (NM_IS_DEVICE (device));
|
|
|
|
priv = NM_MANAGER_GET_PRIVATE (manager);
|
|
|
|
priv->devices = g_slist_append (priv->devices, g_object_ref (device));
|
|
|
|
g_signal_connect (device, "state-changed",
|
|
G_CALLBACK (manager_device_state_changed),
|
|
manager);
|
|
|
|
if (!priv->sleeping) {
|
|
if (!NM_IS_DEVICE_802_11_WIRELESS (device) || priv->wireless_enabled)
|
|
nm_device_bring_up (device, TRUE);
|
|
}
|
|
|
|
nm_device_interface_deactivate (NM_DEVICE_INTERFACE (device));
|
|
|
|
manager_device_added (manager, device);
|
|
}
|
|
|
|
static void
|
|
manager_device_removed (NMManager *manager, NMDevice *device)
|
|
{
|
|
g_signal_emit (manager, signals[DEVICE_REMOVED], 0, device);
|
|
}
|
|
|
|
void
|
|
nm_manager_remove_device (NMManager *manager, NMDevice *device)
|
|
{
|
|
NMManagerPrivate *priv;
|
|
GSList *iter;
|
|
|
|
g_return_if_fail (NM_IS_MANAGER (manager));
|
|
g_return_if_fail (NM_IS_DEVICE (device));
|
|
|
|
priv = NM_MANAGER_GET_PRIVATE (manager);
|
|
|
|
for (iter = priv->devices; iter; iter = iter->next) {
|
|
if (iter->data == device) {
|
|
priv->devices = g_slist_delete_link (priv->devices, iter);
|
|
|
|
nm_device_bring_down (device, FALSE);
|
|
|
|
g_signal_handlers_disconnect_by_func (device, manager_device_state_changed, manager);
|
|
|
|
manager_device_removed (manager, device);
|
|
g_object_unref (device);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
GSList *
|
|
nm_manager_get_devices (NMManager *manager)
|
|
{
|
|
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
|
|
|
|
return NM_MANAGER_GET_PRIVATE (manager)->devices;
|
|
}
|
|
|
|
static gboolean
|
|
impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err)
|
|
{
|
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
|
GSList *iter;
|
|
|
|
*devices = g_ptr_array_sized_new (g_slist_length (priv->devices));
|
|
|
|
for (iter = priv->devices; iter; iter = iter->next)
|
|
g_ptr_array_add (*devices, nm_device_get_dbus_path (NM_DEVICE (iter->data)));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
NMDevice *
|
|
nm_manager_get_device_by_iface (NMManager *manager, const char *iface)
|
|
{
|
|
GSList *iter;
|
|
|
|
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
|
|
|
|
for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
|
|
NMDevice *device = NM_DEVICE (iter->data);
|
|
|
|
if (!strcmp (nm_device_get_iface (device), iface))
|
|
return device;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
NMDevice *
|
|
nm_manager_get_device_by_index (NMManager *manager, int idx)
|
|
{
|
|
GSList *iter;
|
|
|
|
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
|
|
|
|
for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
|
|
NMDevice *device = NM_DEVICE (iter->data);
|
|
|
|
if (nm_device_get_index (device) == idx)
|
|
return device;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
NMDevice *
|
|
nm_manager_get_device_by_udi (NMManager *manager, const char *udi)
|
|
{
|
|
GSList *iter;
|
|
|
|
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
|
|
|
|
for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
|
|
NMDevice *device = NM_DEVICE (iter->data);
|
|
|
|
if (!strcmp (nm_device_get_udi (device), udi))
|
|
return device;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
NMState
|
|
nm_manager_get_state (NMManager *manager)
|
|
{
|
|
NMManagerPrivate *priv;
|
|
GSList *iter;
|
|
NMState state = NM_STATE_DISCONNECTED;
|
|
|
|
g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN);
|
|
|
|
priv = NM_MANAGER_GET_PRIVATE (manager);
|
|
|
|
if (priv->sleeping)
|
|
return NM_STATE_ASLEEP;
|
|
|
|
for (iter = priv->devices; iter; iter = iter->next) {
|
|
NMDevice *dev = NM_DEVICE (iter->data);
|
|
|
|
if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED)
|
|
return NM_STATE_CONNECTED;
|
|
|
|
if (nm_device_is_activating (dev))
|
|
state = NM_STATE_CONNECTING;
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
gboolean
|
|
nm_manager_wireless_enabled (NMManager *manager)
|
|
{
|
|
gboolean enabled;
|
|
|
|
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
|
|
|
|
g_object_get (manager, NM_MANAGER_WIRELESS_ENABLED, &enabled, NULL);
|
|
|
|
return enabled;
|
|
}
|
|
|
|
void
|
|
nm_manager_sleep (NMManager *manager, gboolean sleep)
|
|
{
|
|
NMManagerPrivate *priv;
|
|
|
|
g_return_if_fail (NM_IS_MANAGER (manager));
|
|
|
|
priv = NM_MANAGER_GET_PRIVATE (manager);
|
|
|
|
if (priv->sleeping == sleep)
|
|
return;
|
|
|
|
priv->sleeping = sleep;
|
|
|
|
if (sleep) {
|
|
GSList *iter;
|
|
|
|
nm_info ("Going to sleep.");
|
|
|
|
/* Just deactivate and down all devices from the device list,
|
|
* we'll remove them in 'wake' for speed's sake.
|
|
*/
|
|
for (iter = priv->devices; iter; iter = iter->next)
|
|
nm_device_bring_down (NM_DEVICE (iter->data), FALSE);
|
|
} else {
|
|
nm_info ("Waking up from sleep.");
|
|
|
|
while (g_slist_length (priv->devices))
|
|
nm_manager_remove_device (manager, NM_DEVICE (priv->devices->data));
|
|
|
|
priv->devices = NULL;
|
|
}
|
|
|
|
manager_state_changed (manager);
|
|
}
|
|
|
|
static gboolean
|
|
impl_manager_sleep (NMManager *manager, gboolean sleep, GError **err)
|
|
{
|
|
nm_manager_sleep (manager, sleep);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
NMDevice *
|
|
nm_manager_get_active_device (NMManager *manager)
|
|
{
|
|
GSList *iter;
|
|
|
|
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
|
|
|
|
for (iter = nm_manager_get_devices (manager); iter; iter = iter->next) {
|
|
NMDevice *dev = NM_DEVICE (iter->data);
|
|
|
|
if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED)
|
|
return dev;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* Legacy 0.6 compatibility interface */
|
|
|
|
static gboolean
|
|
impl_manager_legacy_sleep (NMManager *manager, GError **err)
|
|
{
|
|
return impl_manager_sleep (manager, TRUE, err);
|
|
}
|
|
|
|
static gboolean
|
|
impl_manager_legacy_wake (NMManager *manager, GError **err)
|
|
{
|
|
return impl_manager_sleep (manager, FALSE, err);
|
|
}
|
|
|
|
static gboolean
|
|
impl_manager_legacy_state (NMManager *manager, GError **err)
|
|
{
|
|
return nm_manager_get_state (manager);
|
|
}
|
|
|
|
|
|
/* Connections */
|
|
|
|
GSList *
|
|
nm_manager_get_connections (NMManager *manager)
|
|
{
|
|
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
|
|
|
|
return NM_MANAGER_GET_PRIVATE (manager)->connections;
|
|
}
|
|
|
|
void
|
|
nm_manager_update_connections (NMManager *manager,
|
|
GSList *connections,
|
|
gboolean reset)
|
|
{
|
|
g_return_if_fail (NM_IS_MANAGER (manager));
|
|
|
|
if (reset)
|
|
nm_manager_connections_destroy (manager);
|
|
|
|
|
|
}
|