diff options
-rw-r--r-- | src/devices/nm-device-bond.c | 2 | ||||
-rw-r--r-- | src/devices/nm-device-bridge.c | 2 | ||||
-rw-r--r-- | src/devices/nm-device-ethernet.c | 2 | ||||
-rw-r--r-- | src/devices/nm-device-generic.c | 2 | ||||
-rw-r--r-- | src/devices/nm-device-gre.c | 2 | ||||
-rw-r--r-- | src/devices/nm-device-infiniband.c | 2 | ||||
-rw-r--r-- | src/devices/nm-device-macvlan.c | 2 | ||||
-rw-r--r-- | src/devices/nm-device-private.h | 7 | ||||
-rw-r--r-- | src/devices/nm-device-tun.c | 2 | ||||
-rw-r--r-- | src/devices/nm-device-veth.c | 2 | ||||
-rw-r--r-- | src/devices/nm-device-vlan.c | 2 | ||||
-rw-r--r-- | src/devices/nm-device-vxlan.c | 2 | ||||
-rw-r--r-- | src/devices/nm-device.c | 72 | ||||
-rw-r--r-- | src/devices/nm-device.h | 2 | ||||
-rw-r--r-- | src/devices/team/nm-device-team.c | 2 | ||||
-rw-r--r-- | src/devices/wifi/nm-device-olpc-mesh.c | 2 | ||||
-rw-r--r-- | src/devices/wifi/nm-device-wifi.c | 2 | ||||
-rw-r--r-- | src/nm-manager.c | 37 | ||||
-rw-r--r-- | src/nm-types.h | 2 |
19 files changed, 122 insertions, 26 deletions
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index 4baca18261..97a98b257d 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -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; diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index 89c7c5a347..ff710a24e1 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -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; diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index e4a0db0690..27290d8c29 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -1669,7 +1669,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; diff --git a/src/devices/nm-device-generic.c b/src/devices/nm-device-generic.c index 63ed18ff8c..dc542ff3fb 100644 --- a/src/devices/nm-device-generic.c +++ b/src/devices/nm-device-generic.c @@ -181,7 +181,7 @@ 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->dispose = dispose; object_class->get_property = get_property; diff --git a/src/devices/nm-device-gre.c b/src/devices/nm-device-gre.c index ddd913b586..e328afb529 100644 --- a/src/devices/nm-device-gre.c +++ b/src/devices/nm-device-gre.c @@ -179,6 +179,8 @@ nm_device_gre_class_init (NMDeviceGreClass *klass) g_type_class_add_private (klass, sizeof (NMDeviceGrePrivate)); + NM_DEVICE_CLASS_DECLARE_TYPES(klass, NULL, NM_LINK_TYPE_GRE, NM_LINK_TYPE_GRETAP) + object_class->constructed = constructed; object_class->get_property = get_property; diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index b25d3eaaef..29cc93484e 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -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; diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c index 743e2db21e..2333954352 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/devices/nm-device-macvlan.c @@ -136,6 +136,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; diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h index 33f51bfb6e..5010e90655 100644 --- a/src/devices/nm-device-private.h +++ b/src/devices/nm-device-private.h @@ -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 */ diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c index d37e7faec1..286207db22 100644 --- a/src/devices/nm-device-tun.c +++ b/src/devices/nm-device-tun.c @@ -210,6 +210,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; diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c index d80624857e..d143ccf7b9 100644 --- a/src/devices/nm-device-veth.c +++ b/src/devices/nm-device-veth.c @@ -152,6 +152,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; diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 99f092d730..788a4fdcb0 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -606,7 +606,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)); diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c index b84e9aa82d..dedd6d5666 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/devices/nm-device-vxlan.c @@ -247,6 +247,8 @@ 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; diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 1a92ed88f5..fe0596001b 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1575,20 +1575,71 @@ link_changed (NMDevice *self, NMPlatformLink *info) nm_device_set_carrier (self, info->connected); } +#define SET_COMPATIBLE(v, c) if (v) *v = c; + +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) { + SET_COMPATIBLE(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; + } + + SET_COMPATIBLE(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. 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) { + SET_COMPATIBLE(out_compatible, TRUE); + + if (plink) { + if (g_strcmp0 (nm_device_get_iface (self), plink->name) != 0) { + SET_COMPATIBLE(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)) @@ -1707,7 +1758,7 @@ setup_start (NMDevice *self, NMPlatformLink *plink) 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); } @@ -1812,6 +1863,8 @@ setup_finish (NMDevice *self, NMPlatformLink *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; @@ -9378,6 +9431,7 @@ set_property (GObject *object, guint prop_id, NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); const char *hw_addr, *p; guint count; + int ifindex; switch (prop_id) { case PROP_UDI: @@ -9390,9 +9444,17 @@ set_property (GObject *object, guint prop_id, if (g_value_get_string (value)) { 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); + + ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->iface); + if (ifindex > 0) { + NMLinkType link_type = nm_platform_link_get_type (NM_PLATFORM_GET, ifindex); + + g_return_if_fail (link_type > NM_LINK_TYPE_UNKNOWN); + if (link_type_compatible (self, link_type, NULL, NULL)) { + priv->ifindex = ifindex; + priv->up = nm_platform_link_is_up (NM_PLATFORM_GET, priv->ifindex); + } + } } break; case PROP_DRIVER: diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 5a4880b856..269a1327b9 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -121,6 +121,7 @@ typedef struct { NMExportedObjectClass parent; const char *connection_type; + const NMLinkType *link_types; void (*state_changed) (NMDevice *device, NMDeviceState new_state, @@ -471,6 +472,7 @@ 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, diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index ea9f8714b3..a5d934c6e2 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -783,7 +783,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; diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index c3699da3a4..28f7cf835e 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -512,6 +512,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; diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index c34e1ce88a..909cf581e6 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -2986,6 +2986,8 @@ 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; diff --git a/src/nm-manager.c b/src/nm-manager.c index fe7c005061..5db7313631 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1796,7 +1796,7 @@ factory_device_added_cb (NMDeviceFactory *factory, { GError *error = NULL; - if (nm_device_realize (device, NULL, &error)) { + if (nm_device_realize (device, NULL, NULL, &error)) { add_device (NM_MANAGER (user_data), device); nm_device_setup_finish (device, NULL); } else { @@ -1848,22 +1848,29 @@ platform_link_added (NMManager *self, 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); - } + gboolean compatible = FALSE; + + if (nm_device_is_real (device)) 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); + + if (nm_device_realize (device, plink, &compatible, &error)) { + /* Success */ + nm_device_setup_finish (device, plink); return; } - return; + + nm_log_warn (LOGD_DEVICE, "(%s): %s", plink->name, error->message); + remove_device (self, device, FALSE, FALSE); + g_clear_error (&error); + + if (compatible) { + /* Device compatible with platform link, but some other fatal error + * happened during realization. + */ + return; + } + + /* Fall through and create new compatible device for the link */ } /* Try registered device factories */ @@ -1902,7 +1909,7 @@ 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)) { + if (nm_device_realize (device, plink, NULL, &error)) { add_device (self, device); nm_device_setup_finish (device, plink); } else { diff --git a/src/nm-types.h b/src/nm-types.h index b8ed972ee9..88b90f4245 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -119,6 +119,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 { |