summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/devices/nm-device-bond.c2
-rw-r--r--src/devices/nm-device-bridge.c2
-rw-r--r--src/devices/nm-device-ethernet.c2
-rw-r--r--src/devices/nm-device-generic.c2
-rw-r--r--src/devices/nm-device-gre.c2
-rw-r--r--src/devices/nm-device-infiniband.c2
-rw-r--r--src/devices/nm-device-macvlan.c2
-rw-r--r--src/devices/nm-device-private.h7
-rw-r--r--src/devices/nm-device-tun.c2
-rw-r--r--src/devices/nm-device-veth.c2
-rw-r--r--src/devices/nm-device-vlan.c2
-rw-r--r--src/devices/nm-device-vxlan.c2
-rw-r--r--src/devices/nm-device.c72
-rw-r--r--src/devices/nm-device.h2
-rw-r--r--src/devices/team/nm-device-team.c2
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.c2
-rw-r--r--src/devices/wifi/nm-device-wifi.c2
-rw-r--r--src/nm-manager.c37
-rw-r--r--src/nm-types.h2
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 {