core: merge branch 'dcbw/devices-for-all'

https://bugzilla.gnome.org/show_bug.cgi?id=737458
This commit is contained in:
Thomas Haller 2015-12-04 12:23:27 +01:00
commit 153aba0662
44 changed files with 1843 additions and 616 deletions

View file

@ -0,0 +1,41 @@
#!/usr/bin/env python
# vim: ft=python ts=4 sts=4 sw=4 et ai
# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright (C) 2014 Red Hat, Inc.
#
# This example lists all devices, both real and placeholder ones
from gi.repository import GLib, NM
if __name__ == "__main__":
client = NM.Client.new(None)
devices = client.get_all_devices()
print "Real devices"
print "------------"
for d in devices:
if d.is_real():
print "%s (%s): %s" % (d.get_iface(), d.get_type_description(), d.get_state())
print "\nUnrealized/placeholder devices"
print "------------------------------"
for d in devices:
if not d.is_real():
print "%s (%s): %s" % (d.get_iface(), d.get_type_description(), d.get_state())

View file

@ -161,6 +161,13 @@
LLDP TLV names to variant boxed values.
</tp:docstring>
</property>
<property name="Real" type="b" access="read">
<tp:docstring>
True if the device exists, or False for placeholder devices that
do not yet exist but could be automatically created by NetworkManager
if one of their AvailableConnections was activated.
</tp:docstring>
</property>
<method name="Disconnect">
<tp:docstring>

View file

@ -6,11 +6,27 @@
<method name="GetDevices">
<tp:docstring>
Get the list of network devices.
Get the list of realized network devices.
</tp:docstring>
<arg name="devices" type="ao" direction="out">
<tp:docstring>
List of object paths of network devices known to the system.
List of object paths of network devices known to the system. This
list does not include device placeholders (see GetAllDevices()).
</tp:docstring>
</arg>
</method>
<method name="GetAllDevices">
<tp:docstring>
Get the list of all network devices.
</tp:docstring>
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_manager_get_all_devices"/>
<arg name="devices" type="ao" direction="out">
<tp:docstring>
List of object paths of network devices and device placeholders
(eg, devices that do not yet exist but which can be automatically
created by NetworkManager if one of their AvailableConnections
was activated).
</tp:docstring>
</arg>
</method>
@ -249,7 +265,18 @@
<property name="Devices" type="ao" access="read">
<tp:docstring>
The list of network devices/interfaces NetworkManager knows about.
The list of realized network devices. Realized devices are those which
have backing resources (eg from the kernel or a management daemon like
ModemManager, teamd, etc).
</tp:docstring>
</property>
<property name="AllDevices" type="ao" access="read">
<tp:docstring>
The list of both realized and un-realized network devices. Un-realized
devices are software devices which do not yet have backing resources,
but for which backing resources can be created if the device is
activated.
</tp:docstring>
</property>

View file

@ -47,6 +47,7 @@ global:
nm_client_error_quark;
nm_client_get_activating_connection;
nm_client_get_active_connections;
nm_client_get_all_devices;
nm_client_get_connectivity;
nm_client_get_device_by_iface;
nm_client_get_device_by_path;
@ -158,6 +159,7 @@ global:
nm_device_infiniband_get_hw_address;
nm_device_infiniband_get_type;
nm_device_infiniband_new;
nm_device_is_real;
nm_device_is_software;
nm_device_modem_error_get_type;
nm_device_modem_error_quark;

View file

