mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-03 13:40:39 +01:00
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.
This commit is contained in:
parent
4dbaac4ba2
commit
20906ca7a3
19 changed files with 125 additions and 29 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue