summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2014-10-09 12:42:29 -0500
committerThomas Haller <thaller@redhat.com>2015-12-04 12:16:41 +0100
commit20906ca7a338661776a0a8364e41df9fd0ee3467 (patch)
tree5193316fb04f0b16aa1ebc901a2da0c77c2212c4
parent4dbaac4ba24ebc8b257fffe5197cc8e362804a58 (diff)
downloadNetworkManager-20906ca7a338661776a0a8364e41df9fd0ee3467.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-infiniband.c2
-rw-r--r--src/devices/nm-device-ip-tunnel.c7
-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.c73
-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, 125 insertions, 29 deletions
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index 359b3c4abf..033c57214f 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 2a2f234c16..e152bb38b9 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 6f0c3e8881..65f8716d8e 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -1706,7 +1706,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceEthernetPrivate));
- parent_class->connection_type = NM_SETTING_WIRED_SETTING_NAME;
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRED_SETTING_NAME, NM_LINK_TYPE_ETHERNET)
/* virtual methods */
object_class->constructor = constructor;
diff --git a/src/devices/nm-device-generic.c b/src/devices/nm-device-generic.c
index 70ae48c678..0be55d54f0 100644
--- a/src/devices/nm-device-generic.c
+++ b/src/devices/nm-device-generic.c
@@ -196,7 +196,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->constructor = constructor;
object_class->dispose = dispose;
diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c
index e0c3c62d76..95f69c93c3 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-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c
index 64c3a52146..84ab7cd69d 100644
--- a/src/devices/nm-device-ip-tunnel.c
+++ b/src/devices/nm-device-ip-tunnel.c
@@ -852,7 +852,12 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass)
device_class->setup_start = setup_start;
device_class->unrealize = unrealize;
- device_class->connection_type = NM_SETTING_IP_TUNNEL_SETTING_NAME;
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass,
+ NM_SETTING_IP_TUNNEL_SETTING_NAME,
+ NM_LINK_TYPE_GRE,
+ NM_LINK_TYPE_IP6TNL,
+ NM_LINK_TYPE_IPIP,
+ NM_LINK_TYPE_SIT);
/* properties */
g_object_class_install_property
diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c
index e2dd891c1a..aed28816ff 100644
--- a/src/devices/nm-device-macvlan.c
+++ b/src/devices/nm-device-macvlan.c
@@ -143,6 +143,8 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceMacvlanPrivate));
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP)
+
object_class->constructed = constructed;
object_class->get_property = get_property;
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 46d4d391e8..af37c3184d 100644
--- a/src/devices/nm-device-tun.c
+++ b/src/devices/nm-device-tun.c
@@ -364,6 +364,8 @@ nm_device_tun_class_init (NMDeviceTunClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceTunPrivate));
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_TUN, NM_LINK_TYPE_TAP)
+
object_class->get_property = get_property;
object_class->set_property = set_property;
diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c
index 9c22ad1e5c..1fd2a5a834 100644
--- a/src/devices/nm-device-veth.c
+++ b/src/devices/nm-device-veth.c
@@ -153,6 +153,8 @@ nm_device_veth_class_init (NMDeviceVethClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceVethPrivate));
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_VETH)
+
object_class->get_property = get_property;
object_class->dispose = dispose;
diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c
index 58263c5d0c..734a483bdc 100644
--- a/src/devices/nm-device-vlan.c
+++ b/src/devices/nm-device-vlan.c
@@ -667,7 +667,7 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
- parent_class->connection_type = NM_SETTING_VLAN_SETTING_NAME;
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_VLAN_SETTING_NAME, NM_LINK_TYPE_VLAN)
g_type_class_add_private (object_class, sizeof (NMDeviceVlanPrivate));
diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c
index 65b3950dd4..ad2f2ba44f 100644
--- a/src/devices/nm-device-vxlan.c
+++ b/src/devices/nm-device-vxlan.c
@@ -244,6 +244,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 63df7b71aa..5435440e2d 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -1634,20 +1634,69 @@ link_changed (NMDevice *self, NMPlatformLink *info)
nm_device_set_carrier (self, info->connected);
}
+static gboolean
+link_type_compatible (NMDevice *self,
+ NMLinkType link_type,
+ gboolean *out_compatible,
+ GError **error)
+{
+ NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self);
+ guint i = 0;
+
+ if (!klass->link_types) {
+ NM_SET_OUT (out_compatible, FALSE);
+ g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
+ "Device does not support platform links");
+ return FALSE;
+ }
+
+ for (i = 0; klass->link_types[i] > NM_LINK_TYPE_UNKNOWN; i++) {
+ if (klass->link_types[i] == link_type)
+ return TRUE;
+ if (klass->link_types[i] == NM_LINK_TYPE_ANY)
+ return TRUE;
+ }
+
+ NM_SET_OUT (out_compatible, FALSE);
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
+ "Device does not support platform link type 0x%X",
+ link_type);
+ return FALSE;
+}
+
/**
* nm_device_realize():
* @self: the #NMDevice
* @plink: an existing platform link or %NULL
+ * @out_compatible: %TRUE on return if @self is compatible with @plink
* @error: location to store error, or %NULL
*
* Initializes and sets up the device using existing backing resources. Before
* the device is ready for use nm_device_setup_finish() must be called.
+ * @out_compatible will only be set if @plink is not %NULL, and
*
* Returns: %TRUE on success, %FALSE on error
*/
gboolean
-nm_device_realize (NMDevice *self, NMPlatformLink *plink, GError **error)
+nm_device_realize (NMDevice *self,
+ NMPlatformLink *plink,
+ gboolean *out_compatible,
+ GError **error)
{
+ NM_SET_OUT (out_compatible, TRUE);
+
+ if (plink) {
+ if (g_strcmp0 (nm_device_get_iface (self), plink->name) != 0) {
+ NM_SET_OUT (out_compatible, FALSE);
+ g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
+ "Device interface name does not match platform link");
+ return FALSE;
+ }
+
+ if (!link_type_compatible (self, plink->type, out_compatible, error))
+ return FALSE;
+ }
+
/* Try to realize the device from existing resources */
if (NM_DEVICE_GET_CLASS (self)->realize) {
if (!NM_DEVICE_GET_CLASS (self)->realize (self, plink, error))
@@ -1766,7 +1815,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);
}
@@ -1871,6 +1920,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;
@@ -10073,6 +10124,7 @@ set_property (GObject *object, guint prop_id,
const char *hw_addr, *p;
guint count;
gboolean val_bool;
+ const NMPlatformLink *pllink;
switch (prop_id) {
case PROP_UDI:
@@ -10082,12 +10134,19 @@ set_property (GObject *object, guint prop_id,
}
break;
case PROP_IFACE:
- if (g_value_get_string (value)) {
+ p = g_value_get_string (value);
+ if (p) {
+
g_free (priv->iface);
- priv->iface = g_value_dup_string (value);
- priv->ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->iface);
- if (priv->ifindex > 0)
- priv->up = nm_platform_link_is_up (NM_PLATFORM_GET, priv->ifindex);
+ priv->iface = g_strdup (p);
+
+ pllink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, priv->iface);
+ if (pllink) {
+ if (link_type_compatible (self, pllink->type, NULL, NULL)) {
+ priv->ifindex = pllink->ifindex;
+ priv->up = nm_platform_link_is_up (NM_PLATFORM_GET, priv->ifindex);
+ }
+ }
}
break;
case PROP_DRIVER:
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index 268ed06294..55f05c4fab 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -123,6 +123,7 @@ typedef struct {
NMExportedObjectClass parent;
const char *connection_type;
+ const NMLinkType *link_types;
void (*state_changed) (NMDevice *device,
NMDeviceState new_state,
@@ -485,6 +486,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 4bbe4c9ce7..fdc603364d 100644
--- a/src/devices/team/nm-device-team.c
+++ b/src/devices/team/nm-device-team.c
@@ -802,7 +802,7 @@ nm_device_team_class_init (NMDeviceTeamClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceTeamPrivate));
- parent_class->connection_type = NM_SETTING_TEAM_SETTING_NAME;
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_TEAM_SETTING_NAME, NM_LINK_TYPE_TEAM)
/* virtual methods */
object_class->constructed = constructed;
diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c
index 38f1f88dd4..8898c59cd6 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.c
+++ b/src/devices/wifi/nm-device-olpc-mesh.c
@@ -511,6 +511,8 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceOlpcMeshPrivate));
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_OLPC_MESH_SETTING_NAME, NM_LINK_TYPE_OLPC_MESH)
+
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->set_property = set_property;
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index bb73e8c456..72540efed4 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -3034,6 +3034,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 eb0ec6fffc..ba926157f8 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -1818,7 +1818,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 {
@@ -1878,22 +1878,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 */
@@ -1932,7 +1939,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 16ae6fa7b4..65d6193be2 100644
--- a/src/nm-types.h
+++ b/src/nm-types.h
@@ -126,6 +126,8 @@ typedef enum {
NM_LINK_TYPE_BRIDGE = 0x10000 | 0x20000,
NM_LINK_TYPE_BOND,
NM_LINK_TYPE_TEAM,
+
+ NM_LINK_TYPE_ANY = G_MAXUINT32,
} NMLinkType;
typedef enum {