@ -59,6 +59,7 @@ typedef struct {
NMState state;
gboolean startup;
GPtrArray *devices;
GPtrArray *all_devices;
GPtrArray *active_connections;
NMConnectivityState connectivity;
NMActiveConnection *primary_connection;
@ -101,6 +102,7 @@ enum {
PROP_PRIMARY_CONNECTION,
PROP_ACTIVATING_CONNECTION,
PROP_DEVICES,
PROP_ALL_DEVICES,
LAST_PROP
};
@ -108,6 +110,8 @@ enum {
enum {
DEVICE_ADDED,
DEVICE_REMOVED,
ANY_DEVICE_ADDED,
ANY_DEVICE_REMOVED,
PERMISSION_CHANGED,
LAST_SIGNAL
@ -160,8 +164,8 @@ poke_wireless_devices_with_rf_status (NMClient *client)
NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
int i;
for (i = 0; priv->devices && (i < priv->devices->len); i++) {
NMDevice *device = g_ptr_array_index (priv->devices, i);
for (i = 0; priv->all_devices && (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);
@ -194,6 +198,7 @@ register_properties (NMClient *client)
{ NM_CLIENT_PRIMARY_CONNECTION, &priv->primary_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
{ NM_CLIENT_ACTIVATING_CONNECTION, &priv->activating_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
{ NM_CLIENT_DEVICES, &priv->devices, NULL, NM_TYPE_DEVICE, "device" },
{ NM_CLIENT_ALL_DEVICES, &priv->all_devices, NULL, NM_TYPE_DEVICE, "any-device" },
{ NULL },
};
@ -378,6 +383,34 @@ nm_client_get_devices (NMClient *client)
return handle_ptr_array_return (NM_CLIENT_GET_PRIVATE (client)->devices);
}
/**
* nm_client_get_all_devices:
* @client: a #NMClient
*
* Gets both real devices and device placeholders (eg, software devices which
* do not currently exist, but could be created automatically by NetworkManager
* if one of their NMDevice::ActivatableConnections was activated). Use
* nm_device_is_real() to determine whether each device is a real device or
* a placeholder.
*
* Use nm_device_get_type() or the NM_IS_DEVICE_XXXX() functions to determine
* what kind of device each member of the returned array is, and then you may
* use device-specific methods such as nm_device_ethernet_get_hw_address().
*
* Returns: (transfer none) (element-type NMDevice): a #GPtrArray
* containing all the #NMDevices. The returned array is owned by the
* #NMClient object and should not be modified.
*
* Since: 1.2
**/
const GPtrArray *
nm_client_get_all_devices (NMClient *client)
{
g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
return NM_CLIENT_GET_PRIVATE (client)->all_devices;
}
/**
* nm_client_get_device_by_path:
* @client: a #NMClient
@ -1291,25 +1324,55 @@ nm_client_get_activating_connection (NMClient *client)
/****************************************************************/
static void
free_devices (NMClient *client, gboolean emit_signals)
free_devices (NMClient *client, gboolean in_dispose)
{
NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
GPtrArray *devices;
NMDevice *device;
int i;
gs_unref_ptrarray GPtrArray *real_devices = NULL;
gs_unref_ptrarray GPtrArray *all_devices = NULL;
GPtrArray *devices = NULL;
guint i, j;
if (!priv->devices)
return;
real_devices = priv->devices;
all_devices = priv->all_devices;
devices = priv->devices;
priv->devices = NULL;
for (i = 0; i < devices->len; i++) {
device = devices->pdata[i];
if (emit_signals)
g_signal_emit (client, signals[DEVICE_REMOVED], 0, device);
g_object_unref (device);
if (in_dispose) {
priv->devices = NULL;
priv->all_devices = NULL;
} else {
priv->devices = g_ptr_array_new ();
priv->all_devices = g_ptr_array_new ();
}
if (all_devices && all_devices->len > 0)
devices = all_devices;
else if (devices && devices->len > 0)
devices = real_devices;
if (real_devices && devices != real_devices) {
for (i = 0; i < real_devices->len; i++) {
NMDevice *d = real_devices->pdata[i];
if (all_devices) {
for (j = 0; j < all_devices->len; j++) {
if (d == all_devices->pdata[j])
goto next;
}
}
if (!in_dispose)
g_signal_emit (client, signals[DEVICE_REMOVED], 0, d);
next:
g_object_unref (d);
}
}
if (devices) {
for (i = 0; i < devices->len; i++) {
NMDevice *d = devices->pdata[i];
if (!in_dispose)
g_signal_emit (client, signals[DEVICE_REMOVED], 0, d);
g_object_unref (d);
}
}
g_ptr_array_free (devices, TRUE);
}
static void
@ -1382,7 +1445,7 @@ proxy_name_owner_changed (DBusGProxy *proxy,
_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
_nm_object_suppress_property_updates (NM_OBJECT (client), TRUE);
poke_wireless_devices_with_rf_status (client);
free_devices (client, TRUE);
free_devices (client, FALSE);
free_active_connections (client, TRUE);
update_permissions (client, NULL);
priv->wireless_enabled = FALSE;
@ -1980,7 +2043,7 @@ dispose (GObject *object)
g_clear_object (&priv->client_proxy);
g_clear_object (&priv->bus_proxy);
free_devices (client, FALSE);
free_devices (client, TRUE);
free_active_connections (client, FALSE);
g_clear_object (&priv->primary_connection);
g_clear_object (&priv->activating_connection);
@ -2106,6 +2169,9 @@ get_property (GObject *object,
case PROP_DEVICES:
g_value_set_boxed (value, nm_client_get_devices (self));
break;
case PROP_ALL_DEVICES:
g_value_set_boxed (value, nm_client_get_all_devices (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -2323,7 +2389,7 @@ nm_client_class_init (NMClientClass *client_class)
/**
* NMClient:devices:
*
* List of known network devices.
* List of real network devices. Does not include placeholder devices.
*
* Since: 0.9.10
**/
@ -2334,6 +2400,20 @@ nm_client_class_init (NMClientClass *client_class)
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMClient:all-devices:
*
* List of both real devices and device placeholders.
*
* Since: 1.2
**/
g_object_class_install_property
(object_class, PROP_ALL_DEVICES,
g_param_spec_boxed (NM_CLIENT_ALL_DEVICES, "", "",
NM_TYPE_OBJECT_ARRAY,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/* signals */
/**
@ -2341,7 +2421,8 @@ nm_client_class_init (NMClientClass *client_class)
* @client: the client that received the signal
* @device: (type NMDevice): the new device
*
* Notifies that a #NMDevice is added.
* Notifies that a #NMDevice is added. This signal is not emitted for
* placeholder devices.
**/
signals[DEVICE_ADDED] =
g_signal_new ("device-added",
@ -2357,7 +2438,8 @@ nm_client_class_init (NMClientClass *client_class)
* @client: the client that received the signal
* @device: (type NMDevice): the removed device
*
* Notifies that a #NMDevice is removed.
* Notifies that a #NMDevice is removed. This signal is not emitted for
* placeholder devices.
**/
signals[DEVICE_REMOVED] =
g_signal_new ("device-removed",
@ -2368,6 +2450,38 @@ nm_client_class_init (NMClientClass *client_class)
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
/**
* NMClient::any-device-added:
* @client: the client that received the signal
* @device: (type NMDevice): the new device
*
* Notifies that a #NMDevice is added. This signal is emitted for both
* regular devices and placeholder devices.
**/
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);
/**
* NMClient::any-device-removed:
* @client: the client that received the signal
* @device: (type NMDevice): the removed device
*
* Notifies that a #NMDevice is removed. This signal is emitted for both
* regular devices and placeholder devices.
**/
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);
/**
* NMClient::permission-changed:
* @client: the client that received the signal

View file

@ -57,6 +57,7 @@ G_BEGIN_DECLS
#define NM_CLIENT_PRIMARY_CONNECTION "primary-connection"
#define NM_CLIENT_ACTIVATING_CONNECTION "activating-connection"
#define NM_CLIENT_DEVICES "devices"
#define NM_CLIENT_ALL_DEVICES "all-devices"
/**
* NMClientPermission:
@ -175,6 +176,8 @@ NMClient *nm_client_new_finish (GAsyncResult *result,
GError **error);
const GPtrArray *nm_client_get_devices (NMClient *client);
NM_AVAILABLE_IN_1_2
const GPtrArray *nm_client_get_all_devices(NMClient *client);
NMDevice *nm_client_get_device_by_path (NMClient *client, const char *object_path);
NMDevice *nm_client_get_device_by_iface (NMClient *client, const char *iface);

View file

@ -79,6 +79,7 @@ typedef struct {
char *firmware_version;
char *type_description;
NMDeviceCapabilities capabilities;
gboolean real;
gboolean managed;
gboolean firmware_missing;
gboolean autoconnect;
@ -110,6 +111,7 @@ enum {
PROP_DRIVER_VERSION,
PROP_FIRMWARE_VERSION,
PROP_CAPABILITIES,
PROP_REAL,
PROP_MANAGED,
PROP_AUTOCONNECT,
PROP_FIRMWARE_MISSING,
@ -196,6 +198,7 @@ register_properties (NMDevice *device)
{ NM_DEVICE_DRIVER_VERSION, &priv->driver_version },
{ NM_DEVICE_FIRMWARE_VERSION, &priv->firmware_version },
{ NM_DEVICE_CAPABILITIES, &priv->capabilities },
{ NM_DEVICE_REAL, &priv->real },
{ NM_DEVICE_MANAGED, &priv->managed },
{ NM_DEVICE_AUTOCONNECT, &priv->autoconnect },
{ NM_DEVICE_FIRMWARE_MISSING, &priv->firmware_missing },
@ -446,6 +449,9 @@ get_property (GObject *object,
case PROP_CAPABILITIES:
g_value_set_uint (value, nm_device_get_capabilities (device));
break;
case PROP_REAL:
g_value_set_boolean (value, nm_device_is_real (device));
break;
case PROP_MANAGED:
g_value_set_boolean (value, nm_device_get_managed (device));
break;
@ -652,6 +658,22 @@ nm_device_class_init (NMDeviceClass *device_class)
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMDevice:real:
*
* Whether the device is real or is a placeholder device that could
* be created automatically by NetworkManager if one of its
* #NMDevice:available-connections was activated.
*
* Since: 1.2
**/
g_object_class_install_property
(object_class, PROP_REAL,
g_param_spec_boolean (NM_DEVICE_REAL, "", "",
FALSE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMDevice:managed:
*
@ -2105,6 +2127,25 @@ nm_device_get_mtu (NMDevice *device)
return NM_DEVICE_GET_PRIVATE (device)->mtu;
}
/**
* nm_device_is_real:
* @device: a #NMDevice
*
* Returns: %TRUE if the device exists, or %FALSE if it is a placeholder device
* that could be automatically created by NetworkManager if one of its
* #NMDevice:available-connections was activated.
*
* Since: 1.2
**/
gboolean
nm_device_is_real (NMDevice *device)
{
g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
_nm_object_ensure_inited (NM_OBJECT (device));
return NM_DEVICE_GET_PRIVATE (device)->real;
}
/**
* nm_device_is_software:
* @device: a #NMDevice

View file

@ -66,6 +66,7 @@ GQuark nm_device_error_quark (void);
#define NM_DEVICE_DRIVER_VERSION "driver-version"
#define NM_DEVICE_FIRMWARE_VERSION "firmware-version"
#define NM_DEVICE_CAPABILITIES "capabilities"
#define NM_DEVICE_REAL "real"
#define NM_DEVICE_MANAGED "managed"
#define NM_DEVICE_AUTOCONNECT "autoconnect"
#define NM_DEVICE_FIRMWARE_MISSING "firmware-missing"
@ -146,6 +147,8 @@ NM_AVAILABLE_IN_0_9_10
guint32 nm_device_get_mtu (NMDevice *device);
NM_AVAILABLE_IN_1_0
gboolean nm_device_is_software (NMDevice *device);
NM_AVAILABLE_IN_1_2
gboolean nm_device_is_real (NMDevice *device);
const char * nm_device_get_product (NMDevice *device);
const char * nm_device_get_vendor (NMDevice *device);

View file

@ -58,7 +58,7 @@ typedef struct {
const char *signal_prefix;
} PropertyInfo;
static void reload_complete (NMObject *object);
static void reload_complete (NMObject *object, gboolean emit_now);
typedef struct {
DBusGConnection *connection;
@ -72,7 +72,7 @@ typedef struct {
NMObject *parent;
gboolean suppress_property_updates;
GSList *notify_props;
GSList *notify_items;
guint32 notify_id;
gboolean inited;
@ -114,6 +114,27 @@ nm_object_error_quark (void)
return quark;
}
typedef enum {
NOTIFY_SIGNAL_PENDING_NONE,
NOTIFY_SIGNAL_PENDING_ADDED,
NOTIFY_SIGNAL_PENDING_REMOVED,
NOTIFY_SIGNAL_PENDING_ADDED_REMOVED,
} NotifySignalPending;
typedef struct {
const char *property;
const char *signal_prefix;
NotifySignalPending pending;
NMObject *changed;
} NotifyItem;
static void
notify_item_free (NotifyItem *item)
{
g_clear_object (&item->changed);
g_slice_free (NotifyItem, item);
}
static void
proxy_name_owner_changed (DBusGProxy *proxy,
const char *name,
@ -297,8 +318,8 @@ dispose (GObject *object)
priv->notify_id = 0;
}
g_slist_free_full (priv->notify_props, g_free);
priv->notify_props = NULL;
g_slist_free_full (priv->notify_items, (GDestroyNotify) notify_item_free);
priv->notify_items = NULL;
g_slist_free_full (priv->property_interfaces, g_free);
priv->property_interfaces = NULL;
@ -484,52 +505,155 @@ deferred_notify_cb (gpointer data)
{
NMObject *object = NM_OBJECT (data);
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
NMObjectClass *object_class = NM_OBJECT_GET_CLASS (object);
GSList *props, *iter;
priv->notify_id = 0;
/* Clear priv->notify_props early so that an NMObject subclass that
/* Wait until all reloads are done before notifying */
if (priv->reload_remaining)
return G_SOURCE_REMOVE;
/* Clear priv->notify_items early so that an NMObject subclass that
* listens to property changes can queue up other property changes
* during the g_object_notify() call separately from the property
* list we're iterating.
*/
props = g_slist_reverse (priv->notify_props);
priv->notify_props = NULL;
props = g_slist_reverse (priv->notify_items);
priv->notify_items = NULL;
g_object_ref (object);
/* Emit property change notifications first */
for (iter = props; iter; iter = g_slist_next (iter)) {
g_object_notify (G_OBJECT (object), (const char *) iter->data);
g_free (iter->data);
NotifyItem *item = iter->data;
if (item->property)
g_object_notify (G_OBJECT (object), item->property);
}
/* And added/removed signals second */
for (iter = props; iter; iter = g_slist_next (iter)) {
NotifyItem *item = iter->data;
char buf[50];
gint ret = 0;
switch (item->pending) {
case NOTIFY_SIGNAL_PENDING_ADDED:
ret = g_snprintf (buf, sizeof (buf), "%s-added", item->signal_prefix);
break;
case NOTIFY_SIGNAL_PENDING_REMOVED:
ret = g_snprintf (buf, sizeof (buf), "%s-removed", item->signal_prefix);
break;
case NOTIFY_SIGNAL_PENDING_ADDED_REMOVED:
// XXX
if (object_class->object_creation_failed)
object_class->object_creation_failed (object, NULL, g_strdup (nm_object_get_path (item->changed)));
break;
case NOTIFY_SIGNAL_PENDING_NONE:
default:
break;
}
if (ret > 0) {
g_assert (ret < sizeof (buf));
g_signal_emit_by_name (object, buf, item->changed);
}
}
g_object_unref (object);
g_slist_free (props);
return FALSE;
g_slist_free_full (props, (GDestroyNotify) notify_item_free);
return G_SOURCE_REMOVE;
}
static void
_nm_object_defer_notify (NMObject *object)
{
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
if (!priv->notify_id)
priv->notify_id = g_idle_add_full (G_PRIORITY_LOW, deferred_notify_cb, object, NULL);
}
static void
_nm_object_queue_notify_full (NMObject *object,
const char *property,
const char *signal_prefix,
gboolean added,
NMObject *changed)
{
NMObjectPrivate *priv;
NotifyItem *item;
GSList *iter;
g_return_if_fail (NM_IS_OBJECT (object));
g_return_if_fail (!signal_prefix != !property);
g_return_if_fail (!signal_prefix == !changed);
priv = NM_OBJECT_GET_PRIVATE (object);
_nm_object_defer_notify (object);
property = g_intern_string (property);
signal_prefix = g_intern_string (signal_prefix);
for (iter = priv->notify_items; iter; iter = g_slist_next (iter)) {
item = iter->data;
if (property && (property == item->property))
return;
/* Collapse signals for the same object (such as "added->removed") to
* ensure we don't emit signals when their sum should have no effect.
* The "added->removed->removed" sequence requires special handling,
* hence the addition of the ADDED_REMOVED state to ensure that no
* signal is emitted in this case:
*
* Without the ADDED_REMOVED state:
* NONE + added -> ADDED
* ADDED + removed -> NONE
* NONE + removed -> REMOVED (would emit 'removed' signal)
*
* With the ADDED_REMOVED state:
* NONE | ADDED_REMOVED + added -> ADDED
* ADDED + removed -> ADDED_REMOVED
* ADDED_REMOVED + removed -> ADDED_REMOVED (emits no signal)
*/
if (signal_prefix && (changed == item->changed) && (item->signal_prefix == signal_prefix)) {
switch (item->pending) {
case NOTIFY_SIGNAL_PENDING_ADDED:
if (!added)
item->pending = NOTIFY_SIGNAL_PENDING_ADDED_REMOVED;
break;
case NOTIFY_SIGNAL_PENDING_REMOVED:
if (added)
item->pending = NOTIFY_SIGNAL_PENDING_NONE;
break;
case NOTIFY_SIGNAL_PENDING_ADDED_REMOVED:
if (added)
item->pending = NOTIFY_SIGNAL_PENDING_ADDED;
break;
case NOTIFY_SIGNAL_PENDING_NONE:
item->pending = added ? NOTIFY_SIGNAL_PENDING_ADDED : NOTIFY_SIGNAL_PENDING_REMOVED;
break;
default:
g_assert_not_reached ();
}
return;
}
}
item = g_slice_new0 (NotifyItem);
item->property = property;
if (signal_prefix) {
item->signal_prefix = signal_prefix;
item->pending = added ? NOTIFY_SIGNAL_PENDING_ADDED : NOTIFY_SIGNAL_PENDING_REMOVED;
item->changed = changed ? g_object_ref (changed) : NULL;
}
priv->notify_items = g_slist_prepend (priv->notify_items, item);
}
void
_nm_object_queue_notify (NMObject *object, const char *property)
{
NMObjectPrivate *priv;
gboolean found = FALSE;
GSList *iter;
g_return_if_fail (NM_IS_OBJECT (object));
g_return_if_fail (property != NULL);
priv = NM_OBJECT_GET_PRIVATE (object);
if (!priv->notify_id)
priv->notify_id = g_idle_add_full (G_PRIORITY_LOW, deferred_notify_cb, object, NULL);
for (iter = priv->notify_props; iter; iter = g_slist_next (iter)) {
if (!strcmp ((char *) iter->data, property)) {
found = TRUE;
break;
}
}
if (!found)
priv->notify_props = g_slist_prepend (priv->notify_props, g_strdup (property));
_nm_object_queue_notify_full (object, property, NULL, FALSE, NULL);
}
void
@ -759,17 +883,12 @@ array_diff (GPtrArray *needles, GPtrArray *haystack, GPtrArray *diff)
}
static void
emit_added_removed_signal (NMObject *self,
const char *signal_prefix,
NMObject *changed,
gboolean added)
queue_added_removed_signal (NMObject *self,
const char *signal_prefix,
NMObject *changed,
gboolean added)
{
char buf[50];
int ret;
ret = g_snprintf (buf, sizeof (buf), "%s-%s", signal_prefix, added ? "added" : "removed");
g_assert (ret < sizeof (buf));
g_signal_emit_by_name (self, buf, changed);
_nm_object_queue_notify_full (self, NULL, signal_prefix, added, changed);
}
static void
@ -809,17 +928,17 @@ object_property_complete (ObjectCreatedData *odata)
/* Emit added & removed */
for (i = 0; i < removed->len; i++) {
emit_added_removed_signal (self,
pi->signal_prefix,
g_ptr_array_index (removed, i),
FALSE);
queue_added_removed_signal (self,
pi->signal_prefix,
g_ptr_array_index (removed, i),
FALSE);
}
for (i = 0; i < added->len; i++) {
emit_added_removed_signal (self,
pi->signal_prefix,
g_ptr_array_index (added, i),
TRUE);
queue_added_removed_signal (self,
pi->signal_prefix,
g_ptr_array_index (added, i),
TRUE);
}
different = removed->len || added->len;
@ -850,8 +969,8 @@ object_property_complete (ObjectCreatedData *odata)
if (different && odata->property_name)
_nm_object_queue_notify (self, odata->property_name);
if (priv->reload_results && --priv->reload_remaining == 0)
reload_complete (self);
if (--priv->reload_remaining == 0)
reload_complete (self, FALSE);
g_object_unref (self);
g_free (odata->objects);
@ -898,8 +1017,7 @@ handle_object_property (NMObject *self, const char *property_name, GValue *value
odata->array = FALSE;
odata->property_name = property_name;
if (priv->reload_results)
priv->reload_remaining++;
priv->reload_remaining++;
path = g_value_get_boxed (value);
@ -946,8 +1064,7 @@ handle_object_array_property (NMObject *self, const char *property_name, GValue
odata->array = TRUE;
odata->property_name = property_name;
if (priv->reload_results)
priv->reload_remaining++;
priv->reload_remaining++;
if (paths->len == 0) {
object_property_complete (odata);
@ -1214,6 +1331,8 @@ _nm_object_reload_properties (NMObject *object, GError **error)
if (!priv->property_interfaces || !priv->nm_running)
return TRUE;
priv->reload_remaining++;
for (p = priv->property_interfaces; p; p = p->next) {
if (!dbus_g_proxy_call (priv->properties_proxy, "GetAll", error,
G_TYPE_STRING, p->data,
@ -1226,6 +1345,9 @@ _nm_object_reload_properties (NMObject *object, GError **error)
g_hash_table_destroy (props);
}
if (--priv->reload_remaining == 0)
reload_complete (object, TRUE);
return TRUE;
}
@ -1322,13 +1444,22 @@ _nm_object_set_property (NMObject *object,
}
static void
reload_complete (NMObject *object)
reload_complete (NMObject *object, gboolean emit_now)
{
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
GSimpleAsyncResult *simple;
GSList *results, *iter;
GError *error;
if (emit_now) {
if (priv->notify_id) {
g_source_remove (priv->notify_id);
priv->notify_id = 0;
}
deferred_notify_cb (object);
} else
_nm_object_defer_notify (object);
results = priv->reload_results;
priv->reload_results = NULL;
error = priv->reload_error;
@ -1371,7 +1502,7 @@ reload_got_properties (DBusGProxy *proxy, DBusGProxyCall *call,
}
if (--priv->reload_remaining == 0)
reload_complete (object);
reload_complete (object, FALSE);
}
void

View file

@ -686,6 +686,7 @@ typedef struct {
static void
da_check_quit (DaInfo *info)
{
g_assert (info->quit_count > 0);
info->quit_count--;
if (info->quit_count == 0) {
g_source_remove (info->quit_id);

View file

@ -861,6 +861,7 @@ global:
nm_connection_get_setting_ip_tunnel;
nm_connection_verify_secrets;
nm_device_ethernet_get_s390_subchannels;
nm_client_get_all_devices;
nm_device_get_lldp_neighbors;
nm_device_get_metered;
nm_device_ip_tunnel_get_encapsulation_limit;
@ -876,6 +877,7 @@ global:
nm_device_ip_tunnel_get_ttl;
nm_device_ip_tunnel_get_type;
nm_device_get_nm_plugin_missing;
nm_device_is_real;
nm_device_set_managed;
nm_device_tun_get_group;
nm_device_tun_get_hw_address;
@ -896,6 +898,7 @@ global:
nm_lldp_neighbor_new;
nm_lldp_neighbor_ref;
nm_lldp_neighbor_unref;
nm_manager_get_all_devices;
nm_metered_get_type;
nm_setting_802_1x_check_cert_scheme;
nm_setting_bridge_get_multicast_snooping;

View file

@ -73,6 +73,7 @@ enum {
PROP_PRIMARY_CONNECTION,
PROP_ACTIVATING_CONNECTION,
PROP_DEVICES,
PROP_ALL_DEVICES,
PROP_CONNECTIONS,
PROP_HOSTNAME,
PROP_CAN_MODIFY,
@ -84,6 +85,8 @@ enum {
enum {
DEVICE_ADDED,
DEVICE_REMOVED,
ANY_DEVICE_ADDED,
ANY_DEVICE_REMOVED,
PERMISSION_CHANGED,
CONNECTION_ADDED,
CONNECTION_REMOVED,
@ -719,6 +722,34 @@ nm_client_get_devices (NMClient *client)
return nm_manager_get_devices (NM_CLIENT_GET_PRIVATE (client)->manager);
}
/**
* nm_client_get_all_devices:
* @client: a #NMClient
*
* Gets both real devices and device placeholders (eg, software devices which
* do not currently exist, but could be created automatically by NetworkManager
* if one of their NMDevice::ActivatableConnections was activated). Use
* nm_device_is_real() to determine whether each device is a real device or
* a placeholder.
*
* Use nm_device_get_type() or the NM_IS_DEVICE_XXXX() functions to determine
* what kind of device each member of the returned array is, and then you may
* use device-specific methods such as nm_device_ethernet_get_hw_address().
*
* Returns: (transfer none) (element-type NMDevice): a #GPtrArray
* containing all the #NMDevices. The returned array is owned by the
* #NMClient object and should not be modified.
*
* Since: 1.2
**/
const GPtrArray *
nm_client_get_all_devices (NMClient *client)
{
g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
return nm_manager_get_all_devices (NM_CLIENT_GET_PRIVATE (client)->manager);
}
/**
* nm_client_get_device_by_path:
* @client: a #NMClient
@ -1660,6 +1691,7 @@ manager_device_added (NMManager *manager,
{
g_signal_emit (client, signals[DEVICE_ADDED], 0, device);
}
static void
manager_device_removed (NMManager *manager,
NMDevice *device,
@ -1668,6 +1700,22 @@ manager_device_removed (NMManager *manager,
g_signal_emit (client, signals[DEVICE_REMOVED], 0, device);
}
static void
manager_any_device_added (NMManager *manager,
NMDevice *device,
gpointer client)
{
g_signal_emit (client, signals[ANY_DEVICE_ADDED], 0, device);
}
static void
manager_any_device_removed (NMManager *manager,
NMDevice *device,
gpointer client)
{
g_signal_emit (client, signals[ANY_DEVICE_REMOVED], 0, device);
}
static void
manager_permission_changed (NMManager *manager,
NMClientPermission permission,
@ -1707,6 +1755,10 @@ constructed (GObject *object)
G_CALLBACK (manager_device_added), client);
g_signal_connect (priv->manager, "device-removed",
G_CALLBACK (manager_device_removed), client);
g_signal_connect (priv->manager, "any-device-added",
G_CALLBACK (manager_any_device_added), client);
g_signal_connect (priv->manager, "any-device-removed",
G_CALLBACK (manager_any_device_removed), client);
g_signal_connect (priv->manager, "permission-changed",
G_CALLBACK (manager_permission_changed), client);
@ -1873,6 +1925,7 @@ get_property (GObject *object, guint prop_id,
case PROP_ACTIVATING_CONNECTION:
case PROP_DEVICES:
case PROP_METERED:
case PROP_ALL_DEVICES:
g_object_get_property (G_OBJECT (NM_CLIENT_GET_PRIVATE (object)->manager),
pspec->name, value);
break;
@ -2092,7 +2145,7 @@ nm_client_class_init (NMClientClass *client_class)
/**
* NMClient:devices:
*
* List of known network devices.
* List of real network devices. Does not include placeholder devices.
*
* Element-type: NMDevice
**/
@ -2103,6 +2156,21 @@ nm_client_class_init (NMClientClass *client_class)
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMClient:all-devices:
*
* List of both real devices and device placeholders.
*
* Element-type: NMDevice
* Since: 1.2
**/
g_object_class_install_property
(object_class, PROP_ALL_DEVICES,
g_param_spec_boxed (NM_CLIENT_ALL_DEVICES, "", "",
G_TYPE_PTR_ARRAY,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMClient:connections:
*
@ -2166,7 +2234,8 @@ nm_client_class_init (NMClientClass *client_class)
* @client: the client that received the signal
* @device: (type NMDevice): the new device
*
* Notifies that a #NMDevice is added.
* Notifies that a #NMDevice is added. This signal is not emitted for
* placeholder devices.
**/
signals[DEVICE_ADDED] =
g_signal_new (NM_CLIENT_DEVICE_ADDED,
@ -2182,7 +2251,8 @@ nm_client_class_init (NMClientClass *client_class)
* @client: the client that received the signal
* @device: (type NMDevice): the removed device
*
* Notifies that a #NMDevice is removed.
* Notifies that a #NMDevice is removed. This signal is not emitted for
* placeholder devices.
**/
signals[DEVICE_REMOVED] =
g_signal_new (NM_CLIENT_DEVICE_REMOVED,
@ -2193,6 +2263,40 @@ nm_client_class_init (NMClientClass *client_class)
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
/**
* NMClient::any-device-added:
* @client: the client that received the signal
* @device: (type NMDevice): the new device
*
* Notifies that a #NMDevice is added. This signal is emitted for both
* regular devices and placeholder devices.
**/
signals[ANY_DEVICE_ADDED] =
g_signal_new (NM_CLIENT_ANY_DEVICE_ADDED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMClientClass, any_device_added),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
/**
* NMClient::any-device-removed:
* @client: the client that received the signal
* @device: (type NMDevice): the removed device
*
* Notifies that a #NMDevice is removed. This signal is emitted for both
* regular devices and placeholder devices.
**/
signals[ANY_DEVICE_REMOVED] =
g_signal_new (NM_CLIENT_ANY_DEVICE_REMOVED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMClientClass, any_device_removed),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
/**
* NMClient::permission-changed:
* @client: the client that received the signal

View file

@ -53,6 +53,7 @@ G_BEGIN_DECLS
#define NM_CLIENT_PRIMARY_CONNECTION "primary-connection"
#define NM_CLIENT_ACTIVATING_CONNECTION "activating-connection"
#define NM_CLIENT_DEVICES "devices"
#define NM_CLIENT_ALL_DEVICES "all-devices"
#define NM_CLIENT_CONNECTIONS "connections"
#define NM_CLIENT_HOSTNAME "hostname"
#define NM_CLIENT_CAN_MODIFY "can-modify"
@ -60,6 +61,8 @@ G_BEGIN_DECLS
#define NM_CLIENT_DEVICE_ADDED "device-added"
#define NM_CLIENT_DEVICE_REMOVED "device-removed"
#define NM_CLIENT_ANY_DEVICE_ADDED "any-device-added"
#define NM_CLIENT_ANY_DEVICE_REMOVED "any-device-removed"
#define NM_CLIENT_PERMISSION_CHANGED "permission-changed"
#define NM_CLIENT_CONNECTION_ADDED "connection-added"
#define NM_CLIENT_CONNECTION_REMOVED "connection-removed"
@ -164,6 +167,8 @@ typedef struct {
/* Signals */
void (*device_added) (NMClient *client, NMDevice *device);
void (*device_removed) (NMClient *client, NMDevice *device);
void (*any_device_added) (NMClient *client, NMDevice *device);
void (*any_device_removed) (NMClient *client, NMDevice *device);
void (*permission_changed) (NMClient *client,
NMClientPermission permission,
NMClientPermissionResult result);
@ -171,7 +176,7 @@ typedef struct {
void (*connection_removed) (NMClient *client, NMRemoteConnection *connection);
/*< private >*/
gpointer padding[8];
gpointer padding[6];
} NMClientClass;
GType nm_client_get_type (void);
@ -248,6 +253,8 @@ gboolean nm_client_save_hostname_finish (NMClient *client,
/* Devices */
const GPtrArray *nm_client_get_devices (NMClient *client);
NM_AVAILABLE_IN_1_2
const GPtrArray *nm_client_get_all_devices(NMClient *client);
NMDevice *nm_client_get_device_by_path (NMClient *client, const char *object_path);
NMDevice *nm_client_get_device_by_iface (NMClient *client, const char *iface);

View file

@ -86,6 +86,7 @@ typedef struct {
char *type_description;
NMMetered metered;
NMDeviceCapabilities capabilities;
gboolean real;
gboolean managed;
gboolean firmware_missing;
gboolean nm_plugin_missing;
@ -119,6 +120,7 @@ enum {
PROP_DRIVER_VERSION,
PROP_FIRMWARE_VERSION,
PROP_CAPABILITIES,
PROP_REAL,
PROP_MANAGED,
PROP_AUTOCONNECT,
PROP_FIRMWARE_MISSING,
@ -229,6 +231,7 @@ init_dbus (NMObject *object)
{ NM_DEVICE_DRIVER_VERSION, &priv->driver_version },
{ NM_DEVICE_FIRMWARE_VERSION, &priv->firmware_version },
{ NM_DEVICE_CAPABILITIES, &priv->capabilities },
{ NM_DEVICE_REAL, &priv->real },
{ NM_DEVICE_MANAGED, &priv->managed },
{ NM_DEVICE_AUTOCONNECT, &priv->autoconnect },
{ NM_DEVICE_FIRMWARE_MISSING, &priv->firmware_missing },
@ -461,6 +464,9 @@ get_property (GObject *object,
case PROP_CAPABILITIES:
g_value_set_flags (value, nm_device_get_capabilities (device));
break;
case PROP_REAL:
g_value_set_boolean (value, nm_device_is_real (device));
break;
case PROP_MANAGED:
g_value_set_boolean (value, nm_device_get_managed (device));
break;
@ -679,6 +685,22 @@ nm_device_class_init (NMDeviceClass *device_class)
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMDevice:real:
*
* Whether the device is real or is a placeholder device that could
* be created automatically by NetworkManager if one of its
* #NMDevice:available-connections was activated.
*
* Since: 1.2
**/
g_object_class_install_property
(object_class, PROP_REAL,
g_param_spec_boolean (NM_DEVICE_REAL, "", "",
FALSE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMDevice:managed:
*
@ -2097,6 +2119,24 @@ nm_device_get_lldp_neighbors (NMDevice *device)
return NM_DEVICE_GET_PRIVATE (device)->lldp_neighbors;
}
/**
* nm_device_is_real:
* @device: a #NMDevice
*
* Returns: %TRUE if the device exists, or %FALSE if it is a placeholder device
* that could be automatically created by NetworkManager if one of its
* #NMDevice:available-connections was activated.
*
* Since: 1.2
**/
gboolean
nm_device_is_real (NMDevice *device)
{
g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
return NM_DEVICE_GET_PRIVATE (device)->real;
}
/**
* nm_device_is_software:
* @device: a #NMDevice

View file

@ -45,6 +45,7 @@ G_BEGIN_DECLS
#define NM_DEVICE_DRIVER_VERSION "driver-version"
#define NM_DEVICE_FIRMWARE_VERSION "firmware-version"
#define NM_DEVICE_CAPABILITIES "capabilities"
#define NM_DEVICE_REAL "real"
#define NM_DEVICE_MANAGED "managed"
#define NM_DEVICE_AUTOCONNECT "autoconnect"
#define NM_DEVICE_FIRMWARE_MISSING "firmware-missing"
@ -123,6 +124,8 @@ NMActiveConnection * nm_device_get_active_connection(NMDevice *device);
const GPtrArray * nm_device_get_available_connections(NMDevice *device);
const char * nm_device_get_physical_port_id (NMDevice *device);
guint32 nm_device_get_mtu (NMDevice *device);
NM_AVAILABLE_IN_1_2
gboolean nm_device_is_real (NMDevice *device);
gboolean nm_device_is_software (NMDevice *device);
const char * nm_device_get_product (NMDevice *device);

View file

@ -60,6 +60,7 @@ typedef struct {
NMState state;
gboolean startup;
GPtrArray *devices;
GPtrArray *all_devices;
GPtrArray *active_connections;
NMConnectivityState connectivity;
NMActiveConnection *primary_connection;
@ -104,6 +105,7 @@ enum {
PROP_ACTIVATING_CONNECTION,
PROP_DEVICES,
PROP_METERED,
PROP_ALL_DEVICES,
LAST_PROP
};
@ -111,6 +113,8 @@ enum {
enum {
DEVICE_ADDED,
DEVICE_REMOVED,
ANY_DEVICE_ADDED,
ANY_DEVICE_REMOVED,
ACTIVE_CONNECTION_ADDED,
ACTIVE_CONNECTION_REMOVED,
PERMISSION_CHANGED,
@ -136,6 +140,7 @@ nm_manager_init (NMManager *manager)
priv->permissions = g_hash_table_new (g_direct_hash, g_direct_equal);
priv->devices = g_ptr_array_new ();
priv->all_devices = g_ptr_array_new ();
priv->active_connections = g_ptr_array_new ();
}
@ -145,8 +150,8 @@ poke_wireless_devices_with_rf_status (NMManager *manager)
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
int i;
for (i = 0; i < priv->devices->len; i++) {
NMDevice *device = g_ptr_array_index (priv->devices, 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);
@ -182,6 +187,7 @@ init_dbus (NMObject *object)
{ NM_MANAGER_ACTIVATING_CONNECTION, &priv->activating_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
{ NM_MANAGER_DEVICES, &priv->devices, NULL, NM_TYPE_DEVICE, "device" },
{ NM_MANAGER_METERED, &priv->metered },
{ NM_MANAGER_ALL_DEVICES, &priv->all_devices, NULL, NM_TYPE_DEVICE, "any-device" },
{ NULL },
};
@ -667,6 +673,14 @@ nm_manager_get_devices (NMManager *manager)
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)
{
@ -1180,27 +1194,47 @@ static void
free_devices (NMManager *manager, gboolean in_dispose)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
GPtrArray *devices;
NMDevice *device;
int i;
gs_unref_ptrarray GPtrArray *real_devices = NULL;
gs_unref_ptrarray GPtrArray *all_devices = NULL;
GPtrArray *devices = NULL;
guint i, j;
if (!priv->devices)
return;
real_devices = priv->devices;
all_devices = priv->all_devices;
devices = priv->devices;
if (in_dispose)
if (in_dispose) {
priv->devices = NULL;
else {
priv->devices = g_ptr_array_new ();
for (i = 0; i < devices->len; i++) {
device = devices->pdata[i];
g_signal_emit (manager, signals[DEVICE_REMOVED], 0, device);
}
priv->all_devices = NULL;
return;
}
g_ptr_array_unref (devices);
priv->devices = g_ptr_array_new_with_free_func (g_object_unref);
priv->all_devices = g_ptr_array_new_with_free_func (g_object_unref);
if (all_devices && all_devices->len > 0)
devices = all_devices;
else if (devices && devices->len > 0)
devices = real_devices;
if (real_devices && devices != real_devices) {
for (i = 0; i < real_devices->len; i++) {
NMDevice *d = real_devices->pdata[i];
if (all_devices) {
for (j = 0; j < all_devices->len; j++) {
if (d == all_devices->pdata[j])
goto next;
}
}
g_signal_emit (manager, signals[DEVICE_REMOVED], 0, d);
next:
;
}
}
if (devices) {
for (i = 0; i < devices->len; i++)
g_signal_emit (manager, signals[DEVICE_REMOVED], 0, devices->pdata[i]);
}
}
static void
@ -1543,6 +1577,9 @@ get_property (GObject *object,
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;
@ -1689,6 +1726,13 @@ nm_manager_class_init (NMManagerClass *manager_class)
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] =
@ -1707,6 +1751,22 @@ nm_manager_class_init (NMManagerClass *manager_class)
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),

View file

@ -51,6 +51,7 @@ G_BEGIN_DECLS
#define NM_MANAGER_ACTIVATING_CONNECTION "activating-connection"
#define NM_MANAGER_DEVICES "devices"
#define NM_MANAGER_METERED "metered"
#define NM_MANAGER_ALL_DEVICES "all-devices"
typedef struct {
NMObject parent;
@ -67,6 +68,8 @@ typedef struct {
void (*permission_changed) (NMManager *manager,
NMClientPermission permission,
NMClientPermissionResult result);
/* Beware: no more slots. Cannot extend struct without breaking ABI. */
} NMManagerClass;
GType nm_manager_get_type (void);
@ -121,6 +124,8 @@ NMConnectivityState nm_manager_check_connectivity_finish (NMManager *manager,
/* Devices */
const GPtrArray *nm_manager_get_devices (NMManager *manager);
NM_AVAILABLE_IN_1_2
const GPtrArray *nm_manager_get_all_devices(NMManager *manager);
NMDevice *nm_manager_get_device_by_path (NMManager *manager, const char *object_path);
NMDevice *nm_manager_get_device_by_iface (NMManager *manager, const char *iface);

View file

@ -3440,25 +3440,33 @@ nm_utils_g_value_set_object_path (GValue *value, gpointer object)
* nm_utils_g_value_set_object_path_array:
* @value: a #GValue, initialized to store an object path
* @objects: a #GSList of #NMExportedObjects
* @filter_func: (allow-none): function to call on each object in @objects
* @user_data: data to pass to @filter_func
*
* Sets @value to an array of object paths of the objects in @objects.
*/
void
nm_utils_g_value_set_object_path_array (GValue *value, GSList *objects)
nm_utils_g_value_set_object_path_array (GValue *value,
GSList *objects,
NMUtilsObjectFunc filter_func,
gpointer user_data)
{
GPtrArray *paths;
char **paths;
guint i;
GSList *iter;
paths = g_ptr_array_new ();
for (iter = objects; iter; iter = iter->next) {
paths = g_new (char *, g_slist_length (objects) + 1);
for (i = 0, iter = objects; iter; iter = iter->next) {
NMExportedObject *object = iter->data;
if (!nm_exported_object_is_exported (object))
continue;
g_ptr_array_add (paths, g_strdup (nm_exported_object_get_path (object)));
if (filter_func && !filter_func ((GObject *) object, user_data))
continue;
paths[i++] = g_strdup (nm_exported_object_get_path (object));
}
g_ptr_array_add (paths, NULL);
g_value_take_boxed (value, (char **) g_ptr_array_free (paths, FALSE));
paths[i] = NULL;
g_value_take_boxed (value, paths);
}
/**

View file

@ -320,7 +320,20 @@ NMUtilsTestFlags nm_utils_get_testing (void);
void _nm_utils_set_testing (NMUtilsTestFlags flags);
void nm_utils_g_value_set_object_path (GValue *value, gpointer object);
void nm_utils_g_value_set_object_path_array (GValue *value, GSList *objects);
void nm_utils_g_value_set_strv (GValue *value, GPtrArray *strings);
/**
* NMUtilsObjectFunc:
* @object: the object to filter on
* @user_data: data passed to the function from the caller
*
* Returns: %TRUE if the object should be used, %FALSE if not
*/
typedef gboolean (*NMUtilsObjectFunc) (GObject *object, gpointer user_data);
void nm_utils_g_value_set_object_path_array (GValue *value,
GSList *objects,
NMUtilsObjectFunc filter_func,
gpointer user_data);
#endif /* __NETWORKMANAGER_UTILS_H__ */

View file

@ -501,7 +501,7 @@ get_property (GObject *object, guint prop_id,
break;
case PROP_SLAVES:
list = nm_device_master_get_slaves (NM_DEVICE (object));
nm_utils_g_value_set_object_path_array (value, list);
nm_utils_g_value_set_object_path_array (value, list, NULL, NULL);
g_slist_free (list);
break;
default:
@ -529,7 +529,7 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceBondPrivate));
parent_class->connection_type = NM_SETTING_BOND_SETTING_NAME;
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_BOND_SETTING_NAME, NM_LINK_TYPE_BOND)
/* virtual methods */
object_class->get_property = get_property;

View file

@ -97,7 +97,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
return FALSE;
mac_address = nm_setting_bridge_get_mac_address (s_bridge);
if (mac_address) {
if (mac_address && nm_device_is_real (device)) {
const char *hw_addr;
hw_addr = nm_device_get_hw_address (device);
@ -447,7 +447,7 @@ get_property (GObject *object, guint prop_id,
break;
case PROP_SLAVES:
list = nm_device_master_get_slaves (NM_DEVICE (object));
nm_utils_g_value_set_object_path_array (value, list);
nm_utils_g_value_set_object_path_array (value, list, NULL, NULL);
g_slist_free (list);
break;
default:
@ -475,7 +475,7 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceBridgePrivate));
parent_class->connection_type = NM_SETTING_BRIDGE_SETTING_NAME;
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_BRIDGE_SETTING_NAME, NM_LINK_TYPE_BRIDGE)
/* virtual methods */
object_class->get_property = get_property;

View file

@ -305,9 +305,9 @@ nm_device_ethernet_init (NMDeviceEthernet *self)
}
static void
setup (NMDevice *device, NMPlatformLink *plink)
setup_start (NMDevice *device, NMPlatformLink *plink)
{
NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->setup (device, plink);
NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->setup_start (device, plink);
g_object_notify (G_OBJECT (device), NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS);
}
@ -1706,7 +1706,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceEthernetPrivate));
parent_class->connection_type = NM_SETTING_WIRED_SETTING_NAME;
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRED_SETTING_NAME, NM_LINK_TYPE_ETHERNET)
/* virtual methods */
object_class->constructor = constructor;
@ -1716,7 +1716,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
object_class->set_property = set_property;
parent_class->get_generic_capabilities = get_generic_capabilities;
parent_class->setup = setup;
parent_class->setup_start = setup_start;
parent_class->check_connection_compatible = check_connection_compatible;
parent_class->complete_connection = complete_connection;
parent_class->new_default_connection = new_default_connection;

View file

@ -61,13 +61,13 @@ get_type_description (NMDevice *device)
}
static void
setup (NMDevice *device, NMPlatformLink *plink)
setup_start (NMDevice *device, NMPlatformLink *plink)
{
NMDeviceGeneric *self = NM_DEVICE_GENERIC (device);
NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (self);
int ifindex;
NM_DEVICE_CLASS (nm_device_generic_parent_class)->setup (device, plink);
NM_DEVICE_CLASS (nm_device_generic_parent_class)->setup_start (device, plink);
g_clear_pointer (&priv->type_description, g_free);
ifindex = nm_device_get_ip_ifindex (NM_DEVICE (self));
@ -196,14 +196,14 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceGenericPrivate));
parent_class->connection_type = NM_SETTING_GENERIC_SETTING_NAME;
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_GENERIC_SETTING_NAME, NM_LINK_TYPE_ANY)
object_class->constructor = constructor;
object_class->dispose = dispose;
object_class->get_property = get_property;
object_class->set_property = set_property;
parent_class->setup = setup;
parent_class->setup_start = setup_start;
parent_class->get_generic_capabilities = get_generic_capabilities;
parent_class->get_type_description = get_type_description;
parent_class->check_connection_compatible = check_connection_compatible;

View file

@ -149,7 +149,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
if (!s_infiniband)
return FALSE;
if (s_infiniband) {
if (nm_device_is_real (device)) {
const char *mac;
mac = nm_setting_infiniband_get_mac_address (s_infiniband);
@ -327,6 +327,8 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceInfinibandPrivate));
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_INFINIBAND_SETTING_NAME, NM_LINK_TYPE_INFINIBAND)
/* virtual methods */
object_class->get_property = get_property;
object_class->set_property = set_property;

View file

@ -113,7 +113,7 @@ address_equal_pn (int family, const char *a, const void *b)
}
static void
update_properties (NMDevice *device)
update_properties_from_ifindex (NMDevice *device, int ifindex)
{
NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device);
NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self);
@ -127,13 +127,40 @@ update_properties (NMDevice *device)
guint32 flow_label = 0;
char *key;
if (ifindex <= 0) {
clear:
if (priv->parent || priv->parent_ifindex) {
g_clear_object (&priv->parent);
priv->parent_ifindex = 0;
g_object_notify (object, NM_DEVICE_IP_TUNNEL_PARENT);
}
if (priv->local) {
g_clear_pointer (&priv->local, g_free);
g_object_notify (object, NM_DEVICE_IP_TUNNEL_LOCAL);
}
if (priv->remote) {
g_clear_pointer (&priv->remote, g_free);
g_object_notify (object, NM_DEVICE_IP_TUNNEL_REMOTE);
}
if (priv->input_key) {
g_clear_pointer (&priv->input_key, g_free);
g_object_notify (object, NM_DEVICE_IP_TUNNEL_INPUT_KEY);
}
if (priv->output_key) {
g_clear_pointer (&priv->output_key, g_free);
g_object_notify (object, NM_DEVICE_IP_TUNNEL_OUTPUT_KEY);
}
goto out;
}
if (priv->mode == NM_IP_TUNNEL_MODE_GRE) {
const NMPlatformLnkGre *lnk;
lnk = nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL);
lnk = nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, ifindex, NULL);
if (!lnk) {
_LOGW (LOGD_HW, "could not read %s properties", "gre");
return;
goto clear;
}
parent_ifindex = lnk->parent_ifindex;
@ -175,10 +202,10 @@ update_properties (NMDevice *device)
} else if (priv->mode == NM_IP_TUNNEL_MODE_SIT) {
const NMPlatformLnkSit *lnk;
lnk = nm_platform_link_get_lnk_sit (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL);
lnk = nm_platform_link_get_lnk_sit (NM_PLATFORM_GET, ifindex, NULL);
if (!lnk) {
_LOGW (LOGD_HW, "could not read %s properties", "sit");
return;
goto clear;
}
parent_ifindex = lnk->parent_ifindex;
@ -190,10 +217,10 @@ update_properties (NMDevice *device)
} else if (priv->mode == NM_IP_TUNNEL_MODE_IPIP) {
const NMPlatformLnkIpIp *lnk;
lnk = nm_platform_link_get_lnk_ipip (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL);
lnk = nm_platform_link_get_lnk_ipip (NM_PLATFORM_GET, ifindex, NULL);
if (!lnk) {
_LOGW (LOGD_HW, "could not read %s properties", "ipip");
return;
goto clear;
}
parent_ifindex = lnk->parent_ifindex;
@ -206,10 +233,10 @@ update_properties (NMDevice *device)
|| priv->mode == NM_IP_TUNNEL_MODE_IP6IP6) {
const NMPlatformLnkIp6Tnl *lnk;
lnk = nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL);
lnk = nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, ifindex, NULL);
if (!lnk) {
_LOGW (LOGD_HW, "could not read %s properties", "ip6tnl");
return;
goto clear;
}
parent_ifindex = lnk->parent_ifindex;
@ -261,6 +288,8 @@ update_properties (NMDevice *device)
}
}
out:
if (priv->ttl != ttl) {
priv->ttl = ttl;
g_object_notify (object, NM_DEVICE_IP_TUNNEL_TTL);
@ -287,6 +316,12 @@ update_properties (NMDevice *device)
}
}
static void
update_properties (NMDevice *device)
{
update_properties_from_ifindex (device, nm_device_get_ifindex (device));
}
static void
link_changed (NMDevice *device, NMPlatformLink *info)
{
@ -335,8 +370,6 @@ update_connection (NMDevice *device, NMConnection *connection)
nm_connection_add_setting (connection, (NMSetting *) s_ip_tunnel);
}
update_properties (device);
if (nm_setting_ip_tunnel_get_mode (s_ip_tunnel) != priv->mode)
g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_MODE, priv->mode, NULL);
@ -470,43 +503,43 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
if (!s_ip_tunnel)
return FALSE;
update_properties (device);
/* Check parent interface; could be an interface name or a UUID */
parent = nm_setting_ip_tunnel_get_parent (s_ip_tunnel);
if (parent) {
if (!match_parent (priv->parent, parent))
return FALSE;
}
if (nm_setting_ip_tunnel_get_mode (s_ip_tunnel) != priv->mode)
return FALSE;
if (!address_equal_pp (priv->addr_family,
nm_setting_ip_tunnel_get_local (s_ip_tunnel),
priv->local))
return FALSE;
if (nm_device_is_real (device)) {
/* Check parent interface; could be an interface name or a UUID */
parent = nm_setting_ip_tunnel_get_parent (s_ip_tunnel);
if (parent) {
if (!match_parent (priv->parent, parent))
return FALSE;
}
if (!address_equal_pp (priv->addr_family,
nm_setting_ip_tunnel_get_remote (s_ip_tunnel),
priv->remote))
return FALSE;
if (nm_setting_ip_tunnel_get_ttl (s_ip_tunnel) != priv->ttl)
return FALSE;
if (nm_setting_ip_tunnel_get_tos (s_ip_tunnel) != priv->tos)
return FALSE;
if (priv->addr_family == AF_INET) {
if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery)
return FALSE;
} else {
if (nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel) != priv->encap_limit)
if (!address_equal_pp (priv->addr_family,
nm_setting_ip_tunnel_get_local (s_ip_tunnel),
priv->local))
return FALSE;
if (nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel) != priv->flow_label)
if (!address_equal_pp (priv->addr_family,
nm_setting_ip_tunnel_get_remote (s_ip_tunnel),
priv->remote))
return FALSE;
if (nm_setting_ip_tunnel_get_ttl (s_ip_tunnel) != priv->ttl)
return FALSE;
if (nm_setting_ip_tunnel_get_tos (s_ip_tunnel) != priv->tos)
return FALSE;
if (priv->addr_family == AF_INET) {
if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery)
return FALSE;
} else {
if (nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel) != priv->encap_limit)
return FALSE;
if (nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel) != priv->flow_label)
return FALSE;
}
}
return TRUE;
@ -720,13 +753,21 @@ create_and_realize (NMDevice *device,
}
static void
setup (NMDevice *device, NMPlatformLink *plink)
setup_start (NMDevice *device, NMPlatformLink *plink)
{
NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->setup (device, plink);
NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->setup_start (device, plink);
update_properties (device);
}
static void
unrealize (NMDevice *device, gboolean remove_resources)
{
NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->unrealize (device, remove_resources);
update_properties_from_ifindex (device, 0);
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
@ -808,9 +849,15 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass)
device_class->check_connection_compatible = check_connection_compatible;
device_class->create_and_realize = create_and_realize;
device_class->realize = realize;
device_class->setup = setup;
device_class->setup_start = setup_start;
device_class->unrealize = unrealize;
device_class->connection_type = NM_SETTING_IP_TUNNEL_SETTING_NAME;
NM_DEVICE_CLASS_DECLARE_TYPES (klass,
NM_SETTING_IP_TUNNEL_SETTING_NAME,
NM_LINK_TYPE_GRE,
NM_LINK_TYPE_IP6TNL,
NM_LINK_TYPE_IPIP,
NM_LINK_TYPE_SIT);
/* properties */
g_object_class_install_property

View file

@ -143,6 +143,8 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceMacvlanPrivate));
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP)
object_class->constructed = constructed;
object_class->get_property = get_property;

View file

@ -106,4 +106,11 @@ void nm_device_set_wwan_ip6_config (NMDevice *device, NMIP6Config *config);
gboolean nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value);
#define NM_DEVICE_CLASS_DECLARE_TYPES(klass, conn_type, ...) \
NM_DEVICE_CLASS (klass)->connection_type = conn_type; \
{ \
static const NMLinkType link_types[] = { __VA_ARGS__, NM_LINK_TYPE_NONE }; \
NM_DEVICE_CLASS (klass)->link_types = link_types; \
}
#endif /* NM_DEVICE_PRIVATE_H */

View file

@ -24,9 +24,9 @@
#include <string.h>
#include <sys/types.h>
#include "nm-default.h"
#include "nm-device-tun.h"
#include "nm-device-private.h"
#include "nm-default.h"
#include "nm-platform.h"
#include "nm-device-factory.h"
#include "nm-setting-tun.h"
@ -226,6 +226,13 @@ realize (NMDevice *device, NMPlatformLink *plink, GError **error)
return TRUE;
}
static void
setup_start (NMDevice *device, NMPlatformLink *plink)
{
NM_DEVICE_CLASS (nm_device_tun_parent_class)->setup_start (device, plink);
reload_tun_properties (device);
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
@ -235,8 +242,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
NMSettingTun *s_tun;
gint64 user, group;
reload_tun_properties (self);
if (!NM_DEVICE_CLASS (nm_device_tun_parent_class)->check_connection_compatible (device, connection))
return FALSE;
@ -244,27 +249,47 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
if (!s_tun)
return FALSE;
mode = tun_mode_from_string (priv->mode);
if (mode != nm_setting_tun_get_mode (s_tun))
return FALSE;
if (nm_device_is_real (device)) {
mode = tun_mode_from_string (priv->mode);
if (mode != nm_setting_tun_get_mode (s_tun))
return FALSE;
user = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1);
group = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_group (s_tun), 10, 0, G_MAXINT32, -1);
user = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1);
group = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_group (s_tun), 10, 0, G_MAXINT32, -1);
if (user != priv->props.owner)
return FALSE;
if (group != priv->props.group)
return FALSE;
if (nm_setting_tun_get_pi (s_tun) == priv->props.no_pi)
return FALSE;
if (nm_setting_tun_get_vnet_hdr (s_tun) != priv->props.vnet_hdr)
return FALSE;
if (nm_setting_tun_get_multi_queue (s_tun) != priv->props.multi_queue)
return FALSE;
if (user != priv->props.owner)
return FALSE;
if (group != priv->props.group)
return FALSE;
if (nm_setting_tun_get_pi (s_tun) == priv->props.no_pi)
return FALSE;
if (nm_setting_tun_get_vnet_hdr (s_tun) != priv->props.vnet_hdr)
return FALSE;
if (nm_setting_tun_get_multi_queue (s_tun) != priv->props.multi_queue)
return FALSE;
}
return TRUE;
}
static void
unrealize (NMDevice *device, gboolean remove_resources)
{
NMDeviceTun *self = NM_DEVICE_TUN (device);
NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self);
GParamSpec **properties;
guint n_properties, i;
NM_DEVICE_CLASS (nm_device_tun_parent_class)->unrealize (device, remove_resources);
memset (&priv->props, 0, sizeof (NMPlatformTunProperties));
properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (self), &n_properties);
for (i = 0; i < n_properties; i++)
g_object_notify_by_pspec (G_OBJECT (self), properties[i]);
g_free (properties);
}
/**************************************************************/
static void
@ -339,6 +364,8 @@ nm_device_tun_class_init (NMDeviceTunClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceTunPrivate));
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_TUN, NM_LINK_TYPE_TAP)
object_class->get_property = get_property;
object_class->set_property = set_property;
@ -349,6 +376,8 @@ nm_device_tun_class_init (NMDeviceTunClass *klass)
device_class->check_connection_compatible = check_connection_compatible;
device_class->create_and_realize = create_and_realize;
device_class->realize = realize;
device_class->setup_start = setup_start;
device_class->unrealize = unrealize;
device_class->update_connection = update_connection;
/* properties */

