summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2014-10-09 12:42:29 -0500
committerThomas Haller <thaller@redhat.com>2015-08-19 13:05:30 +0200
commit50959dc20fae00dad81a4107da076a0077661dbe (patch)
tree8c832d9ba2e67bbbe274fc0bdf39e6c9666e76ce
parent572cea61f34a42dff29859eb6c1f61f59a887c03 (diff)
downloadNetworkManager-50959dc20fae00dad81a4107da076a0077661dbe.tar.gz
core: ensure platform links are compatible with the NMDevice
Ensure the platform link with the same interface name as the NMDevice is actually compatible with it before using the link for initialization of device properties. If not, remove the NMDevice and create a new one since there are kernel resources with a different type.
-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 {