diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index b54b2e0a0..2a2f234c1 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -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); diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index fe4553660..6f0c3e888 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -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); } @@ -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; diff --git a/src/devices/nm-device-generic.c b/src/devices/nm-device-generic.c index 37eae35bd..70ae48c67 100644 --- a/src/devices/nm-device-generic.c +++ b/src/devices/nm-device-generic.c @@ -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)); @@ -203,7 +203,7 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass) 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; diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index a647245f6..e0c3c62d7 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -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); diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index 4cf2a689f..64c3a5214 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -503,41 +503,43 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) if (!s_ip_tunnel) return FALSE; - /* 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; @@ -751,9 +753,9 @@ 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); } @@ -847,7 +849,7 @@ 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; diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c index 214b22703..46d4d391e 100644 --- a/src/devices/nm-device-tun.c +++ b/src/devices/nm-device-tun.c @@ -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,23 +249,25 @@ 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; } @@ -367,6 +374,7 @@ 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; diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 0f7b0d9f8..58263c5d0 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -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)); @@ -311,6 +311,9 @@ notify_new_device_added (NMDevice *device, NMDevice *new_device) if (priv->parent) return; + 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."); @@ -397,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 @@ -672,7 +678,7 @@ 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; diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c index f52d81e0a..65b3950dd 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/devices/nm-device-vxlan.c @@ -133,11 +133,11 @@ 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); } @@ -247,7 +247,7 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) 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 */ diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index f9607685f..63df7b71a 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -556,7 +556,7 @@ 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; } @@ -1152,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; } /** @@ -1385,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)); + } } } @@ -1449,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); @@ -1471,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)) @@ -1562,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; } @@ -1635,7 +1640,8 @@ link_changed (NMDevice *self, NMPlatformLink *info) * @plink: an existing platform link or %NULL * @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. * * Returns: %TRUE on success, %FALSE on error */ @@ -1648,7 +1654,7 @@ nm_device_realize (NMDevice *self, NMPlatformLink *plink, GError **error) return FALSE; } - NM_DEVICE_GET_CLASS (self)->setup (self, plink); + NM_DEVICE_GET_CLASS (self)->setup_start (self, plink); return TRUE; } @@ -1671,15 +1677,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; @@ -1742,7 +1753,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; @@ -1751,6 +1762,7 @@ 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) { @@ -1759,7 +1771,7 @@ setup (NMDevice *self, NMPlatformLink *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); @@ -1844,17 +1856,29 @@ 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); - - if (master > 0) - device_set_master (self, master); - } - priv->real = TRUE; +} + +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) +{ + 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)); } @@ -2810,7 +2834,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; } /** @@ -6547,14 +6572,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 * @@ -8461,6 +8478,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) @@ -10324,7 +10342,8 @@ 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; diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index c185184a7..268ed0629 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -174,14 +174,28 @@ 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(): @@ -466,7 +480,6 @@ 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); @@ -477,6 +490,8 @@ 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); diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 70bb6d628..bb73e8c45 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -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); } @@ -3040,7 +3040,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) 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; diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index aa892cc71..609e645e0 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -598,17 +598,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); } diff --git a/src/nm-manager.c b/src/nm-manager.c index 5c6bdb2a1..eb0ec6fff 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -58,7 +58,7 @@ #include "nmdbus-manager.h" #include "nmdbus-device.h" -static void add_device (NMManager *self, NMDevice *device, gboolean try_assume); +static void add_device (NMManager *self, NMDevice *device); static NMActiveConnection *_new_active_connection (NMManager *self, NMConnection *connection, @@ -487,8 +487,11 @@ find_device_by_ip_iface (NMManager *self, const gchar *iface) g_return_val_if_fail (iface != NULL, NULL); for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = g_slist_next (iter)) { - if (g_strcmp0 (nm_device_get_ip_iface (NM_DEVICE (iter->data)), iface) == 0) - return NM_DEVICE (iter->data); + NMDevice *candidate = iter->data; + + if ( nm_device_is_real (candidate) + && g_strcmp0 (nm_device_get_ip_iface (candidate), iface) == 0) + return candidate; } return NULL; } @@ -840,6 +843,8 @@ find_parent_device_for_connection (NMManager *self, NMConnection *connection) NMDevice *parent, *first_compatible = NULL; GSList *iter; + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + factory = nm_device_factory_manager_find_factory_for_connection (connection); if (!factory) return NULL; @@ -849,7 +854,7 @@ find_parent_device_for_connection (NMManager *self, NMConnection *connection) return NULL; /* Try as an interface name */ - parent = find_device_by_ip_iface (self, parent_name); + parent = find_device_by_iface (self, parent_name); if (parent) return parent; @@ -964,10 +969,9 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMDeviceFactory *factory; - GSList *iter; - char *iface = NULL; + GSList *connections, *iter; + gs_free char *iface = NULL; NMDevice *device = NULL, *parent = NULL; - gboolean nm_owned = FALSE; g_return_val_if_fail (NM_IS_MANAGER (self), NULL); g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); @@ -989,7 +993,7 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "interface name '%s' already created", iface); - goto out; + return NULL; } } @@ -1003,79 +1007,61 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError NM_MANAGER_ERROR_FAILED, "NetworkManager plugin for '%s' unavailable", nm_connection_get_connection_type (connection)); - goto out; + return NULL; } - nm_owned = !nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface); - device = nm_device_factory_create_device (factory, iface, NULL, connection, NULL, error); - if (device) { + if (!device) + return NULL; + + add_device (self, device); + + /* Add device takes a reference that NMManager still owns, so it's + * safe to unref here and still return @device. + */ + g_object_unref (device); + + /* Create backing resources if the device has any autoconnect connections */ + connections = nm_settings_get_connections (priv->settings); + for (iter = connections; iter; iter = g_slist_next (iter)) { + NMConnection *candidate = iter->data; + NMSettingConnection *s_con; + + if (!nm_device_check_connection_compatible (device, candidate)) + continue; + + s_con = nm_connection_get_setting_connection (candidate); + g_assert (s_con); + if (!nm_setting_connection_get_autoconnect (s_con)) + continue; + + /* Create any backing resources the device needs */ if (!nm_device_create_and_realize (device, connection, parent, error)) { - g_clear_object (&device); - goto out; + remove_device (self, device, FALSE, TRUE); + device = NULL; } - - if (nm_owned) - nm_device_set_nm_owned (device); - - /* If it was created by NM there's no connection to assume, but if it - * previously existed there might be one. - */ - add_device (self, device, !nm_owned); - - /* Add device takes a reference that NMManager still owns, so it's - * safe to unref here and still return @device. - */ - g_object_unref (device); + break; } -out: - g_free (iface); return device; } -static void -system_create_virtual_devices (NMManager *self) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GSList *iter, *connections; - - nm_log_dbg (LOGD_CORE, "creating virtual devices..."); - - connections = nm_settings_get_connections (priv->settings); - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = iter->data; - - /* We only create a virtual interface if the connection can autoconnect */ - if ( nm_connection_is_virtual (connection) - && nm_settings_connection_can_autoconnect (NM_SETTINGS_CONNECTION (connection))) - system_create_virtual_device (self, connection, NULL); - } - g_slist_free (connections); -} - static void connection_added (NMSettings *settings, - NMSettingsConnection *settings_connection, + NMConnection *connection, NMManager *manager) { - NMConnection *connection = NM_CONNECTION (settings_connection); - - if (nm_connection_is_virtual (connection)) { - NMSettingConnection *s_con = nm_connection_get_setting_connection (connection); - - g_assert (s_con); - if (nm_setting_connection_get_autoconnect (s_con)) - system_create_virtual_device (manager, connection, NULL); - } + if (nm_connection_is_virtual (connection)) + system_create_virtual_device (manager, connection, NULL); } static void connection_changed (NMSettings *settings, - NMSettingsConnection *connection, + NMConnection *connection, NMManager *manager) { - /* FIXME: Some virtual devices may need to be updated in the future. */ + if (nm_connection_is_virtual (connection)) + system_create_virtual_device (manager, connection, NULL); } static void @@ -1590,17 +1576,25 @@ assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *conn return TRUE; } +static gboolean +can_start_device (NMManager *self, NMDevice *device) +{ + return nm_device_is_real (device) + && !manager_sleeping (self) + && !nm_device_get_unmanaged (device, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT); +} + static gboolean recheck_assume_connection (NMDevice *device, gpointer user_data) { NMManager *self = NM_MANAGER (user_data); NMSettingsConnection *connection; - gboolean was_unmanaged = FALSE, success, generated; + gboolean was_unmanaged = FALSE, success, generated = FALSE; NMDeviceState state; - if (manager_sleeping (self)) - return FALSE; - if (nm_device_get_unmanaged (device, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT)) + g_return_val_if_fail (!nm_device_get_is_nm_owned (device), FALSE); + + if (!can_start_device (self, device)) return FALSE; state = nm_device_get_state (device); @@ -1671,26 +1665,51 @@ device_ip_iface_changed (NMDevice *device, } } +static void +device_realized (NMDevice *device, + GParamSpec *pspec, + NMManager *self) +{ + int ifindex; + gboolean assumed = FALSE; + + /* Loopback device never gets managed */ + ifindex = nm_device_get_ifindex (device); + if (ifindex > 0 && nm_platform_link_get_type (NM_PLATFORM_GET, ifindex) == NM_LINK_TYPE_LOOPBACK) + return; + + if (!can_start_device (self, device)) + return; + + if (!nm_device_get_is_nm_owned (device)) { + assumed = recheck_assume_connection (device, self); + g_signal_connect (device, NM_DEVICE_RECHECK_ASSUME, + G_CALLBACK (recheck_assume_connection), self); + } + + if (!assumed && nm_device_get_managed (device)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NOW_MANAGED); + } +} + /** * add_device: * @self: the #NMManager * @device: the #NMDevice to add - * @try_assume: %TRUE if existing connection (if any) should be assumed * * If successful, this function will increase the references count of @device. * Callers should decrease the reference count. */ static void -add_device (NMManager *self, NMDevice *device, gboolean try_assume) +add_device (NMManager *self, NMDevice *device) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - const char *iface, *driver, *type_desc; + const char *iface, *type_desc; const GSList *unmanaged_specs; - gboolean user_unmanaged, sleeping; - gboolean enabled = FALSE; RfKillType rtype; GSList *iter, *remove = NULL; - gboolean connection_assumed = FALSE; int ifindex; const char *dbus_path; @@ -1738,6 +1757,9 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume) g_signal_connect (device, "notify::" NM_DEVICE_IP_IFACE, G_CALLBACK (device_ip_iface_changed), self); + g_signal_connect (device, "notify::" NM_DEVICE_REAL, + G_CALLBACK (device_realized), + self); if (priv->startup) { g_signal_connect (device, "notify::" NM_DEVICE_HAS_PENDING_ACTION, @@ -1752,52 +1774,29 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume) rtype = nm_device_get_rfkill_type (device); if (rtype != RFKILL_TYPE_UNKNOWN) { nm_manager_rfkill_update (self, rtype); - enabled = radio_enabled_for_type (self, rtype, TRUE); - nm_device_set_enabled (device, enabled); + nm_device_set_enabled (device, radio_enabled_for_type (self, rtype, TRUE)); } iface = nm_device_get_iface (device); g_assert (iface); - type_desc = nm_device_get_type_desc (device); g_assert (type_desc); - driver = nm_device_get_driver (device); - if (!driver) - driver = "unknown"; - nm_log_info (LOGD_HW, "(%s): new %s device (carrier: %s, driver: '%s', ifindex: %d)", - iface, type_desc, - nm_device_has_capability (device, NM_DEVICE_CAP_CARRIER_DETECT) - ? (nm_device_has_carrier (device) ? "ON" : "OFF") - : "UNKNOWN", - driver, nm_device_get_ifindex (device)); + + nm_log_info (LOGD_HW, "(%s): new %s device", iface, type_desc); unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings); - user_unmanaged = nm_device_spec_match_list (device, unmanaged_specs); - nm_device_set_unmanaged_initial (device, NM_UNMANAGED_USER, user_unmanaged); - - sleeping = manager_sleeping (self); - nm_device_set_unmanaged_initial (device, NM_UNMANAGED_INTERNAL, sleeping); + nm_device_set_unmanaged_initial (device, + NM_UNMANAGED_USER, + nm_device_spec_match_list (device, unmanaged_specs)); + nm_device_set_unmanaged_initial (device, + NM_UNMANAGED_INTERNAL, + manager_sleeping (self)); dbus_path = nm_exported_object_export (NM_EXPORTED_OBJECT (device)); nm_log_dbg (LOGD_DEVICE, "(%s): exported as %s", nm_device_get_iface (device), dbus_path); nm_device_finish_init (device); - if (try_assume) { - connection_assumed = recheck_assume_connection (device, self); - g_signal_connect (device, NM_DEVICE_RECHECK_ASSUME, - G_CALLBACK (recheck_assume_connection), self); - } - - if (!connection_assumed && nm_device_get_managed (device)) { - nm_device_state_changed (device, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_NOW_MANAGED); - } - - /* Try to generate a default connection. If this fails because the link is - * not initialized, we will retry again in device_link_initialized_cb(). - */ nm_settings_device_added (priv->settings, device); g_signal_emit (self, signals[DEVICE_ADDED], 0, device); g_object_notify (G_OBJECT (self), NM_MANAGER_DEVICES); @@ -1808,11 +1807,6 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume) if (d != device) nm_device_notify_new_device_added (d, device); } - - /* New devices might be master interfaces for virtual interfaces; so we may - * need to create new virtual interfaces now. - */ - system_create_virtual_devices (self); } /*******************************************************************/ @@ -1824,9 +1818,10 @@ factory_device_added_cb (NMDeviceFactory *factory, { GError *error = NULL; - if (nm_device_realize (device, NULL, &error)) - add_device (NM_MANAGER (user_data), device, TRUE); - else { + if (nm_device_realize (device, NULL, &error)) { + add_device (NM_MANAGER (user_data), device); + nm_device_setup_finish (device, NULL); + } else { nm_log_warn (LOGD_DEVICE, "(%s): failed to realize device: %s", nm_device_get_iface (device), error->message); g_error_free (error); @@ -1881,6 +1876,26 @@ platform_link_added (NMManager *self, if (nm_manager_get_device_by_ifindex (self, ifindex)) return; + device = find_device_by_iface (self, plink->name); + if (device) { + if (!nm_device_is_real (device)) { + if (nm_device_realize (device, plink, &error)) + nm_device_setup_finish (device, plink); + else { + nm_log_warn (LOGD_DEVICE, "(%s): %s", plink->name, error->message); + g_clear_error (&error); + remove_device (self, device, FALSE, FALSE); + } + return; + } else if (!nm_device_realize (device, plink, &error)) { + nm_log_warn (LOGD_HW, "%s: factory failed to create device: %s", + plink->name, error->message); + g_clear_error (&error); + return; + } + return; + } + /* Try registered device factories */ factory = nm_device_factory_manager_find_factory_for_link_type (plink->type); if (factory) { @@ -1917,10 +1932,11 @@ platform_link_added (NMManager *self, if (device) { if (nm_plugin_missing) nm_device_set_nm_plugin_missing (device, TRUE); - if (nm_device_realize (device, plink, &error)) - add_device (self, device, plink->type != NM_LINK_TYPE_LOOPBACK); - else { - nm_log_warn (LOGD_HW, "%s: failed to realize device: %s", + if (nm_device_realize (device, plink, &error)) { + add_device (self, device); + nm_device_setup_finish (device, plink); + } else { + nm_log_warn (LOGD_DEVICE, "%s: failed to realize device: %s", plink->name, error->message); g_clear_error (&error); } @@ -1954,17 +1970,21 @@ _platform_link_cb_idle (PlatformLinkCbData *data) device = nm_manager_get_device_by_ifindex (self, data->ifindex); if (device) { if (nm_device_is_software (device)) { + /* Software devices stick around until their connection is removed */ if (!nm_device_unrealize (device, FALSE, &error)) { nm_log_warn (LOGD_DEVICE, "(%s): failed to unrealize: %s", - nm_device_get_iface (device), - error->message); + nm_device_get_iface (device), + error->message); g_clear_error (&error); + remove_device (self, device, FALSE, TRUE); } + } else { + /* Hardware devices always get removed when their kernel link is gone */ + remove_device (self, device, FALSE, TRUE); } - remove_device (self, device, FALSE, TRUE); } + g_object_remove_weak_pointer (G_OBJECT (self), (gpointer *) &data->self); } - g_object_remove_weak_pointer (G_OBJECT (self), (gpointer *) &data->self); } g_slice_free (PlatformLinkCbData, data); return G_SOURCE_REMOVE; @@ -2079,7 +2099,8 @@ impl_manager_get_devices (NMManager *self, const char *path; path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (iter->data)); - if (path) + if ( path + && nm_device_is_real (iter->data)) paths[i++] = path; } paths[i++] = NULL; @@ -2181,7 +2202,7 @@ find_master (NMManager *self, const char *master; NMDevice *master_device = NULL; NMSettingsConnection *master_connection = NULL; - GSList *iter, *connections = NULL; + GSList *iter; s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); @@ -2191,7 +2212,7 @@ find_master (NMManager *self, return TRUE; /* success, but no master */ /* Try as an interface name first */ - master_device = find_device_by_ip_iface (self, master); + master_device = find_device_by_iface (self, master); if (master_device) { if (master_device == device) { g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, @@ -2223,23 +2244,6 @@ find_master (NMManager *self, break; } } - } else { - /* Might be a virtual interface that hasn't been created yet, so - * look through the interface names of connections that require - * virtual interfaces and see if one of their virtual interface - * names matches the master. - */ - connections = nm_manager_get_activatable_connections (self); - for (iter = connections; iter && !master_connection; iter = g_slist_next (iter)) { - NMSettingsConnection *candidate = iter->data; - char *vname; - - vname = get_virtual_iface_name (self, NM_CONNECTION (candidate), NULL, NULL); - if (g_strcmp0 (master, vname) == 0 && is_compatible_with_slave (NM_CONNECTION (candidate), connection)) - master_connection = candidate; - g_free (vname); - } - g_slist_free (connections); } } @@ -2333,7 +2337,7 @@ ensure_master_active_connection (NMManager *self, /* If the device is disconnected, find a compatible connection and * activate it on the device. */ - if (master_state == NM_DEVICE_STATE_DISCONNECTED) { + if (master_state == NM_DEVICE_STATE_DISCONNECTED || !nm_device_is_real (master_device)) { GSList *connections; g_assert (master_connection == NULL); @@ -2394,9 +2398,11 @@ ensure_master_active_connection (NMManager *self, continue; found_device = TRUE; - master_state = nm_device_get_state (candidate); - if (master_state != NM_DEVICE_STATE_DISCONNECTED) - continue; + if (!nm_device_is_software (candidate)) { + master_state = nm_device_get_state (candidate); + if (nm_device_is_real (candidate) && master_state != NM_DEVICE_STATE_DISCONNECTED) + continue; + } master_ac = nm_manager_activate_connection (self, master_connection, @@ -2683,6 +2689,17 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * return FALSE; } + /* Create any backing resources the device needs */ + if (!nm_device_is_real (device)) { + NMDevice *parent; + + parent = find_parent_device_for_connection (self, (NMConnection *) connection); + if (!nm_device_create_and_realize (device, (NMConnection *) connection, parent, error)) { + g_prefix_error (error, "%s failed to create resources: ", nm_device_get_iface (device)); + return FALSE; + } + } + /* Try to find the master connection/device if the connection has a dependency */ if (!find_master (self, applied, device, &master_connection, &master_device, &master_ac, @@ -3086,7 +3103,7 @@ validate_activation_request (NMManager *self, if (!iface) goto error; - device = find_device_by_ip_iface (self, iface); + device = find_device_by_iface (self, iface); g_free (iface); } } @@ -4209,6 +4226,7 @@ gboolean nm_manager_start (NMManager *self, GError **error) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + GSList *iter, *connections; guint i; if (!nm_settings_start (priv->settings, error)) @@ -4256,11 +4274,14 @@ nm_manager_start (NMManager *self, GError **error) /* Load VPN plugins */ priv->vpn_manager = g_object_ref (nm_vpn_manager_get ()); - /* - * Connections added before the manager is started do not emit + /* Connections added before the manager is started do not emit * connection-added signals thus devices have to be created manually. */ - system_create_virtual_devices (self); + nm_log_dbg (LOGD_CORE, "creating virtual devices..."); + connections = nm_settings_get_connections (priv->settings); + for (iter = connections; iter; iter = iter->next) + connection_added (priv->settings, NM_CONNECTION (iter->data), self); + g_slist_free (connections); priv->devices_inited = TRUE; @@ -5067,6 +5088,12 @@ nm_manager_init (NMManager *manager) priv->metered = NM_METERED_UNKNOWN; } +static gboolean +device_is_real (GObject *device, gpointer user_data) +{ + return nm_device_is_real (NM_DEVICE (device)); +} + static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) @@ -5139,7 +5166,7 @@ get_property (GObject *object, guint prop_id, g_value_set_boolean (value, priv->sleeping); break; case PROP_DEVICES: - nm_utils_g_value_set_object_path_array (value, priv->devices, NULL, NULL); + nm_utils_g_value_set_object_path_array (value, priv->devices, device_is_real, NULL); break; case PROP_METERED: g_value_set_uint (value, priv->metered);