View file

@ -153,6 +153,8 @@ nm_device_veth_class_init (NMDeviceVethClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceVethPrivate));
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_VETH)
object_class->get_property = get_property;
object_class->dispose = dispose;

View file

@ -148,12 +148,12 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent)
}
static void
setup (NMDevice *device, NMPlatformLink *plink)
setup_start (NMDevice *device, NMPlatformLink *plink)
{
NMDeviceVlan *self = NM_DEVICE_VLAN (device);
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
NM_DEVICE_CLASS (nm_device_vlan_parent_class)->setup (device, plink);
NM_DEVICE_CLASS (nm_device_vlan_parent_class)->setup_start (device, plink);
_LOGI (LOGD_HW | LOGD_VLAN, "VLAN ID %d with parent %s",
priv->vlan_id, nm_device_get_iface (priv->parent));
@ -256,6 +256,16 @@ create_and_realize (NMDevice *device,
return TRUE;
}
static void
unrealize (NMDevice *device, gboolean remove_resources)
{
NM_DEVICE_CLASS (nm_device_vlan_parent_class)->unrealize (device, remove_resources);
NM_DEVICE_VLAN_GET_PRIVATE (device)->vlan_id = 0;
g_object_notify (G_OBJECT (device), NM_DEVICE_VLAN_ID);
nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), NULL);
}
/******************************************************************/
static NMDeviceCapabilities
@ -290,36 +300,31 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
return NM_DEVICE_CLASS (nm_device_vlan_parent_class)->is_available (device, flags);
}
static gboolean
component_added (NMDevice *device, GObject *component)
static void
notify_new_device_added (NMDevice *device, NMDevice *new_device)
{
NMDeviceVlan *self = NM_DEVICE_VLAN (device);
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
NMDevice *added_device;
const NMPlatformLink *plink;
const NMPlatformLnkVlan *plnk;
if (priv->parent)
return FALSE;
return;
if (!NM_IS_DEVICE (component))
return FALSE;
added_device = NM_DEVICE (component);
if (!nm_device_is_real (device))
return;
plnk = nm_platform_link_get_lnk_vlan (NM_PLATFORM_GET, nm_device_get_ifindex (device), &plink);
if (!plnk) {
_LOGW (LOGD_VLAN, "failed to get VLAN interface info while checking added component.");
return FALSE;
return;
}
if ( plink->parent <= 0
|| nm_device_get_ifindex (added_device) != plink->parent)
return FALSE;
|| nm_device_get_ifindex (new_device) != plink->parent)
return;
nm_device_vlan_set_parent (self, added_device);
/* Don't claim parent exclusively */
return FALSE;
nm_device_vlan_set_parent (self, new_device);
}
/******************************************************************/
@ -395,18 +400,21 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
if (!s_vlan)
return FALSE;
if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id)
return FALSE;
/* Before the device is realized some properties will not be set */
if (nm_device_is_real (device)) {
if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id)
return FALSE;
/* Check parent interface; could be an interface name or a UUID */
parent = nm_setting_vlan_get_parent (s_vlan);
if (parent) {
if (!match_parent (NM_DEVICE_VLAN (device), parent))
return FALSE;
} else {
/* Parent could be a MAC address in an NMSettingWired */
if (!match_hwaddr (device, connection, TRUE))
return FALSE;
/* Check parent interface; could be an interface name or a UUID */
parent = nm_setting_vlan_get_parent (s_vlan);
if (parent) {
if (!match_parent (NM_DEVICE_VLAN (device), parent))
return FALSE;
} else {
/* Parent could be a MAC address in an NMSettingWired */
if (!match_hwaddr (device, connection, TRUE))
return FALSE;
}
}
/* Ensure the interface name matches. If not specified we assume a match
@ -659,7 +667,7 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
parent_class->connection_type = NM_SETTING_VLAN_SETTING_NAME;
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_VLAN_SETTING_NAME, NM_LINK_TYPE_VLAN)
g_type_class_add_private (object_class, sizeof (NMDeviceVlanPrivate));
@ -670,14 +678,15 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
parent_class->create_and_realize = create_and_realize;
parent_class->realize = realize;
parent_class->setup = setup;
parent_class->setup_start = setup_start;
parent_class->unrealize = unrealize;
parent_class->get_generic_capabilities = get_generic_capabilities;
parent_class->bring_up = bring_up;
parent_class->act_stage1_prepare = act_stage1_prepare;
parent_class->ip4_config_pre_commit = ip4_config_pre_commit;
parent_class->deactivate = deactivate;
parent_class->is_available = is_available;
parent_class->component_added = component_added;
parent_class->notify_new_device_added = notify_new_device_added;
parent_class->check_connection_compatible = check_connection_compatible;
parent_class->complete_connection = complete_connection;

View file

@ -22,9 +22,9 @@
#include <string.h>
#include "nm-default.h"
#include "nm-device-vxlan.h"
#include "nm-device-private.h"
#include "nm-default.h"
#include "nm-manager.h"
#include "nm-platform.h"
#include "nm-utils.h"
@ -133,15 +133,32 @@ link_changed (NMDevice *device, NMPlatformLink *info)
}
static void
setup (NMDevice *device, NMPlatformLink *plink)
setup_start (NMDevice *device, NMPlatformLink *plink)
{
g_assert (plink->type == NM_LINK_TYPE_VXLAN);
NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->setup (device, plink);
NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->setup_start (device, plink);
update_properties (device);
}
static void
unrealize (NMDevice *device, gboolean remove_resources)
{
NMDeviceVxlan *self = NM_DEVICE_VXLAN (device);
NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (self);
GParamSpec **properties;
guint n_properties, i;
NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->unrealize (device, remove_resources);
memset (&priv->props, 0, sizeof (NMPlatformLnkVxlan));
properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (self), &n_properties);
for (i = 0; i < n_properties; i++)
g_object_notify_by_pspec (G_OBJECT (self), properties[i]);
g_free (properties);
}
/**************************************************************/
@ -227,10 +244,13 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceVxlanPrivate));
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_VXLAN)
object_class->get_property = get_property;
device_class->link_changed = link_changed;
device_class->setup = setup;
device_class->setup_start = setup_start;
device_class->unrealize = unrealize;
/* properties */
g_object_class_install_property

View file

@ -129,6 +129,7 @@ enum {
PROP_HAS_PENDING_ACTION,
PROP_METERED,
PROP_LLDP_NEIGHBORS,
PROP_REAL,
LAST_PROP
};
@ -207,6 +208,7 @@ typedef struct {
char * udi;
char * iface; /* may change, could be renamed by user */
int ifindex;
gboolean real;
char * ip_iface;
int ip_ifindex;
NMDeviceType type;
@ -554,17 +556,38 @@ nm_device_get_iface (NMDevice *self)
int
nm_device_get_ifindex (NMDevice *self)
{
g_return_val_if_fail (self != NULL, 0);
g_return_val_if_fail (NM_IS_DEVICE (self), 0);
return NM_DEVICE_GET_PRIVATE (self)->ifindex;
}
/**
* nm_device_is_software:
* @self: the #NMDevice
*
* Indicates if the device is a software-based virtual device without
* backing hardware, which can be added and removed programmatically.
*
* Returns: %TRUE if the device is a software-based device
*/
gboolean
nm_device_is_software (NMDevice *self)
{
return NM_FLAGS_HAS (NM_DEVICE_GET_PRIVATE (self)->capabilities, NM_DEVICE_CAP_IS_SOFTWARE);
}
/**
* nm_device_is_real:
* @self: the #NMDevice
*
* Returns: %TRUE if the device exists, %FALSE if the device is a placeholder
*/
gboolean
nm_device_is_real (NMDevice *self)
{
return NM_DEVICE_GET_PRIVATE (self)->real;
}
const char *
nm_device_get_ip_iface (NMDevice *self)
{
@ -1129,8 +1152,7 @@ nm_device_release_one_slave (NMDevice *self, NMDevice *slave, gboolean configure
static gboolean
can_unmanaged_external_down (NMDevice *self)
{
return nm_device_is_software (self)
&& !nm_device_get_is_nm_owned (self);
return nm_device_is_software (self) && !NM_DEVICE_GET_PRIVATE (self)->is_nm_owned;
}
/**
@ -1362,23 +1384,31 @@ nm_device_set_carrier (NMDevice *self, gboolean carrier)
}
static void
device_set_master (NMDevice *self, int ifindex)
device_recheck_slave_status (NMDevice *self, NMPlatformLink *plink)
{
NMDevice *master;
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
master = nm_manager_get_device_by_ifindex (nm_manager_get (), ifindex);
if (master && NM_DEVICE_GET_CLASS (master)->enslave_slave) {
g_clear_object (&priv->master);
priv->master = g_object_ref (master);
nm_device_master_add_slave (master, self, FALSE);
} else if (master) {
_LOGI (LOGD_DEVICE, "enslaved to non-master-type device %s; ignoring",
nm_device_get_iface (master));
} else {
_LOGW (LOGD_DEVICE, "enslaved to unknown device %d %s",
ifindex,
nm_platform_link_get_name (NM_PLATFORM_GET, ifindex));
g_return_if_fail (plink != NULL);
if (priv->enslaved && plink->master != nm_device_get_ifindex (priv->master))
nm_device_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
if (plink->master && !priv->enslaved) {
NMDevice *master;
master = nm_manager_get_device_by_ifindex (nm_manager_get (), plink->master);
if (master && NM_DEVICE_GET_CLASS (master)->enslave_slave) {
g_clear_object (&priv->master);
priv->master = g_object_ref (master);
nm_device_master_add_slave (master, self, FALSE);
} else if (master) {
_LOGI (LOGD_DEVICE, "enslaved to non-master-type device %s; ignoring",
nm_device_get_iface (master));
} else {
_LOGW (LOGD_DEVICE, "enslaved to unknown device %d %s",
plink->master,
nm_platform_link_get_name (NM_PLATFORM_GET, plink->master));
}
}
}
@ -1426,6 +1456,12 @@ device_link_changed (NMDevice *self)
g_object_notify (G_OBJECT (self), NM_DEVICE_MTU);
}
if (info.driver && g_strcmp0 (priv->driver, info.driver) != 0) {
g_free (priv->driver);
priv->driver = g_strdup (info.driver);
g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER);
}
if (info.name[0] && strcmp (priv->iface, info.name) != 0) {
_LOGI (LOGD_DEVICE, "interface index %d renamed iface from '%s' to '%s'",
priv->ifindex, priv->iface, info.name);
@ -1448,15 +1484,6 @@ device_link_changed (NMDevice *self)
nm_device_emit_recheck_auto_activate (self);
}
/* Update slave status for external changes */
if (priv->enslaved && info.master != nm_device_get_ifindex (priv->master))
nm_device_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
if (info.master && !priv->enslaved) {
device_set_master (self, info.master);
if (priv->master)
nm_device_enslave_slave (priv->master, self, NULL);
}
if (priv->rdisc && nm_platform_link_get_ipv6_token (NM_PLATFORM_GET, priv->ifindex, &token_iid)) {
_LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface);
if (nm_rdisc_set_iid (priv->rdisc, token_iid))
@ -1539,6 +1566,7 @@ device_link_changed (NMDevice *self)
if (emit_link_initialized)
g_signal_emit (self, signals[LINK_INITIALIZED], 0);
device_recheck_slave_status (self, &info);
return G_SOURCE_REMOVE;
}
@ -1606,26 +1634,76 @@ link_changed (NMDevice *self, NMPlatformLink *info)
nm_device_set_carrier (self, info->connected);
}
static gboolean
link_type_compatible (NMDevice *self,
NMLinkType link_type,
gboolean *out_compatible,
GError **error)
{
NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self);
guint i = 0;
if (!klass->link_types) {
NM_SET_OUT (out_compatible, FALSE);
g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
"Device does not support platform links");
return FALSE;
}
for (i = 0; klass->link_types[i] > NM_LINK_TYPE_UNKNOWN; i++) {
if (klass->link_types[i] == link_type)
return TRUE;
if (klass->link_types[i] == NM_LINK_TYPE_ANY)
return TRUE;
}
NM_SET_OUT (out_compatible, FALSE);
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
"Device does not support platform link type 0x%X",
link_type);
return FALSE;
}
/**
* nm_device_realize():
* @self: the #NMDevice
* @plink: an existing platform link or %NULL
* @out_compatible: %TRUE on return if @self is compatible with @plink
* @error: location to store error, or %NULL
*
* Initializes and sets up the device using existing backing resources.
* Initializes and sets up the device using existing backing resources. Before
* the device is ready for use nm_device_setup_finish() must be called.
* @out_compatible will only be set if @plink is not %NULL, and
*
* Returns: %TRUE on success, %FALSE on error
*/
gboolean
nm_device_realize (NMDevice *self, NMPlatformLink *plink, GError **error)
nm_device_realize (NMDevice *self,
NMPlatformLink *plink,
gboolean *out_compatible,
GError **error)
{
NM_SET_OUT (out_compatible, TRUE);
if (plink) {
if (g_strcmp0 (nm_device_get_iface (self), plink->name) != 0) {
NM_SET_OUT (out_compatible, FALSE);
g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
"Device interface name does not match platform link");
return FALSE;
}
if (!link_type_compatible (self, plink->type, out_compatible, error))
return FALSE;
}
/* Try to realize the device from existing resources */
if (NM_DEVICE_GET_CLASS (self)->realize) {
if (!NM_DEVICE_GET_CLASS (self)->realize (self, plink, error))
return FALSE;
}
NM_DEVICE_GET_CLASS (self)->setup (self, plink);
NM_DEVICE_GET_CLASS (self)->setup_start (self, plink);
return TRUE;
}
@ -1648,15 +1726,20 @@ nm_device_create_and_realize (NMDevice *self,
NMDevice *parent,
GError **error)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMPlatformLink plink = { .type = NM_LINK_TYPE_UNKNOWN };
/* Must be set before device is realized */
priv->is_nm_owned = !nm_platform_link_get_by_ifname (NM_PLATFORM_GET, priv->iface);
/* Create any resources the device needs */
if (NM_DEVICE_GET_CLASS (self)->create_and_realize) {
if (!NM_DEVICE_GET_CLASS (self)->create_and_realize (self, connection, parent, &plink, error))
return FALSE;
}
NM_DEVICE_GET_CLASS (self)->setup (self, (plink.type != NM_LINK_TYPE_UNKNOWN) ? &plink : NULL);
NM_DEVICE_GET_CLASS (self)->setup_start (self, (plink.type != NM_LINK_TYPE_UNKNOWN) ? &plink : NULL);
nm_device_setup_finish (self, (plink.type != NM_LINK_TYPE_UNKNOWN) ? &plink : NULL);
g_return_val_if_fail (nm_device_check_connection_compatible (self, connection), TRUE);
return TRUE;
@ -1719,7 +1802,7 @@ check_carrier (NMDevice *self)
}
static void
setup (NMDevice *self, NMPlatformLink *plink)
setup_start (NMDevice *self, NMPlatformLink *plink)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
static guint32 id = 0;
@ -1728,15 +1811,16 @@ setup (NMDevice *self, NMPlatformLink *plink)
g_return_if_fail (priv->ip_ifindex <= 0);
g_return_if_fail (priv->ip_iface == NULL);
/* Balanced by a thaw in nm_device_setup_finish() */
g_object_freeze_notify (G_OBJECT (self));
if (plink) {
g_return_if_fail (priv->iface == NULL || strcmp (plink->name, priv->iface) == 0);
g_return_if_fail (link_type_compatible (self, plink->type, NULL, NULL));
update_device_from_platform_link (self, plink);
}
if (priv->ifindex > 0) {
_LOGD (LOGD_DEVICE, "setup(): %s, kernel ifindex %d", G_OBJECT_TYPE_NAME (self), priv->ifindex);
_LOGD (LOGD_DEVICE, "setup_start(): %s, kernel ifindex %d", G_OBJECT_TYPE_NAME (self), priv->ifindex);
priv->physical_port_id = nm_platform_link_get_physical_port_id (NM_PLATFORM_GET, priv->ifindex);
g_object_notify (G_OBJECT (self), NM_DEVICE_PHYSICAL_PORT_ID);
@ -1821,15 +1905,150 @@ setup (NMDevice *self, NMPlatformLink *plink)
g_object_notify (G_OBJECT (self), NM_DEVICE_CAPABILITIES);
/* Enslave ourselves */
if (priv->ifindex > 0) {
int master = nm_platform_link_get_master (NM_PLATFORM_GET, priv->ifindex);
priv->real = TRUE;
}
if (master > 0)
device_set_master (self, master);
static void
setup_finish (NMDevice *self, NMPlatformLink *plink)
{
if (plink) {
update_device_from_platform_link (self, plink);
device_recheck_slave_status (self, plink);
}
}
void
nm_device_setup_finish (NMDevice *self, NMPlatformLink *plink)
{
g_return_if_fail (!plink || link_type_compatible (self, plink->type, NULL, NULL));
NM_DEVICE_GET_CLASS (self)->setup_finish (self, plink);
NM_DEVICE_GET_PRIVATE (self)->real = TRUE;
g_object_notify (G_OBJECT (self), NM_DEVICE_REAL);
nm_device_recheck_available_connections (self);
/* Balanced by a freeze in setup_start() */
g_object_thaw_notify (G_OBJECT (self));
}
static void
unrealize (NMDevice *self, gboolean remove_resources)
{
int ifindex;
if (remove_resources) {
ifindex = nm_device_get_ifindex (self);
if ( ifindex > 0
&& nm_device_is_software (self))
nm_platform_link_delete (NM_PLATFORM_GET, ifindex);
}
}
/**
* nm_device_unrealize():
* @self: the #NMDevice
* @remove_resources: if %TRUE, remove backing resources
* @error: location to store error, or %NULL
*
* Clears any properties that depend on backing resources (kernel devices,
* etc) and removes those resources if @remove_resources is %TRUE.
*
* Returns: %TRUE on success, %FALSE on error
*/
gboolean
nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
{
NMDevicePrivate *priv;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
if (!nm_device_is_software (self) || !nm_device_is_real (self)) {
g_set_error_literal (error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_NOT_SOFTWARE,
"This device is not a software device or is not realized");
return FALSE;
}
priv = NM_DEVICE_GET_PRIVATE (self);
g_return_val_if_fail (priv->iface != NULL, FALSE);
g_object_freeze_notify (G_OBJECT (self));
if (NM_DEVICE_GET_CLASS (self)->unrealize)
NM_DEVICE_GET_CLASS (self)->unrealize (self, remove_resources);
if (priv->ifindex > 0) {
priv->ifindex = 0;
g_object_notify (G_OBJECT (self), NM_DEVICE_IFINDEX);
}
priv->ip_ifindex = 0;
if (priv->ip_iface) {
g_clear_pointer (&priv->ip_iface, g_free);
g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE);
}
if (priv->driver_version) {
g_clear_pointer (&priv->driver_version, g_free);
g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER_VERSION);
}
if (priv->firmware_version) {
g_clear_pointer (&priv->firmware_version, g_free);
g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_VERSION);
}
if (priv->udi) {
g_clear_pointer (&priv->udi, g_free);
g_object_notify (G_OBJECT (self), NM_DEVICE_UDI);
}
if (priv->hw_addr) {
g_clear_pointer (&priv->hw_addr, g_free);
g_object_notify (G_OBJECT (self), NM_DEVICE_HW_ADDRESS);
}
if (priv->physical_port_id) {
g_clear_pointer (&priv->physical_port_id, g_free);
g_object_notify (G_OBJECT (self), NM_DEVICE_PHYSICAL_PORT_ID);
}
g_clear_pointer (&priv->perm_hw_addr, g_free);
g_clear_pointer (&priv->initial_hw_addr, g_free);
priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED;
g_object_notify (G_OBJECT (self), NM_DEVICE_CAPABILITIES);
priv->real = FALSE;
g_object_notify (G_OBJECT (self), NM_DEVICE_REAL);
g_object_thaw_notify (G_OBJECT (self));
nm_device_state_changed (self,
NM_DEVICE_STATE_UNMANAGED,
remove_resources ?
NM_DEVICE_STATE_REASON_USER_REQUESTED : NM_DEVICE_STATE_REASON_NOW_UNMANAGED);
return TRUE;
}
/**
* nm_device_notify_new_device_added():
* @self: the #NMDevice
* @device: the newly added device
*
* Called by the manager to notify the device that a new device has
* been found and added.
*/
void
nm_device_notify_new_device_added (NMDevice *self, NMDevice *device)
{
NMDeviceClass *klass;
g_return_if_fail (NM_IS_DEVICE (self));
g_return_if_fail (NM_IS_DEVICE (device));
klass = NM_DEVICE_GET_CLASS (self);
if (klass->notify_new_device_added)
klass->notify_new_device_added (self, device);
}
/**
@ -1847,8 +2066,14 @@ setup (NMDevice *self, NMPlatformLink *plink)
gboolean
nm_device_notify_component_added (NMDevice *self, GObject *component)
{
if (NM_DEVICE_GET_CLASS (self)->component_added)
return NM_DEVICE_GET_CLASS (self)->component_added (self, component);
NMDeviceClass *klass;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
g_return_val_if_fail (G_IS_OBJECT (component), FALSE);
klass = NM_DEVICE_GET_CLASS (self);
if (klass->component_added)
return klass->component_added (self, component);
return FALSE;
}
@ -2064,6 +2289,18 @@ nm_device_master_release_slaves (NMDevice *self)
}
}
/**
* nm_device_is_master:
* @self: the device
*
* Returns: %TRUE if the device can have slaves
*/
gboolean
nm_device_is_master (NMDevice *self)
{
return NM_DEVICE_GET_PRIVATE (self)->is_master;
}
/**
* nm_device_get_master:
* @self: the device
@ -2418,7 +2655,7 @@ device_has_config (NMDevice *self)
return TRUE;
/* The existence of a software device is good enough. */
if (nm_device_is_software (self))
if (nm_device_is_software (self) && nm_device_is_real (self))
return TRUE;
/* Slaves are also configured by definition */
@ -2648,6 +2885,34 @@ nm_device_check_connection_compatible (NMDevice *self, NMConnection *connection)
return NM_DEVICE_GET_CLASS (self)->check_connection_compatible (self, connection);
}
gboolean
nm_device_check_slave_connection_compatible (NMDevice *self, NMConnection *slave)
{
NMDevicePrivate *priv;
NMSettingConnection *s_con;
const char *connection_type, *slave_type;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
g_return_val_if_fail (NM_IS_CONNECTION (slave), FALSE);
priv = NM_DEVICE_GET_PRIVATE (self);
if (!priv->is_master)
return FALSE;
/* All masters should have connection type set */
connection_type = NM_DEVICE_GET_CLASS (self)->connection_type;
g_return_val_if_fail (connection_type, FALSE);
s_con = nm_connection_get_setting_connection (slave);
g_assert (s_con);
slave_type = nm_setting_connection_get_slave_type (s_con);
if (!slave_type)
return FALSE;
return strcmp (connection_type, slave_type) == 0;
}
/**
* nm_device_can_assume_connections:
* @self: #NMDevice instance
@ -2660,7 +2925,8 @@ nm_device_check_connection_compatible (NMDevice *self, NMConnection *connection)
static gboolean
nm_device_can_assume_connections (NMDevice *self)
{
return !!NM_DEVICE_GET_CLASS (self)->update_connection;
return !!NM_DEVICE_GET_CLASS (self)->update_connection
&& !NM_DEVICE_GET_PRIVATE (self)->is_nm_owned;
}
/**
@ -6397,14 +6663,6 @@ nm_device_get_is_nm_owned (NMDevice *self)
return NM_DEVICE_GET_PRIVATE (self)->is_nm_owned;
}
void
nm_device_set_nm_owned (NMDevice *self)
{
g_return_if_fail (NM_IS_DEVICE (self));
NM_DEVICE_GET_PRIVATE (self)->is_nm_owned = TRUE;
}
/*
* delete_on_deactivate_link_delete
*
@ -6418,16 +6676,21 @@ delete_on_deactivate_link_delete (gpointer user_data)
DeleteOnDeactivateData *data = user_data;
NMDevice *self = data->device;
_LOGD (LOGD_DEVICE, "delete_on_deactivate: cleanup and delete virtual link #%d (id=%u)",
data->ifindex, data->idle_add_id);
if (data->device) {
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (data->device);
gs_free_error GError *error = NULL;
g_object_remove_weak_pointer (G_OBJECT (data->device), (void **) &data->device);
priv->delete_on_deactivate_data = NULL;
}
_LOGD (LOGD_DEVICE, "delete_on_deactivate: cleanup and delete virtual link #%d (id=%u)",
data->ifindex, data->idle_add_id);
nm_platform_link_delete (NM_PLATFORM_GET, data->ifindex);
if (!nm_device_unrealize (data->device, TRUE, &error))
_LOGD (LOGD_DEVICE, "delete_on_deactivate: unrealizing %d failed (%s)", data->ifindex, error->message);
} else
nm_platform_link_delete (NM_PLATFORM_GET, data->ifindex);
g_free (data);
return FALSE;
}
@ -6462,7 +6725,7 @@ delete_on_deactivate_check_and_schedule (NMDevice *self, int ifindex)
return;
if (priv->queued_act_request)
return;
if (!nm_device_is_software (self))
if (!nm_device_is_software (self) || !nm_device_is_real (self))
return;
if (nm_device_get_state (self) == NM_DEVICE_STATE_UNMANAGED)
return;
@ -6558,6 +6821,8 @@ delete_cb (NMDevice *self,
GError *error,
gpointer user_data)
{
GError *local = NULL;
if (error) {
g_dbus_method_invocation_return_gerror (context, error);
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, FALSE, subject, error->message);
@ -6565,9 +6830,11 @@ delete_cb (NMDevice *self,
}
/* Authorized */
nm_platform_link_delete (NM_PLATFORM_GET, nm_device_get_ifindex (self));
g_dbus_method_invocation_return_value (context, NULL);
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, TRUE, subject, NULL);
if (nm_device_unrealize (self, TRUE, &local))
g_dbus_method_invocation_return_value (context, NULL);
else
g_dbus_method_invocation_take_error (context, local);
}
static void
@ -6575,10 +6842,10 @@ impl_device_delete (NMDevice *self, GDBusMethodInvocation *context)
{
GError *error = NULL;
if (!nm_device_is_software (self)) {
if (!nm_device_is_software (self) || !nm_device_is_real (self)) {
error = g_error_new_literal (NM_DEVICE_ERROR,
NM_DEVICE_ERROR_NOT_SOFTWARE,
"This device is not a software device");
"This device is not a software device or is not realized");
g_dbus_method_invocation_take_error (context, error);
return;
}
@ -8302,6 +8569,7 @@ _nm_device_check_connection_available (NMDevice *self,
&& nm_device_get_unmanaged (self, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT))
return FALSE;
if ( state < NM_DEVICE_STATE_DISCONNECTED
&& !nm_device_is_software (self)
&& ( ( !NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER)
&& !nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE))
|| ( NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER)
@ -9896,6 +10164,7 @@ set_property (GObject *object, guint prop_id,
const char *hw_addr, *p;
guint count;
gboolean val_bool;
const NMPlatformLink *pllink;
switch (prop_id) {
case PROP_UDI:
@ -9905,12 +10174,19 @@ set_property (GObject *object, guint prop_id,
}
break;
case PROP_IFACE:
if (g_value_get_string (value)) {
p = g_value_get_string (value);
if (p) {
g_free (priv->iface);
priv->iface = g_value_dup_string (value);
priv->ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->iface);
if (priv->ifindex > 0)
priv->up = nm_platform_link_is_up (NM_PLATFORM_GET, priv->ifindex);
priv->iface = g_strdup (p);
pllink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, priv->iface);
if (pllink) {
if (link_type_compatible (self, pllink->type, NULL, NULL)) {
priv->ifindex = pllink->ifindex;
priv->up = nm_platform_link_is_up (NM_PLATFORM_GET, priv->ifindex);
}
}
}
break;
case PROP_DRIVER:
@ -10103,7 +10379,7 @@ get_property (GObject *object, guint prop_id,
g_value_set_boolean (value, priv->is_master);
break;
case PROP_MASTER:
g_value_set_object (value, priv->master);
g_value_set_object (value, nm_device_get_master (self));
break;
case PROP_HW_ADDRESS:
g_value_set_string (value, priv->hw_addr);
@ -10122,6 +10398,9 @@ get_property (GObject *object, guint prop_id,
g_value_take_variant (value, g_variant_builder_end (&array_builder));
}
break;
case PROP_REAL:
g_value_set_boolean (value, priv->real);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -10162,7 +10441,9 @@ nm_device_class_init (NMDeviceClass *klass)
klass->check_connection_compatible = check_connection_compatible;
klass->check_connection_available = check_connection_available;
klass->can_unmanaged_external_down = can_unmanaged_external_down;
klass->setup = setup;
klass->setup_start = setup_start;
klass->setup_finish = setup_finish;
klass->unrealize = unrealize;
klass->is_up = is_up;
klass->bring_up = bring_up;
klass->take_down = take_down;
@ -10412,6 +10693,13 @@ nm_device_class_init (NMDeviceClass *klass)
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_REAL,
g_param_spec_boolean (NM_DEVICE_REAL, "", "",
FALSE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/* Signals */
signals[STATE_CHANGED] =
g_signal_new ("state-changed",

View file

@ -59,6 +59,7 @@
#define NM_DEVICE_HW_ADDRESS "hw-address"
#define NM_DEVICE_METERED "metered"
#define NM_DEVICE_LLDP_NEIGHBORS "lldp-neighbors"
#define NM_DEVICE_REAL "real"
#define NM_DEVICE_TYPE_DESC "type-desc" /* Internal only */
#define NM_DEVICE_RFKILL_TYPE "rfkill-type" /* Internal only */
@ -122,6 +123,7 @@ typedef struct {
NMExportedObjectClass parent;
const char *connection_type;
const NMLinkType *link_types;
void (*state_changed) (NMDevice *device,
NMDeviceState new_state,
@ -173,14 +175,39 @@ typedef struct {
GError **error);
/**
* setup():
* setup_start():
* @self: the #NMDevice
* @plink: the #NMPlatformLink if backed by a kernel netdevice
*
* Update the device from backing resource properties (like hardware
* addresses, carrier states, driver/firmware info, etc).
* addresses, carrier states, driver/firmware info, etc). This function
* should only change properties for this device, and should not perform
* any tasks that affect other interfaces (like master/slave or parent/child
* stuff).
*/
void (*setup) (NMDevice *self, NMPlatformLink *plink);
void (*setup_start) (NMDevice *self, NMPlatformLink *plink);
/**
* setup_finish():
* @self: the #NMDevice
* @plink: the #NMPlatformLink if backed by a kernel netdevice
*
* Update the device's master/slave or parent/child relationships from
* backing resource properties. After this function finishes, the device
* is ready for network connectivity.
*/
void (*setup_finish) (NMDevice *self, NMPlatformLink *plink);
/**
* unrealize():
* @self: the #NMDevice
* @remove_resources: if %TRUE remove backing resources
* @error: location to store error, or %NULL
*
* Clears any properties that depend on backing resources (kernel devices,
* etc) and removes those resources if @remove_resources is %TRUE.
*/
void (*unrealize) (NMDevice *self, gboolean remove_resources);
/* Hardware state (IFF_UP) */
gboolean (*can_unmanaged_external_down) (NMDevice *self);
@ -288,6 +315,8 @@ typedef struct {
gboolean (* have_any_ready_slaves) (NMDevice *self,
const GSList *slaves);
void (* notify_new_device_added) (NMDevice *self, NMDevice *new_device);
/**
* component_added:
* @self: the #NMDevice
@ -324,6 +353,7 @@ const char * nm_device_get_udi (NMDevice *dev);
const char * nm_device_get_iface (NMDevice *dev);
int nm_device_get_ifindex (NMDevice *dev);
gboolean nm_device_is_software (NMDevice *dev);
gboolean nm_device_is_real (NMDevice *dev);
const char * nm_device_get_ip_iface (NMDevice *dev);
int nm_device_get_ip_ifindex(NMDevice *dev);
const char * nm_device_get_driver (NMDevice *dev);
@ -358,6 +388,7 @@ void nm_device_capture_initial_config (NMDevice *dev);
/* Master */
GSList * nm_device_master_get_slaves (NMDevice *dev);
gboolean nm_device_is_master (NMDevice *dev);
/* Slave */
NMDevice * nm_device_get_master (NMDevice *dev);
@ -391,6 +422,7 @@ gboolean nm_device_complete_connection (NMDevice *device,
GError **error);
gboolean nm_device_check_connection_compatible (NMDevice *device, NMConnection *connection);
gboolean nm_device_check_slave_connection_compatible (NMDevice *device, NMConnection *connection);
gboolean nm_device_uses_assumed_connection (NMDevice *device);
@ -451,17 +483,22 @@ void nm_device_set_unmanaged_initial (NMDevice *device,
gboolean unmanaged);
gboolean nm_device_get_is_nm_owned (NMDevice *device);
void nm_device_set_nm_owned (NMDevice *device);
gboolean nm_device_has_capability (NMDevice *self, NMDeviceCapabilities caps);
gboolean nm_device_realize (NMDevice *device,
NMPlatformLink *plink,
gboolean *out_compatible,
GError **error);
gboolean nm_device_create_and_realize (NMDevice *self,
NMConnection *connection,
NMDevice *parent,
GError **error);
void nm_device_setup_finish (NMDevice *self,
NMPlatformLink *plink);
gboolean nm_device_unrealize (NMDevice *device,
gboolean remove_resources,
GError **error);
gboolean nm_device_get_autoconnect (NMDevice *device);
@ -496,6 +533,7 @@ gboolean nm_device_check_connection_available (NMDevice *device,
NMDeviceCheckConAvailableFlags flags,
const char *specific_object);
void nm_device_notify_new_device_added (NMDevice *self, NMDevice *new_device);
gboolean nm_device_notify_component_added (NMDevice *device, GObject *component);
gboolean nm_device_owns_iface (NMDevice *device, const char *iface);

View file

@ -758,7 +758,7 @@ get_property (GObject *object, guint prop_id,
break;
case PROP_SLAVES:
list = nm_device_master_get_slaves (NM_DEVICE (object));
nm_utils_g_value_set_object_path_array (value, list);
nm_utils_g_value_set_object_path_array (value, list, NULL, NULL);
g_slist_free (list);
break;
default:
@ -802,7 +802,7 @@ nm_device_team_class_init (NMDeviceTeamClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceTeamPrivate));
parent_class->connection_type = NM_SETTING_TEAM_SETTING_NAME;
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_TEAM_SETTING_NAME, NM_LINK_TYPE_TEAM)
/* virtual methods */
object_class->constructed = constructed;

View file

@ -511,6 +511,8 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceOlpcMeshPrivate));
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_OLPC_MESH_SETTING_NAME, NM_LINK_TYPE_OLPC_MESH)
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->set_property = set_property;

View file

@ -424,9 +424,9 @@ periodic_update_cb (gpointer user_data)
}
static void
setup (NMDevice *device, NMPlatformLink *plink)
setup_start (NMDevice *device, NMPlatformLink *plink)
{
NM_DEVICE_CLASS (nm_device_wifi_parent_class)->setup (device, plink);
NM_DEVICE_CLASS (nm_device_wifi_parent_class)->setup_start (device, plink);
g_object_notify (G_OBJECT (device), NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS);
}
@ -3034,13 +3034,15 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceWifiPrivate));
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRELESS_SETTING_NAME, NM_LINK_TYPE_WIFI)
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->set_property = set_property;
object_class->dispose = dispose;
object_class->finalize = finalize;
parent_class->setup = setup;
parent_class->setup_start = setup_start;
parent_class->bring_up = bring_up;
parent_class->can_auto_connect = can_auto_connect;
parent_class->is_available = is_available;

View file

@ -468,9 +468,7 @@ master_failed (NMActiveConnection *self)
* @specific_object: the object path of the specific object (ie, WiFi access point,
* etc) that will be used to activate @connection and @device
* @subject: the #NMAuthSubject representing the requestor of the activation
* @device: the device/interface to configure according to @connection; or %NULL
* if the connection describes a software device which will be created during
* connection activation
* @device: the device/interface to configure according to @connection
*
* Creates a new device-based activation request.
*
@ -483,7 +481,7 @@ nm_act_request_new (NMSettingsConnection *settings_connection,
NMDevice *device)
{
g_return_val_if_fail (!settings_connection || NM_IS_SETTINGS_CONNECTION (settings_connection), NULL);
g_return_val_if_fail (!device || NM_IS_DEVICE (device), NULL);
g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
return (NMActRequest *) g_object_new (NM_TYPE_ACT_REQUEST,

View file

@ -515,8 +515,13 @@ nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device)
priv->pending_activation_id = g_strdup_printf ("activation::%p", (void *)self);
nm_device_add_pending_action (device, priv->pending_activation_id, TRUE);
}
} else
} else {
/* The ActiveConnection's device can only be cleared after the
* connection is activated.
*/
g_warn_if_fail (priv->state > NM_ACTIVE_CONNECTION_STATE_UNKNOWN);
priv->device = NULL;
}
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_INT_DEVICE);
g_signal_emit (self, signals[DEVICE_CHANGED], 0, priv->device, old_device);
@ -598,17 +603,17 @@ master_state_cb (NMActiveConnection *master,
gpointer user_data)
{
NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
NMActiveConnectionState master_state = nm_active_connection_get_state (master);
NMDevice *master_device = nm_active_connection_get_device (master);
check_master_ready (self);
_LOGD ("master ActiveConnection [%p] state now '%s' (%d)",
master, state_to_string (master_state), master_state);
if ( master_state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING
&& !priv->master_ready) {
/* Master failed without ever creating its device */
if ( master_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATING
&& (!master_device || !nm_device_is_real (master_device))) {
/* Master failed without ever creating or realizing its device */
if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed)
NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed (self);
}
@ -831,6 +836,7 @@ set_property (GObject *object, guint prop_id,
}
break;
case PROP_INT_DEVICE:
/* construct-only */
nm_active_connection_set_device (NM_ACTIVE_CONNECTION (object), g_value_get_object (value));
break;
case PROP_INT_SUBJECT:
@ -1129,7 +1135,7 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class)
(object_class, PROP_INT_DEVICE,
g_param_spec_object (NM_ACTIVE_CONNECTION_INT_DEVICE, "", "",
NM_TYPE_DEVICE,
G_PARAM_READWRITE |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property

File diff suppressed because it is too large Load diff

View file

@ -50,6 +50,7 @@
#define NM_MANAGER_DEVICES "devices"
#define NM_MANAGER_METERED "metered"
#define NM_MANAGER_GLOBAL_DNS_CONFIGURATION "global-dns-configuration"
#define NM_MANAGER_ALL_DEVICES "all-devices"
/* Not exported */
#define NM_MANAGER_HOSTNAME "hostname"

View file

@ -1779,8 +1779,8 @@ nm_policy_new (NMManager *manager, NMSettings *settings)
_connect_manager_signal (policy, "notify::" NM_MANAGER_HOSTNAME, hostname_changed);
_connect_manager_signal (policy, "notify::" NM_MANAGER_SLEEPING, sleeping_changed);
_connect_manager_signal (policy, "notify::" NM_MANAGER_NETWORKING_ENABLED, sleeping_changed);
_connect_manager_signal (policy, "device-added", device_added);
_connect_manager_signal (policy, "device-removed", device_removed);
_connect_manager_signal (policy, "internal-device-added", device_added);
_connect_manager_signal (policy, "internal-device-removed", device_removed);
_connect_manager_signal (policy, NM_MANAGER_ACTIVE_CONNECTION_ADDED, active_connection_added);
_connect_manager_signal (policy, NM_MANAGER_ACTIVE_CONNECTION_REMOVED, active_connection_removed);

View file

@ -126,6 +126,8 @@ typedef enum {
NM_LINK_TYPE_BRIDGE = 0x10000 | 0x20000,
NM_LINK_TYPE_BOND,
NM_LINK_TYPE_TEAM,
NM_LINK_TYPE_ANY = G_MAXUINT32,
} NMLinkType;
typedef enum {

View file

@ -1854,13 +1854,20 @@ default_wired_clear_tag (NMSettings *self,
nm_config_set_no_auto_default_for_device (NM_SETTINGS_GET_PRIVATE (self)->config, device);
}
void
nm_settings_device_added (NMSettings *self, NMDevice *device)
static void
device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self)
{
NMConnection *connection;
NMSettingsConnection *added;
GError *error = NULL;
if (!nm_device_is_real (device))
return;
g_signal_handlers_disconnect_by_func (device,
G_CALLBACK (device_realized),
self);
/* If the device isn't managed or it already has a default wired connection,
* ignore it.
*/
@ -1898,11 +1905,27 @@ nm_settings_device_added (NMSettings *self, NMDevice *device)
nm_settings_connection_get_id (added));
}
void
nm_settings_device_added (NMSettings *self, NMDevice *device)
{
if (nm_device_is_real (device))
device_realized (device, NULL, self);
else {
g_signal_connect_after (device, "notify::" NM_DEVICE_REAL,
G_CALLBACK (device_realized),
self);
}
}
void
nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean quitting)
{
NMSettingsConnection *connection;
g_signal_handlers_disconnect_by_func (device,
G_CALLBACK (device_realized),
self);
connection = g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG);
if (connection) {
default_wired_clear_tag (self, device, connection, FALSE);

View file

@ -9,6 +9,7 @@ import dbus
import dbus.service
import dbus.mainloop.glib
import random
import collections
mainloop = GLib.MainLoop()
@ -83,32 +84,42 @@ def to_path(src):
return dbus.ObjectPath("/")
class ExportedObj(dbus.service.Object):
DBusInterface = collections.namedtuple('DBusInterface', ['dbus_iface', 'get_props_func', 'prop_changed_func'])
def __init__(self, bus, object_path):
dbus.service.Object.__init__(self, bus, object_path)
self._bus = bus
self.path = object_path
self.__dbus_ifaces = {}
def add_dbus_interface(self, dbus_iface, get_props_func):
self.__dbus_ifaces[dbus_iface] = get_props_func
def add_dbus_interface(self, dbus_iface, get_props_func, prop_changed_func):
self.__dbus_ifaces[dbus_iface] = ExportedObj.DBusInterface(dbus_iface, get_props_func, prop_changed_func)
def _get_dbus_properties(self, iface):
return self.__dbus_ifaces[iface]()
def __dbus_interface_get(self, dbus_iface):
if dbus_iface not in self.__dbus_ifaces:
raise UnknownInterfaceException()
return self.__dbus_ifaces[dbus_iface]
def _dbus_property_get(self, dbus_iface, propname = None):
props = self.__dbus_interface_get(dbus_iface).get_props_func()
if propname is None:
return props
if propname not in props:
raise UnknownPropertyException()
return props[propname]
def _dbus_property_notify(self, dbus_iface, propname):
prop = self._dbus_property_get(dbus_iface, propname)
self.__dbus_interface_get(dbus_iface).prop_changed_func(self, { propname: prop })
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='s', out_signature='a{sv}')
def GetAll(self, iface):
if iface not in self.__dbus_ifaces.keys():
raise UnknownInterfaceException()
return self._get_dbus_properties(iface)
def GetAll(self, dbus_iface):
return self._dbus_property_get(dbus_iface)
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v')
def Get(self, iface, name):
if iface not in self.__dbus_ifaces.keys():
raise UnknownInterfaceException()
props = self._get_dbus_properties(iface)
if not name in props.keys():
raise UnknownPropertyException()
return props[name]
def Get(self, dbus_iface, name):
return self._dbus_property_get(dbus_iface, name)
###################################################################
IFACE_DEVICE = 'org.freedesktop.NetworkManager.Device'
@ -137,7 +148,7 @@ class Device(ExportedObj):
object_path = "/org/freedesktop/NetworkManager/Devices/%d" % Device.counter
Device.counter = Device.counter + 1
ExportedObj.__init__(self, bus, object_path)
self.add_dbus_interface(IFACE_DEVICE, self.__get_props)
self.add_dbus_interface(IFACE_DEVICE, self.__get_props, Device.PropertiesChanged)
self.iface = iface
self.udi = "/sys/devices/virtual/%s" % iface
@ -180,9 +191,7 @@ class Device(ExportedObj):
pass
def __notify(self, propname):
props = self._get_dbus_properties(IFACE_DEVICE)
changed = { propname: props[propname] }
Device.PropertiesChanged(self, changed)
self._dbus_property_notify(IFACE_DEVICE, propname)
@dbus.service.signal(IFACE_DEVICE, signature='a{sv}')
def PropertiesChanged(self, changed):
@ -212,7 +221,7 @@ PE_S390_SUBCHANNELS = "S390Subchannels"
class WiredDevice(Device):
def __init__(self, bus, iface, mac, subchannels):
Device.__init__(self, bus, iface, NM_DEVICE_TYPE_ETHERNET)
self.add_dbus_interface(IFACE_WIRED, self.__get_props)
self.add_dbus_interface(IFACE_WIRED, self.__get_props, WiredDevice.PropertiesChanged)
if mac is None:
self.mac = random_mac()
@ -232,9 +241,7 @@ class WiredDevice(Device):
return props
def __notify(self, propname):
props = self._get_dbus_properties(IFACE_WIRED)
changed = { propname: props[propname] }
WiredDevice.PropertiesChanged(self, changed)
self._dbus_property_notify(IFACE_WIRED, propname)
@dbus.service.signal(IFACE_WIRED, signature='a{sv}')
def PropertiesChanged(self, changed):
@ -250,7 +257,7 @@ PV_VLAN_ID = "VlanId"
class VlanDevice(Device):
def __init__(self, bus, iface):
Device.__init__(self, bus, iface, NM_DEVICE_TYPE_VLAN)
self.add_dbus_interface(IFACE_VLAN, self.__get_props)
self.add_dbus_interface(IFACE_VLAN, self.__get_props, VlanDevice.PropertiesChanged)
self.mac = random_mac()
self.carrier = False
@ -288,7 +295,7 @@ class WifiAp(ExportedObj):
path = "/org/freedesktop/NetworkManager/AccessPoint/%d" % WifiAp.counter
WifiAp.counter = WifiAp.counter + 1
ExportedObj.__init__(self, bus, path)
self.add_dbus_interface(IFACE_WIFI_AP, self.__get_props)
self.add_dbus_interface(IFACE_WIFI_AP, self.__get_props, WifiAp.PropertiesChanged)
self.ssid = ssid
if mac:
@ -327,9 +334,7 @@ class WifiAp(ExportedObj):
return props
def __notify(self, propname):
props = self._get_dbus_properties(IFACE_WIFI_AP)
changed = { propname: props[propname] }
WifiAp.PropertiesChanged(self, changed)
self._dbus_property_notify(IFACE_WIFI_AP, propname)
@dbus.service.signal(IFACE_WIFI_AP, signature='a{sv}')
def PropertiesChanged(self, changed):
@ -352,7 +357,7 @@ PW_WIRELESS_CAPABILITIES = "WirelessCapabilities"
class WifiDevice(Device):
def __init__(self, bus, iface):
Device.__init__(self, bus, iface, NM_DEVICE_TYPE_WIFI)
self.add_dbus_interface(IFACE_WIFI, self.__get_props)
self.add_dbus_interface(IFACE_WIFI, self.__get_props, WifiDevice.PropertiesChanged)
self.mac = random_mac()
self.aps = []
@ -404,9 +409,7 @@ class WifiDevice(Device):
return props
def __notify(self, propname):
props = self._get_dbus_properties(IFACE_WIFI)
changed = { propname: props[propname] }
WifiDevice.PropertiesChanged(self, changed)
self._dbus_property_notify(IFACE_WIFI, propname)
@dbus.service.signal(IFACE_WIFI, signature='a{sv}')
def PropertiesChanged(self, changed):
@ -440,7 +443,7 @@ class WimaxNsp(ExportedObj):
path = "/org/freedesktop/NetworkManager/Nsp/%d" % WimaxNsp.counter
WimaxNsp.counter = WimaxNsp.counter + 1
ExportedObj.__init__(self, bus, path)
self.add_dbus_interface(IFACE_WIMAX_NSP, self.__get_props)
self.add_dbus_interface(IFACE_WIMAX_NSP, self.__get_props, WimaxNsp.PropertiesChanged)
self.name = name
self.strength = random.randint(0, 100)
@ -465,9 +468,7 @@ class WimaxNsp(ExportedObj):
return props
def __notify(self, propname):
props = self._get_dbus_properties(IFACE_WIMAX_NSP)
changed = { propname: props[propname] }
WimaxNsp.PropertiesChanged(self, changed)
self._dbus_property_notify(IFACE_WIMAX_NSP, propname)
@dbus.service.signal(IFACE_WIMAX_NSP, signature='a{sv}')
def PropertiesChanged(self, changed):
@ -491,7 +492,7 @@ PX_ACTIVE_NSP = "ActiveNsp"
class WimaxDevice(Device):
def __init__(self, bus, iface):
Device.__init__(self, bus, iface, NM_DEVICE_TYPE_WIMAX)
self.add_dbus_interface(IFACE_WIMAX, self.__get_props)
self.add_dbus_interface(IFACE_WIMAX, self.__get_props, WimaxDevice.PropertiesChanged)
self.mac = random_mac()
self.bsid = random_mac()
@ -536,9 +537,7 @@ class WimaxDevice(Device):
return props
def __notify(self, propname):
props = self._get_dbus_properties(IFACE_WIMAX)
changed = { propname: props[propname] }
WimaxDevice.PropertiesChanged(self, changed)
self._dbus_property_notify(IFACE_WIMAX, propname)
@dbus.service.signal(IFACE_WIMAX, signature='a{sv}')
def PropertiesChanged(self, changed):
@ -583,7 +582,7 @@ class ActiveConnection(ExportedObj):
object_path = "/org/freedesktop/NetworkManager/ActiveConnection/%d" % ActiveConnection.counter
ActiveConnection.counter = ActiveConnection.counter + 1
ExportedObj.__init__(self, bus, object_path)
self.add_dbus_interface(IFACE_ACTIVE_CONNECTION, self.__get_props)
self.add_dbus_interface(IFACE_ACTIVE_CONNECTION, self.__get_props, ActiveConnection.PropertiesChanged)
self.device = device
self.conn = connection
@ -638,6 +637,7 @@ class UnknownConnectionException(dbus.DBusException):
_dbus_error_name = IFACE_NM + '.UnknownConnection'
PM_DEVICES = 'Devices'
PM_ALL_DEVICES = 'AllDevices'
PM_NETWORKING_ENABLED = 'NetworkingEnabled'
PM_WWAN_ENABLED = 'WwanEnabled'
PM_WWAN_HARDWARE_ENABLED = 'WwanHardwareEnabled'
@ -659,7 +659,7 @@ def set_device_ac_cb(device, ac):
class NetworkManager(ExportedObj):
def __init__(self, bus, object_path):
ExportedObj.__init__(self, bus, object_path)
self.add_dbus_interface(IFACE_NM, self.__get_props)
self.add_dbus_interface(IFACE_NM, self.__get_props, NetworkManager.PropertiesChanged)
self._bus = bus;
self.devices = []
@ -680,7 +680,11 @@ class NetworkManager(ExportedObj):
@dbus.service.method(dbus_interface=IFACE_NM, in_signature='', out_signature='ao')
def GetDevices(self):
return self._get_dbus_properties(IFACE_NM)[PM_DEVICES]
return to_path_array(self.devices)
@dbus.service.method(dbus_interface=IFACE_NM, in_signature='', out_signature='ao')
def GetAllDevices(self):
return to_path_array(self.devices)
@dbus.service.method(dbus_interface=IFACE_NM, in_signature='s', out_signature='o')
def GetDeviceByIpIface(self, ip_iface):
@ -799,6 +803,7 @@ class NetworkManager(ExportedObj):
def add_device(self, device):
self.devices.append(device)
self.__notify(PM_DEVICES)
self.__notify(PM_ALL_DEVICES)
self.DeviceAdded(to_path(device))
@dbus.service.signal(IFACE_NM, signature='o')
@ -808,12 +813,14 @@ class NetworkManager(ExportedObj):
def remove_device(self, device):
self.devices.remove(device)
self.__notify(PM_DEVICES)
self.__notify(PM_ALL_DEVICES)
self.DeviceRemoved(to_path(device))
################# D-Bus Properties interface
def __get_props(self):
props = {}
props[PM_DEVICES] = to_path_array(self.devices)
props[PM_ALL_DEVICES] = to_path_array(self.devices)
props[PM_NETWORKING_ENABLED] = True
props[PM_WWAN_ENABLED] = True
props[PM_WWAN_HARDWARE_ENABLED] = True
@ -831,9 +838,7 @@ class NetworkManager(ExportedObj):
return props
def __notify(self, propname):
props = self._get_dbus_properties(IFACE_NM)
changed = { propname: props[propname] }
NetworkManager.PropertiesChanged(self, changed)
self._dbus_property_notify(IFACE_NM, propname)
@dbus.service.signal(IFACE_NM, signature='a{sv}')
def PropertiesChanged(self, changed):