core: give better error reason why device is incompatible with profile

Note the special error codes  NM_UTILS_ERROR_CONNECTION_AVAILABLE_*.
This will be used to determine, whether the profile is fundamentally
incompatible with the device, or whether just some other properties
mismatch. That information will be importand during a plain `nmcli
connection up`, where NetworkManager searches all devices for a device
to activate. If no device is found (and multiple errors happened),
we want to show the error that is most likely relevant for the user.

Also note, how NMDevice's check_connection_compatible() uses the new
class field "device_class->connection_type_check_compatible" to simplify
checks for compatible profiles.

The error reason is still unused.
This commit is contained in:
Thomas Haller 2018-06-27 17:00:55 +02:00
parent 570e1fa75b
commit 33a88ca566
36 changed files with 525 additions and 453 deletions

View file

@ -225,6 +225,40 @@ nm_connection_get_setting_by_name (NMConnection *connection, const char *name)
return type ? _connection_get_setting (connection, type) : NULL;
}
/*****************************************************************************/
gpointer /* (NMSetting *) */
_nm_connection_check_main_setting (NMConnection *connection,
const char *setting_name,
GError **error)
{
NMSetting *setting;
nm_assert (NM_IS_CONNECTION (connection));
nm_assert (setting_name);
if (!nm_connection_is_type (connection, setting_name)) {
nm_utils_error_set (error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
"connection type is not \"%s\"",
setting_name);
return NULL;
}
setting = nm_connection_get_setting_by_name (connection, setting_name);
if (!setting) {
nm_utils_error_set (error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
"connection misses \"%s\" settings",
setting_name);
return NULL;
}
return setting;
}
/*****************************************************************************/
static gboolean
validate_permissions_type (GVariant *variant, GError **error)
{

View file

@ -140,6 +140,10 @@ gboolean _nm_connection_replace_settings (NMConnection *connection,
NMSettingParseFlags parse_flags,
GError **error);
gpointer _nm_connection_check_main_setting (NMConnection *connection,
const char *setting_name,
GError **error);
/**
* NMSettingVerifyResult:
* @NM_SETTING_VERIFY_SUCCESS: the setting verifies successfully

View file

@ -87,25 +87,23 @@ get_generic_capabilities (NMDevice *dev)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingAdsl *s_adsl;
const char *protocol;
if (!NM_DEVICE_CLASS (nm_device_adsl_parent_class)->check_connection_compatible (device, connection))
return FALSE;
if (!nm_connection_is_type (connection, NM_SETTING_ADSL_SETTING_NAME))
if (!NM_DEVICE_CLASS (nm_device_adsl_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_adsl = nm_connection_get_setting_adsl (connection);
if (!s_adsl)
return FALSE;
/* FIXME: we don't yet support IPoATM */
protocol = nm_setting_adsl_get_protocol (s_adsl);
if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM) == 0)
if (nm_streq0 (protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM)) {
/* FIXME: we don't yet support IPoATM */
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"IPoATM protocol is not yet supported");
return FALSE;
}
return TRUE;
}
@ -678,6 +676,8 @@ nm_device_adsl_class_init (NMDeviceAdslClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_adsl);
device_class->connection_type_check_compatible = NM_SETTING_ADSL_SETTING_NAME;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->check_connection_compatible = check_connection_compatible;

View file

@ -157,36 +157,36 @@ can_auto_connect (NMDevice *device,
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device);
NMSettingConnection *s_con;
NMSettingBluetooth *s_bt;
const char *bdaddr;
guint32 bt_type;
if (!NM_DEVICE_CLASS (nm_device_bt_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_BLUETOOTH_SETTING_NAME))
return FALSE;
s_bt = nm_connection_get_setting_bluetooth (connection);
if (!s_bt)
if (!NM_DEVICE_CLASS (nm_device_bt_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
bt_type = get_connection_bt_type (connection);
if (!(bt_type & priv->capabilities))
if (!NM_FLAGS_ALL (priv->capabilities, bt_type)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"device does not support bluetooth type of profile");
return FALSE;
}
s_bt = nm_connection_get_setting_bluetooth (connection);
bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt);
if (!bdaddr)
if (!bdaddr) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"profile lacks bdaddr setting");
return FALSE;
if (!nm_utils_hwaddr_matches (priv->bdaddr, -1, bdaddr, -1))
}
if (!nm_utils_hwaddr_matches (priv->bdaddr, -1, bdaddr, -1)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"devices bdaddr setting mismatches");
return FALSE;
}
return TRUE;
}
@ -1184,6 +1184,8 @@ nm_device_bt_class_init (NMDeviceBtClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_bluetooth);
device_class->connection_type_check_compatible = NM_SETTING_BLUETOOTH_SETTING_NAME;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->can_auto_connect = can_auto_connect;
device_class->deactivate = deactivate;

View file

@ -174,21 +174,6 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
return NM_DEVICE_CLASS (nm_device_6lowpan_parent_class)->is_available (device, flags);
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSetting6Lowpan *s_6lowpan;
if (!NM_DEVICE_CLASS (nm_device_6lowpan_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_6lowpan = nm_connection_get_setting_6lowpan (connection);
if (!s_6lowpan)
return FALSE;
return TRUE;
}
static gboolean
complete_connection (NMDevice *device,
NMConnection *connection,
@ -249,7 +234,8 @@ update_connection (NMDevice *device, NMConnection *connection)
/* Don't change a parent specified by UUID if it's still valid */
parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device), setting_parent);
if (parent_connection && nm_device_check_connection_compatible (parent_device, parent_connection))
if ( parent_connection
&& nm_device_check_connection_compatible (parent_device, parent_connection, NULL))
new_parent = NULL;
}
if (new_parent)
@ -299,10 +285,10 @@ nm_device_6lowpan_class_init (NMDevice6LowpanClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_6lowpan);
device_class->connection_type_supported = NM_SETTING_6LOWPAN_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_6LOWPAN_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_6LOWPAN);
device_class->act_stage1_prepare = act_stage1_prepare;
device_class->check_connection_compatible = check_connection_compatible;
device_class->complete_connection = complete_connection;
device_class->create_and_realize = create_and_realize;
device_class->get_generic_capabilities = get_generic_capabilities;

View file

@ -55,23 +55,6 @@ get_generic_capabilities (NMDevice *dev)
return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingBond *s_bond;
if (!NM_DEVICE_CLASS (nm_device_bond_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_bond = nm_connection_get_setting_bond (connection);
if (!s_bond || !nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME))
return FALSE;
/* FIXME: match bond properties like mode, etc? */
return TRUE;
}
static gboolean
complete_connection (NMDevice *device,
NMConnection *connection,
@ -636,11 +619,11 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_bond);
device_class->connection_type_supported = NM_SETTING_BOND_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_BOND_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_BOND);
device_class->is_master = TRUE;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->check_connection_compatible = check_connection_compatible;
device_class->complete_connection = complete_connection;
device_class->update_connection = update_connection;

View file

@ -95,23 +95,29 @@ check_connection_available (NMDevice *device,
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingBridge *s_bridge;
const char *mac_address;
if (!NM_DEVICE_CLASS (nm_device_bridge_parent_class)->check_connection_compatible (device, connection))
if (!NM_DEVICE_CLASS (nm_device_bridge_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_bridge = nm_connection_get_setting_bridge (connection);
if (!s_bridge)
return FALSE;
if ( nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME)
&& _nm_connection_get_setting_bluetooth_for_nap (connection)) {
s_bridge = nm_connection_get_setting_bridge (connection);
if (!s_bridge) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"missing bridge setting for bluetooth NAP profile");
return FALSE;
}
if (!nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME)) {
if ( nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME)
&& _nm_connection_get_setting_bluetooth_for_nap (connection)) {
/* a bluetooth NAP connection is handled by the bridge */
} else
/* a bluetooth NAP connection is handled by the bridge.
*
* Proceed... */
} else {
s_bridge = _nm_connection_check_main_setting (connection, NM_SETTING_BRIDGE_SETTING_NAME, error);
if (!s_bridge)
return FALSE;
}
@ -120,8 +126,11 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
const char *hw_addr;
hw_addr = nm_device_get_hw_address (device);
if (!hw_addr || !nm_utils_hwaddr_matches (hw_addr, -1, mac_address, -1))
if (!hw_addr || !nm_utils_hwaddr_matches (hw_addr, -1, mac_address, -1)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"mac address mismatches");
return FALSE;
}
}
return TRUE;

View file

@ -117,21 +117,6 @@ create_and_realize (NMDevice *device,
return TRUE;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingDummy *s_dummy;
if (!NM_DEVICE_CLASS (nm_device_dummy_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_dummy = nm_connection_get_setting_dummy (connection);
if (!s_dummy)
return FALSE;
return TRUE;
}
static NMActStageReturn
act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
{
@ -176,10 +161,10 @@ nm_device_dummy_class_init (NMDeviceDummyClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_dummy);
device_class->connection_type_supported = NM_SETTING_DUMMY_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_DUMMY_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_DUMMY);
device_class->complete_connection = complete_connection;
device_class->check_connection_compatible = check_connection_compatible;
device_class->create_and_realize = create_and_realize;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->update_connection = update_connection;

View file

@ -343,23 +343,21 @@ match_subchans (NMDeviceEthernet *self, NMSettingWired *s_wired, gboolean *try_m
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device);
NMSettingWired *s_wired;
if (!NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->check_connection_compatible (device, connection))
if (!NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_wired = nm_connection_get_setting_wired (connection);
if (nm_connection_is_type (connection, NM_SETTING_PPPOE_SETTING_NAME)) {
/* NOP */
} else if (nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)) {
s_wired = nm_connection_get_setting_wired (connection);
} else {
s_wired = _nm_connection_check_main_setting (connection, NM_SETTING_WIRED_SETTING_NAME, error);
if (!s_wired)
return FALSE;
} else
return FALSE;
}
if (s_wired) {
const char *mac, *perm_hw_addr;
@ -367,28 +365,43 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
const char * const *mac_blacklist;
int i;
if (!match_subchans (self, s_wired, &try_mac))
if (!match_subchans (self, s_wired, &try_mac)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"s390 subchannels don't match");
return FALSE;
}
perm_hw_addr = nm_device_get_permanent_hw_address (device);
mac = nm_setting_wired_get_mac_address (s_wired);
if (perm_hw_addr) {
if (try_mac && mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1))
if ( try_mac
&& mac
&& !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"permanent MAC address doesn't match");
return FALSE;
}
/* Check for MAC address blacklist */
mac_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired);
for (i = 0; mac_blacklist[i]; i++) {
if (!nm_utils_hwaddr_valid (mac_blacklist[i], ETH_ALEN)) {
g_warn_if_reached ();
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"invalid MAC in blacklist");
return FALSE;
}
if (nm_utils_hwaddr_matches (mac_blacklist[i], -1, perm_hw_addr, -1))
if (nm_utils_hwaddr_matches (mac_blacklist[i], -1, perm_hw_addr, -1)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"permanent MAC address of device blacklisted");
return FALSE;
}
}
} else if (mac)
} else if (mac) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"device has no permanent MAC address to match");
return FALSE;
}
}
return TRUE;

View file

@ -86,19 +86,19 @@ realize_start_notify (NMDevice *device, const NMPlatformLink *plink)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingConnection *s_con;
if (!NM_DEVICE_CLASS (nm_device_generic_parent_class)->check_connection_compatible (device, connection))
return FALSE;
if (!nm_connection_is_type (connection, NM_SETTING_GENERIC_SETTING_NAME))
if (!NM_DEVICE_CLASS (nm_device_generic_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_con = nm_connection_get_setting_connection (connection);
if (!nm_setting_connection_get_interface_name (s_con))
if (!nm_setting_connection_get_interface_name (s_con)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"generic profiles need an interface name");
return FALSE;
}
return TRUE;
}
@ -230,6 +230,7 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_generic);
device_class->connection_type_supported = NM_SETTING_GENERIC_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_GENERIC_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_ANY);
device_class->realize_start_notify = realize_start_notify;

View file

@ -123,30 +123,28 @@ get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingInfiniband *s_infiniband;
if (!NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->check_connection_compatible (device, connection))
return FALSE;
if (!nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME))
return FALSE;
s_infiniband = nm_connection_get_setting_infiniband (connection);
if (!s_infiniband)
if (!NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
if (nm_device_is_real (device)) {
const char *mac;
const char *hw_addr;
s_infiniband = nm_connection_get_setting_infiniband (connection);
mac = nm_setting_infiniband_get_mac_address (s_infiniband);
if (mac) {
hw_addr = nm_device_get_permanent_hw_address (device);
if ( !hw_addr
|| !nm_utils_hwaddr_matches (mac, -1, hw_addr, -1))
|| !nm_utils_hwaddr_matches (mac, -1, hw_addr, -1)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"MAC address mismatches");
return FALSE;
}
}
}
@ -375,6 +373,7 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_infiniband);
device_class->connection_type_supported = NM_SETTING_INFINIBAND_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_INFINIBAND_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_INFINIBAND);
device_class->create_and_realize = create_and_realize;

View file

@ -458,7 +458,7 @@ update_connection (NMDevice *device, NMConnection *connection)
/* Don't change a parent specified by UUID if it's still valid */
parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device),
setting_parent);
if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection))
if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection, NULL))
new_parent = NULL;
}
if (new_parent)
@ -524,54 +524,79 @@ update_connection (NMDevice *device, NMConnection *connection)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device);
NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self);
NMSettingIPTunnel *s_ip_tunnel;
const char *parent;
if (!NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->check_connection_compatible (device, connection))
if (!NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection);
if (!s_ip_tunnel)
return FALSE;
if (nm_setting_ip_tunnel_get_mode (s_ip_tunnel) != priv->mode)
if (nm_setting_ip_tunnel_get_mode (s_ip_tunnel) != priv->mode) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"incompatible IP tunnel mode");
return FALSE;
}
if (nm_device_is_real (device)) {
/* Check parent interface; could be an interface name or a UUID */
parent = nm_setting_ip_tunnel_get_parent (s_ip_tunnel);
if (parent && !nm_device_match_parent (device, parent))
if (parent && !nm_device_match_parent (device, parent)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"IP tunnel parent mismatches");
return FALSE;
}
if (!address_equal_pp (priv->addr_family,
nm_setting_ip_tunnel_get_local (s_ip_tunnel),
priv->local))
priv->local)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"local IP tunnel address mismatches");
return FALSE;
}
if (!address_equal_pp (priv->addr_family,
nm_setting_ip_tunnel_get_remote (s_ip_tunnel),
priv->remote))
priv->remote)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"remote IP tunnel address mismatches");
return FALSE;
}
if (nm_setting_ip_tunnel_get_ttl (s_ip_tunnel) != priv->ttl)
if (nm_setting_ip_tunnel_get_ttl (s_ip_tunnel) != priv->ttl) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"TTL of IP tunnel mismatches");
return FALSE;
}
if (nm_setting_ip_tunnel_get_tos (s_ip_tunnel) != priv->tos)
if (nm_setting_ip_tunnel_get_tos (s_ip_tunnel) != priv->tos) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"TOS of IP tunnel mismatches");
return FALSE;
}
if (priv->addr_family == AF_INET) {
if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery)
if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"MTU discovery setting of IP tunnel mismatches");
return FALSE;
}
} else {
if (nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel) != priv->encap_limit)
if (nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel) != priv->encap_limit) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"encapsulation limit of IP tunnel mismatches");
return FALSE;
}
if (nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel) != priv->flow_label)
if (nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel) != priv->flow_label) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"flow-label of IP tunnel mismatches");
return FALSE;
}
}
}
@ -1044,6 +1069,7 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ip_tunnel);
device_class->connection_type_supported = NM_SETTING_IP_TUNNEL_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_IP_TUNNEL_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_GRE,
NM_LINK_TYPE_GRETAP,
NM_LINK_TYPE_IP6TNL,

View file

@ -627,21 +627,6 @@ deactivate (NMDevice *device)
supplicant_interface_release (self);
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingMacsec *s_macsec;
if (!NM_DEVICE_CLASS (nm_device_macsec_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_macsec = nm_connection_get_setting_macsec (connection);
if (!s_macsec)
return FALSE;
return TRUE;
}
/******************************************************************/
static NMDeviceCapabilities
@ -849,10 +834,10 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_macsec);
device_class->connection_type_supported = NM_SETTING_MACSEC_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_MACSEC_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_MACSEC);
device_class->act_stage2_config = act_stage2_config;
device_class->check_connection_compatible = check_connection_compatible;
device_class->create_and_realize = create_and_realize;
device_class->deactivate = deactivate;
device_class->get_generic_capabilities = get_generic_capabilities;

View file

@ -290,40 +290,58 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
/*****************************************************************************/
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE ((NMDeviceMacvlan *) device);
NMSettingMacvlan *s_macvlan;
const char *parent = NULL;
if (!NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->check_connection_compatible (device, connection))
if (!NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_macvlan = nm_connection_get_setting_macvlan (connection);
if (!s_macvlan)
return FALSE;
if (nm_setting_macvlan_get_tap (s_macvlan) != priv->props.tap)
if (nm_setting_macvlan_get_tap (s_macvlan) != priv->props.tap) {
if (priv->props.tap) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"macvtap device does not match macvlan profile");
} else {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"macvlan device does not match macvtap profile");
}
return FALSE;
}
/* Before the device is realized some properties will not be set */
if (nm_device_is_real (device)) {
if (setting_mode_to_platform (nm_setting_macvlan_get_mode (s_macvlan)) != priv->props.mode)
if (setting_mode_to_platform (nm_setting_macvlan_get_mode (s_macvlan)) != priv->props.mode) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"macvlan mode setting differs");
return FALSE;
}
if (nm_setting_macvlan_get_promiscuous (s_macvlan) == priv->props.no_promisc)
if (nm_setting_macvlan_get_promiscuous (s_macvlan) == priv->props.no_promisc) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"macvlan promiscuous setting differs");
return FALSE;
}
/* Check parent interface; could be an interface name or a UUID */
parent = nm_setting_macvlan_get_parent (s_macvlan);
if (parent) {
if (!nm_device_match_parent (device, parent))
if (!nm_device_match_parent (device, parent)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"macvlan parent setting differs");
return FALSE;
}
} else {
/* Parent could be a MAC address in an NMSettingWired */
if (!nm_device_match_parent_hwaddr (device, connection, TRUE))
if (!nm_device_match_parent_hwaddr (device, connection, TRUE)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"macvlan parent mac setting differs");
return FALSE;
}
}
}
@ -402,7 +420,7 @@ update_connection (NMDevice *device, NMConnection *connection)
/* Don't change a parent specified by UUID if it's still valid */
parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device), setting_parent);
if (parent_connection && nm_device_check_connection_compatible (parent_device, parent_connection))
if (parent_connection && nm_device_check_connection_compatible (parent_device, parent_connection, NULL))
new_parent = NULL;
}
if (new_parent)
@ -501,6 +519,7 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_macvlan);
device_class->connection_type_supported = NM_SETTING_MACVLAN_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_MACVLAN_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP);
device_class->act_stage1_prepare = act_stage1_prepare;

View file

@ -49,24 +49,6 @@ G_DEFINE_TYPE (NMDevicePpp, nm_device_ppp, NM_TYPE_DEVICE)
#define NM_DEVICE_PPP_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDevicePpp, NM_IS_DEVICE_PPP)
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingPppoe *s_pppoe;
if (!NM_DEVICE_CLASS (nm_device_ppp_parent_class)->check_connection_compatible (device, connection))
return FALSE;
if (!nm_streq0 (nm_connection_get_connection_type (connection),
NM_SETTING_PPPOE_SETTING_NAME))
return FALSE;
s_pppoe = nm_connection_get_setting_pppoe (connection);
nm_assert (s_pppoe);
return !!nm_setting_pppoe_get_parent (s_pppoe);
}
static NMDeviceCapabilities
get_generic_capabilities (NMDevice *device)
{
@ -282,11 +264,11 @@ nm_device_ppp_class_init (NMDevicePppClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ppp);
device_class->connection_type_supported = NM_SETTING_PPPOE_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_PPPOE_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_PPP);
device_class->act_stage2_config = act_stage2_config;
device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
device_class->check_connection_compatible = check_connection_compatible;
device_class->create_and_realize = create_and_realize;
device_class->deactivate = deactivate;
device_class->get_generic_capabilities = get_generic_capabilities;

View file

@ -289,18 +289,14 @@ _same_og (const char *str, gboolean og_valid, guint32 og_num)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceTun *self = NM_DEVICE_TUN (device);
NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self);
NMSettingTunMode mode;
NMSettingTun *s_tun;
if (!NM_DEVICE_CLASS (nm_device_tun_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_tun = nm_connection_get_setting_tun (connection);
if (!s_tun)
if (!NM_DEVICE_CLASS (nm_device_tun_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
if (nm_device_is_real (device)) {
@ -308,22 +304,43 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
case IFF_TUN: mode = NM_SETTING_TUN_MODE_TUN; break;
case IFF_TAP: mode = NM_SETTING_TUN_MODE_TAP; break;
default:
/* Huh? */
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"invalid tun type on device");
return FALSE;
}
if (mode != nm_setting_tun_get_mode (s_tun))
s_tun = nm_connection_get_setting_tun (connection);
if (mode != nm_setting_tun_get_mode (s_tun)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"tun mode setting mismatches");
return FALSE;
if (!_same_og (nm_setting_tun_get_owner (s_tun), priv->props.owner_valid, priv->props.owner))
}
if (!_same_og (nm_setting_tun_get_owner (s_tun), priv->props.owner_valid, priv->props.owner)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"tun owner setting mismatches");
return FALSE;
if (!_same_og (nm_setting_tun_get_group (s_tun), priv->props.group_valid, priv->props.group))
}
if (!_same_og (nm_setting_tun_get_group (s_tun), priv->props.group_valid, priv->props.group)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"tun group setting mismatches");
return FALSE;
if (nm_setting_tun_get_pi (s_tun) != priv->props.pi)
}
if (nm_setting_tun_get_pi (s_tun) != priv->props.pi) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"tun pi setting mismatches");
return FALSE;
if (nm_setting_tun_get_vnet_hdr (s_tun) != priv->props.vnet_hdr)
}
if (nm_setting_tun_get_vnet_hdr (s_tun) != priv->props.vnet_hdr) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"tun vnet-hdr setting mismatches");
return FALSE;
if (nm_setting_tun_get_multi_queue (s_tun) != priv->props.multi_queue)
}
if (nm_setting_tun_get_multi_queue (s_tun) != priv->props.multi_queue) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"tun multi-queue setting mismatches");
return FALSE;
}
}
return TRUE;
@ -435,6 +452,7 @@ nm_device_tun_class_init (NMDeviceTunClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_tun);
device_class->connection_type_supported = NM_SETTING_TUN_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_TUN_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_TUN);
device_class->link_changed = link_changed;

View file

@ -331,33 +331,39 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
/*****************************************************************************/
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE ((NMDeviceVlan *) device);
NMSettingVlan *s_vlan;
const char *parent = NULL;
const char *parent;
if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_compatible (device, connection))
if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_vlan = nm_connection_get_setting_vlan (connection);
if (!s_vlan)
return FALSE;
/* Before the device is realized some properties will not be set */
if (nm_device_is_real (device)) {
if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id)
s_vlan = nm_connection_get_setting_vlan (connection);
if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vlan id setting mismatches");
return FALSE;
}
/* Check parent interface; could be an interface name or a UUID */
parent = nm_setting_vlan_get_parent (s_vlan);
if (parent) {
if (!nm_device_match_parent (device, parent))
if (!nm_device_match_parent (device, parent)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vlan parent setting differs");
return FALSE;
}
} else {
/* Parent could be a MAC address in an NMSettingWired */
if (!nm_device_match_parent_hwaddr (device, connection, TRUE))
if (!nm_device_match_parent_hwaddr (device, connection, TRUE)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vlan parent mac setting differs");
return FALSE;
}
}
}
@ -455,7 +461,7 @@ update_connection (NMDevice *device, NMConnection *connection)
/* Don't change a parent specified by UUID if it's still valid */
parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device), setting_parent);
if (parent_connection && nm_device_check_connection_compatible (parent_device, parent_connection))
if (parent_connection && nm_device_check_connection_compatible (parent_device, parent_connection, NULL))
new_parent = NULL;
}
if (new_parent)
@ -607,6 +613,7 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_vlan);
device_class->connection_type_supported = NM_SETTING_VLAN_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_VLAN_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_VLAN);
device_class->create_and_realize = create_and_realize;

View file

@ -246,65 +246,108 @@ address_matches (const char *str, in_addr_t addr4, struct in6_addr *addr6)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE ((NMDeviceVxlan *) device);
NMSettingVxlan *s_vxlan;
const char *parent;
if (!NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_vxlan = nm_connection_get_setting_vxlan (connection);
if (!s_vxlan)
if (!NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
if (nm_device_is_real (device)) {
s_vxlan = nm_connection_get_setting_vxlan (connection);
parent = nm_setting_vxlan_get_parent (s_vxlan);
if (parent && !nm_device_match_parent (device, parent))
if (parent && !nm_device_match_parent (device, parent)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan parent mismatches");
return FALSE;
}
if (priv->props.id != nm_setting_vxlan_get_id (s_vxlan))
if (priv->props.id != nm_setting_vxlan_get_id (s_vxlan)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan id mismatches");
return FALSE;
}
if (!address_matches (nm_setting_vxlan_get_local (s_vxlan), priv->props.local, &priv->props.local6))
if (!address_matches (nm_setting_vxlan_get_local (s_vxlan), priv->props.local, &priv->props.local6)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan local address mismatches");
return FALSE;
}
if (!address_matches (nm_setting_vxlan_get_remote (s_vxlan), priv->props.group, &priv->props.group6))
if (!address_matches (nm_setting_vxlan_get_remote (s_vxlan), priv->props.group, &priv->props.group6)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan remote address mismatches");
return FALSE;
}
if (priv->props.src_port_min != nm_setting_vxlan_get_source_port_min (s_vxlan))
if (priv->props.src_port_min != nm_setting_vxlan_get_source_port_min (s_vxlan)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan source port min mismatches");
return FALSE;
}
if (priv->props.src_port_max != nm_setting_vxlan_get_source_port_max (s_vxlan))
if (priv->props.src_port_max != nm_setting_vxlan_get_source_port_max (s_vxlan)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan source port max mismatches");
return FALSE;
}
if (priv->props.dst_port != nm_setting_vxlan_get_destination_port (s_vxlan))
if (priv->props.dst_port != nm_setting_vxlan_get_destination_port (s_vxlan)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan destination port mismatches");
return FALSE;
}
if (priv->props.tos != nm_setting_vxlan_get_tos (s_vxlan))
if (priv->props.tos != nm_setting_vxlan_get_tos (s_vxlan)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan TOS mismatches");
return FALSE;
}
if (priv->props.ttl != nm_setting_vxlan_get_ttl (s_vxlan))
if (priv->props.ttl != nm_setting_vxlan_get_ttl (s_vxlan)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan TTL mismatches");
return FALSE;
}
if (priv->props.learning != nm_setting_vxlan_get_learning (s_vxlan))
if (priv->props.learning != nm_setting_vxlan_get_learning (s_vxlan)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan learning mismatches");
return FALSE;
}
if (priv->props.ageing != nm_setting_vxlan_get_ageing (s_vxlan))
if (priv->props.ageing != nm_setting_vxlan_get_ageing (s_vxlan)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan ageing mismatches");
return FALSE;
}
if (priv->props.proxy != nm_setting_vxlan_get_proxy (s_vxlan))
if (priv->props.proxy != nm_setting_vxlan_get_proxy (s_vxlan)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan proxy mismatches");
return FALSE;
}
if (priv->props.rsc != nm_setting_vxlan_get_rsc (s_vxlan))
if (priv->props.rsc != nm_setting_vxlan_get_rsc (s_vxlan)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan rsc mismatches");
return FALSE;
}
if (priv->props.l2miss != nm_setting_vxlan_get_l2_miss (s_vxlan))
if (priv->props.l2miss != nm_setting_vxlan_get_l2_miss (s_vxlan)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan l2miss mismatches");
return FALSE;
}
if (priv->props.l3miss != nm_setting_vxlan_get_l3_miss (s_vxlan))
if (priv->props.l3miss != nm_setting_vxlan_get_l3_miss (s_vxlan)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vxlan l3miss mismatches");
return FALSE;
}
}
return TRUE;
@ -367,7 +410,7 @@ update_connection (NMDevice *device, NMConnection *connection)
/* Don't change a parent specified by UUID if it's still valid */
parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device),
setting_parent);
if (parent_connection && nm_device_check_connection_compatible (parent_device, parent_connection))
if (parent_connection && nm_device_check_connection_compatible (parent_device, parent_connection, NULL))
new_parent = NULL;
}
}
@ -582,6 +625,7 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_vxlan);
device_class->connection_type_supported = NM_SETTING_VXLAN_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_VXLAN_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_VXLAN);
device_class->link_changed = link_changed;

View file

@ -91,23 +91,24 @@ update_connection (NMDevice *device, NMConnection *connection)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingWpan *s_wpan;
const char *mac, *hw_addr;
if (!NM_DEVICE_CLASS (nm_device_wpan_parent_class)->check_connection_compatible (device, connection))
if (!NM_DEVICE_CLASS (nm_device_wpan_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_wpan = nm_connection_get_setting_wpan (connection);
if (!s_wpan)
return FALSE;
mac = nm_setting_wpan_get_mac_address (s_wpan);
if (mac) {
hw_addr = nm_device_get_hw_address (device);
if (!nm_utils_hwaddr_matches (mac, -1, hw_addr, -1))
if (!nm_utils_hwaddr_matches (mac, -1, hw_addr, -1)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"MAC address mismatches");
return FALSE;
}
}
return TRUE;
@ -216,6 +217,7 @@ nm_device_wpan_class_init (NMDeviceWpanClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_wpan);
device_class->connection_type_supported = NM_SETTING_WPAN_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_WPAN_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_WPAN);
device_class->complete_connection = complete_connection;

View file

@ -5420,21 +5420,43 @@ nm_device_match_parent_hwaddr (NMDevice *device,
}
static gboolean
check_connection_compatible (NMDevice *self, NMConnection *connection)
check_connection_compatible (NMDevice *self, NMConnection *connection, GError **error)
{
const char *device_iface = nm_device_get_iface (self);
gs_free char *conn_iface = nm_manager_get_connection_iface (nm_manager_get (),
connection,
NULL, NULL);
gs_free_error GError *local = NULL;
gs_free char *conn_iface = NULL;
NMDeviceClass *klass;
klass = NM_DEVICE_GET_CLASS (self);
if (klass->connection_type_check_compatible) {
if (!_nm_connection_check_main_setting (connection,
klass->connection_type_check_compatible,
error))
return FALSE;
}
conn_iface = nm_manager_get_connection_iface (nm_manager_get (),
connection,
NULL,
&local);
/* We always need a interface name for virtual devices, but for
* physical ones a connection without interface name is fine for
* any device. */
if (!conn_iface)
return !nm_connection_is_virtual (connection);
if (!conn_iface) {
if (nm_connection_is_virtual (connection)) {
nm_utils_error_set (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"cannot get interface name due to %s", local->message);
return FALSE;
}
return TRUE;
}
if (strcmp (conn_iface, device_iface) != 0)
if (!nm_streq0 (conn_iface, device_iface)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"mismatching interface name");
return FALSE;
}
return TRUE;
}
@ -5443,6 +5465,11 @@ check_connection_compatible (NMDevice *self, NMConnection *connection)
* nm_device_check_connection_compatible:
* @self: an #NMDevice
* @connection: an #NMConnection
* @error: optional reason why it is incompatible. Note that the
* error code is set to %NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
* if the profile is fundamentally incompatible with the device
* (most commonly, because the device-type does not support the
* connection-type).
*
* Checks if @connection could potentially be activated on @self.
* This means only that @self has the proper capabilities, and that
@ -5455,12 +5482,12 @@ check_connection_compatible (NMDevice *self, NMConnection *connection)
* @self.
*/
gboolean
nm_device_check_connection_compatible (NMDevice *self, NMConnection *connection)
nm_device_check_connection_compatible (NMDevice *self, NMConnection *connection, GError **error)
{
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
return NM_DEVICE_GET_CLASS (self)->check_connection_compatible (self, connection);
return NM_DEVICE_GET_CLASS (self)->check_connection_compatible (self, connection, error);
}
gboolean
@ -13217,13 +13244,22 @@ _nm_device_check_connection_available (NMDevice *self,
GError **error)
{
NMDeviceState state;
GError *local = NULL;
/* an unrealized software device is always available, hardware devices never. */
if (!nm_device_is_real (self)) {
if (nm_device_is_software (self)) {
if (!nm_device_check_connection_compatible (self, connection)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
"profile is not compatible with software device");
if (!nm_device_check_connection_compatible (self, connection,
error ? &local : NULL)) {
if (error) {
nm_utils_error_set (error,
local->domain == NM_UTILS_ERROR
? local->code
: NM_UTILS_ERROR_UNKNOWN,
"profile is not compatible with software device (%s)",
local->message);
g_error_free (local);
}
return FALSE;
}
return TRUE;
@ -13271,9 +13307,17 @@ _nm_device_check_connection_available (NMDevice *self,
}
}
if (!nm_device_check_connection_compatible (self, connection)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
"profile is not compatible with device");
if (!nm_device_check_connection_compatible (self, connection,
error ? &local : NULL)) {
if (error) {
nm_utils_error_set (error,
local->domain == NM_UTILS_ERROR
? local->code
: NM_UTILS_ERROR_UNKNOWN,
"profile is not compatible with device (%s)",
local->message);
g_error_free (local);
}
return FALSE;
}

View file

@ -203,6 +203,11 @@ typedef struct _NMDeviceClass {
const char *default_type_description;
const char *connection_type_supported;
/* most device types, can only handle profiles of a particular type. This
* is the connection.type setting, as checked by nm_device_check_connection_compatible() */
const char *connection_type_check_compatible;
const NMLinkType *link_types;
/* Whether the device type is a master-type. This depends purely on the
@ -301,7 +306,9 @@ typedef struct _NMDeviceClass {
* only the devices type and characteristics. Does not use any live
* network information like WiFi scan lists etc.
*/
gboolean (* check_connection_compatible) (NMDevice *self, NMConnection *connection);
gboolean (* check_connection_compatible) (NMDevice *self,
NMConnection *connection,
GError **error);
/* Checks whether the connection is likely available to be activated,
* including any live network information like scan lists. The connection
@ -534,7 +541,10 @@ gboolean nm_device_complete_connection (NMDevice *device,
NMConnection *const*existing_connections,
GError **error);
gboolean nm_device_check_connection_compatible (NMDevice *device, NMConnection *connection);
gboolean nm_device_check_connection_compatible (NMDevice *device,
NMConnection *connection,
GError **error);
gboolean nm_device_check_slave_connection_compatible (NMDevice *device, NMConnection *connection);
gboolean nm_device_unmanage_on_quit (NMDevice *self);

View file

@ -76,21 +76,6 @@ get_generic_capabilities (NMDevice *device)
return NM_DEVICE_CAP_IS_SOFTWARE;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
const char *connection_type;
if (!NM_DEVICE_CLASS (nm_device_ovs_bridge_parent_class)->check_connection_compatible (device, connection))
return FALSE;
connection_type = nm_connection_get_connection_type (connection);
if (!nm_streq0 (connection_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME))
return FALSE;
return TRUE;
}
static NMActStageReturn
act_stage3_ip4_config_start (NMDevice *device,
NMIP4Config **out_config,
@ -153,6 +138,7 @@ nm_device_ovs_bridge_class_init (NMDeviceOvsBridgeClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ovs_bridge);
device_class->connection_type_supported = NM_SETTING_OVS_BRIDGE_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_OVS_BRIDGE_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES ();
device_class->is_master = TRUE;
@ -160,7 +146,6 @@ nm_device_ovs_bridge_class_init (NMDeviceOvsBridgeClass *klass)
device_class->create_and_realize = create_and_realize;
device_class->unrealize = unrealize;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->check_connection_compatible = check_connection_compatible;
device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
device_class->enslave_slave = enslave_slave;

View file

@ -85,25 +85,20 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingConnection *s_con;
NMSettingOvsInterface *s_ovs_iface;
if (!NM_DEVICE_CLASS (nm_device_ovs_interface_parent_class)->check_connection_compatible (device, connection))
if (!NM_DEVICE_CLASS (nm_device_ovs_interface_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_ovs_iface = nm_connection_get_setting_ovs_interface (connection);
if (!s_ovs_iface)
return FALSE;
if (!NM_IN_STRSET (nm_setting_ovs_interface_get_interface_type (s_ovs_iface),
"internal", "patch")) {
return FALSE;
}
s_con = nm_connection_get_setting_connection (connection);
if (g_strcmp0 (nm_setting_connection_get_connection_type (s_con),
NM_SETTING_OVS_INTERFACE_SETTING_NAME) != 0) {
if (!NM_IN_STRSET (nm_setting_ovs_interface_get_interface_type (s_ovs_iface),
"internal",
"patch")) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"unsupported OVS interface type in profile");
return FALSE;
}
@ -202,6 +197,7 @@ nm_device_ovs_interface_class_init (NMDeviceOvsInterfaceClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ovs_interface);
device_class->connection_type_supported = NM_SETTING_OVS_INTERFACE_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_OVS_INTERFACE_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_OPENVSWITCH);
device_class->get_type_description = get_type_description;

View file

@ -70,26 +70,6 @@ get_generic_capabilities (NMDevice *device)
return NM_DEVICE_CAP_IS_SOFTWARE;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingConnection *s_con;
const char *connection_type;
if (!NM_DEVICE_CLASS (nm_device_ovs_port_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_con = nm_connection_get_setting_connection (connection);
connection_type = nm_setting_connection_get_connection_type (s_con);
if (!connection_type)
return FALSE;
if (strcmp (connection_type, NM_SETTING_OVS_PORT_SETTING_NAME) == 0)
return TRUE;
return FALSE;
}
static NMActStageReturn
act_stage3_ip4_config_start (NMDevice *device,
NMIP4Config **out_config,
@ -199,13 +179,13 @@ nm_device_ovs_port_class_init (NMDeviceOvsPortClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ovs_port);
device_class->connection_type_supported = NM_SETTING_OVS_PORT_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_OVS_PORT_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES ();
device_class->is_master = TRUE;
device_class->get_type_description = get_type_description;
device_class->create_and_realize = create_and_realize;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->check_connection_compatible = check_connection_compatible;
device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
device_class->enslave_slave = enslave_slave;

View file

@ -84,23 +84,6 @@ get_generic_capabilities (NMDevice *device)
return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingTeam *s_team;
if (!NM_DEVICE_CLASS (nm_device_team_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_team = nm_connection_get_setting_team (connection);
if (!s_team || !nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME))
return FALSE;
/* FIXME: match team properties like mode, etc? */
return TRUE;
}
static gboolean
complete_connection (NMDevice *device,
NMConnection *connection,
@ -920,12 +903,12 @@ nm_device_team_class_init (NMDeviceTeamClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_team);
device_class->connection_type_supported = NM_SETTING_TEAM_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_TEAM_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_TEAM);
device_class->is_master = TRUE;
device_class->create_and_realize = create_and_realize;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->check_connection_compatible = check_connection_compatible;
device_class->complete_connection = complete_connection;
device_class->update_connection = update_connection;
device_class->master_update_slave_connection = master_update_slave_connection;

View file

@ -492,59 +492,62 @@ is_connection_known_network (NMConnection *connection)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingConnection *s_con;
NMSettingWireless *s_wireless;
const char *mac;
const char * const *mac_blacklist;
int i;
const char *mode;
const char *perm_hw_addr;
if (!NM_DEVICE_CLASS (nm_device_iwd_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_WIRELESS_SETTING_NAME))
if (!NM_DEVICE_CLASS (nm_device_iwd_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_wireless = nm_connection_get_setting_wireless (connection);
if (!s_wireless)
return FALSE;
perm_hw_addr = nm_device_get_permanent_hw_address (device);
mac = nm_setting_wireless_get_mac_address (s_wireless);
if (perm_hw_addr) {
if (mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1))
if (mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"mac address mispatches");
return FALSE;
}
/* Check for MAC address blacklist */
mac_blacklist = nm_setting_wireless_get_mac_address_blacklist (s_wireless);
for (i = 0; mac_blacklist[i]; i++) {
if (!nm_utils_hwaddr_valid (mac_blacklist[i], ETH_ALEN)) {
g_warn_if_reached ();
nm_assert (nm_utils_hwaddr_valid (mac_blacklist[i], ETH_ALEN));
if (nm_utils_hwaddr_matches (mac_blacklist[i], -1, perm_hw_addr, -1)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"mac address blacklisted");
return FALSE;
}
if (nm_utils_hwaddr_matches (mac_blacklist[i], -1, perm_hw_addr, -1))
return FALSE;
}
} else if (mac)
} else if (mac) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"device has no valid mac address as required by profile");
return FALSE;
}
mode = nm_setting_wireless_get_mode (s_wireless);
if (mode && g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0)
if (!NM_IN_STRSET (nm_setting_wireless_get_mode (s_wireless),
NULL,
NM_SETTING_WIRELESS_MODE_INFRA)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"IWD only support infrastructure type profiles");
return FALSE;
}
/* 8021x networks can only be used if they've been provisioned on the IWD side and
* thus are Known Networks.
*/
if (get_connection_iwd_security (connection) == NM_IWD_NETWORK_SECURITY_8021X) {
if (!is_connection_known_network (connection))
if (!is_connection_known_network (connection)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"802.1x profile is not a known network");
return FALSE;
}
}
return TRUE;
@ -1986,6 +1989,7 @@ nm_device_iwd_class_init (NMDeviceIwdClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&nm_interface_info_device_wireless);
device_class->connection_type_supported = NM_SETTING_WIRELESS_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_WIRELESS_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_WIFI);
device_class->can_auto_connect = can_auto_connect;

View file

@ -79,28 +79,6 @@ G_DEFINE_TYPE (NMDeviceOlpcMesh, nm_device_olpc_mesh, NM_TYPE_DEVICE)
/*****************************************************************************/
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingConnection *s_con;
NMSettingOlpcMesh *s_mesh;
if (!NM_DEVICE_CLASS (nm_device_olpc_mesh_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_OLPC_MESH_SETTING_NAME))
return FALSE;
s_mesh = nm_connection_get_setting_olpc_mesh (connection);
if (!s_mesh)
return FALSE;
return TRUE;
}
static gboolean
get_autoconnect_allowed (NMDevice *device)
{
@ -524,9 +502,9 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_olpc_mesh);
device_class->connection_type_supported = NM_SETTING_OLPC_MESH_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_OLPC_MESH_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_OLPC_MESH);
device_class->check_connection_compatible = check_connection_compatible;
device_class->get_autoconnect_allowed = get_autoconnect_allowed;
device_class->complete_connection = complete_connection;
device_class->is_available = is_available;

View file

@ -604,11 +604,10 @@ is_adhoc_wpa (NMConnection *connection)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (device);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
NMSettingConnection *s_con;
NMSettingWireless *s_wireless;
const char *mac;
const char * const *mac_blacklist;
@ -616,18 +615,10 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
const char *mode;
const char *perm_hw_addr;
if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_WIRELESS_SETTING_NAME))
if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_wireless = nm_connection_get_setting_wireless (connection);
if (!s_wireless)
return FALSE;
perm_hw_addr = nm_device_get_permanent_hw_address (device);
mac = nm_setting_wireless_get_mac_address (s_wireless);
@ -3339,6 +3330,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&nm_interface_info_device_wireless);
device_class->connection_type_supported = NM_SETTING_WIRELESS_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_WIRELESS_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_WIFI);
device_class->can_auto_connect = can_auto_connect;

View file

@ -397,12 +397,29 @@ get_type_description (NMDevice *device)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
if (!NM_DEVICE_CLASS (nm_device_modem_parent_class)->check_connection_compatible (device, connection))
GError *local = NULL;
if (!NM_DEVICE_CLASS (nm_device_modem_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
return nm_modem_check_connection_compatible (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, connection);
if (!nm_modem_check_connection_compatible (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem,
connection,
error ? &local : NULL)) {
if (error) {
g_set_error (error,
NM_UTILS_ERROR,
g_error_matches (local, NM_UTILS_ERROR, NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE)
? NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE
: NM_UTILS_ERROR_UNKNOWN,
"modem is incompatible with connection: %s",
local->message);
g_error_free (local);
}
return FALSE;
}
return TRUE;
}
static gboolean

View file

@ -617,44 +617,40 @@ act_stage1_prepare (NMModem *_self,
/*****************************************************************************/
static gboolean
check_connection_compatible_with_modem (NMModem *_self, NMConnection *connection)
check_connection_compatible_with_modem (NMModem *_self, NMConnection *connection, GError **error)
{
NMModemBroadband *self = NM_MODEM_BROADBAND (_self);
MMModemCapability modem_caps;
NMSettingConnection *s_con;
modem_caps = mm_modem_get_current_capabilities (self->_priv.modem_iface);
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
if (MODEM_CAPS_3GPP (modem_caps)) {
NMSettingGsm *s_gsm;
if (!g_str_equal (nm_setting_connection_get_connection_type (s_con),
NM_SETTING_GSM_SETTING_NAME))
return FALSE;
s_gsm = nm_connection_get_setting_gsm (connection);
if (!s_gsm)
if (!_nm_connection_check_main_setting (connection, NM_SETTING_GSM_SETTING_NAME, error))
return FALSE;
return TRUE;
}
if (MODEM_CAPS_3GPP2 (modem_caps)) {
NMSettingCdma *s_cdma;
if (!g_str_equal (nm_setting_connection_get_connection_type (s_con),
NM_SETTING_CDMA_SETTING_NAME))
return FALSE;
s_cdma = nm_connection_get_setting_cdma (connection);
if (!s_cdma)
if (!_nm_connection_check_main_setting (connection, NM_SETTING_CDMA_SETTING_NAME, error))
return FALSE;
return TRUE;
}
if ( !_nm_connection_check_main_setting (connection, NM_SETTING_GSM_SETTING_NAME, NULL)
&& !_nm_connection_check_main_setting (connection, NM_SETTING_CDMA_SETTING_NAME, NULL)) {
nm_utils_error_set (error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
"connection type %s is not supported by modem",
nm_connection_get_connection_type (connection));
return FALSE;
}
nm_utils_error_set (error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"modem lacks capabilities for %s profile",
nm_connection_get_connection_type (connection));
return FALSE;
}

View file

@ -280,46 +280,41 @@ deactivate_cleanup (NMModem *modem, NMDevice *device)
static gboolean
check_connection_compatible_with_modem (NMModem *modem,
NMConnection *connection)
NMConnection *connection,
GError **error)
{
NMModemOfono *self = NM_MODEM_OFONO (modem);
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self);
NMSettingConnection *s_con;
NMSettingGsm *s_gsm;
const char *uuid;
const char *id;
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
uuid = nm_connection_get_uuid (connection);
id = nm_connection_get_id (connection);
s_gsm = nm_connection_get_setting_gsm (connection);
if (!s_gsm)
if (!_nm_connection_check_main_setting (connection, NM_SETTING_GSM_SETTING_NAME, NULL)) {
nm_utils_error_set (error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
"connection type %s is not supported by ofono modem",
nm_connection_get_connection_type (connection));
return FALSE;
}
if (!priv->imsi) {
_LOGW ("skipping %s/%s: no IMSI", uuid, id);
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"modem has no IMSI");
return FALSE;
}
if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_GSM_SETTING_NAME)) {
_LOGD ("skipping %s/%s: not GSM", uuid, id);
id = nm_connection_get_id (connection);
if (!strstr (id, "/context")) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"the connection ID has no context");
return FALSE;
}
if (!g_strrstr (id, "/context")) {
_LOGD ("skipping %s/%s: unexpected ID", uuid, id);
if (!strstr (id, priv->imsi)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"the connection ID does not contain the IMSI");
return FALSE;
}
if (!g_strrstr (id, priv->imsi)) {
_LOGD ("skipping %s/%s: ID doesn't contain IMSI", uuid, id);
return FALSE;
}
_LOGD ("%s/%s compatible with IMSI %s", uuid, id, priv->imsi);
return TRUE;
}

View file

@ -1027,35 +1027,29 @@ nm_modem_act_stage2_config (NMModem *self,
/*****************************************************************************/
gboolean
nm_modem_check_connection_compatible (NMModem *self, NMConnection *connection)
nm_modem_check_connection_compatible (NMModem *self, NMConnection *connection, GError **error)
{
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
NMSettingConnection *s_con;
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
if (g_str_equal (nm_setting_connection_get_connection_type (s_con),
NM_SETTING_GSM_SETTING_NAME)) {
if (nm_streq0 (nm_connection_get_connection_type (connection),
NM_SETTING_GSM_SETTING_NAME)) {
NMSettingGsm *s_gsm;
const char *str;
s_gsm = nm_connection_get_setting_gsm (connection);
s_gsm = _nm_connection_check_main_setting (connection, NM_SETTING_GSM_SETTING_NAME, error);
if (!s_gsm)
return FALSE;
str = nm_setting_gsm_get_device_id (s_gsm);
if (str) {
if (!priv->device_id) {
_LOGD ("%s/%s has device-id, device does not",
nm_connection_get_uuid (connection),
nm_connection_get_id (connection));
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"GSM profile has device-id, device does not");
return FALSE;
}
if (strcmp (str, priv->device_id)) {
_LOGD ("%s/%s device-id mismatch",
nm_connection_get_uuid (connection),
nm_connection_get_id (connection));
if (!nm_streq (str, priv->device_id)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"device has differing device-id than GSM profile");
return FALSE;
}
}
@ -1065,30 +1059,26 @@ nm_modem_check_connection_compatible (NMModem *self, NMConnection *connection)
* are only compared if present on the device.
*/
str = nm_setting_gsm_get_sim_id (s_gsm);
if (str && priv->sim_id) {
if (strcmp (str, priv->sim_id)) {
_LOGD ("%s/%s sim-id mismatch",
nm_connection_get_uuid (connection),
nm_connection_get_id (connection));
if ( priv->sim_id
&& (str = nm_setting_gsm_get_sim_id (s_gsm))) {
if (!nm_streq (str, priv->sim_id)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"device has differing sim-id than GSM profile");
return FALSE;
}
}
str = nm_setting_gsm_get_sim_operator_id (s_gsm);
if (str && priv->sim_operator_id) {
if (strcmp (str, priv->sim_operator_id)) {
_LOGD ("%s/%s sim-operator-id mismatch",
nm_connection_get_uuid (connection),
nm_connection_get_id (connection));
if ( priv->sim_operator_id
&& (str = nm_setting_gsm_get_sim_operator_id (s_gsm))) {
if (!nm_streq (str, priv->sim_operator_id)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"device has differing sim-operator-id than GSM profile");
return FALSE;
}
}
}
if (NM_MODEM_GET_CLASS (self)->check_connection_compatible_with_modem)
return NM_MODEM_GET_CLASS (self)->check_connection_compatible_with_modem (self, connection);
return FALSE;
return NM_MODEM_GET_CLASS (self)->check_connection_compatible_with_modem (self, connection, error);
}
/*****************************************************************************/

View file

@ -122,7 +122,8 @@ typedef struct {
const char **pass);
gboolean (*check_connection_compatible_with_modem) (NMModem *modem,
NMConnection *connection);
NMConnection *connection,
GError **error);
gboolean (*complete_connection) (NMModem *modem,
NMConnection *connection,
@ -185,7 +186,9 @@ void nm_modem_get_capabilities (NMModem *self,
NMDeviceModemCapabilities *modem_caps,
NMDeviceModemCapabilities *current_caps);
gboolean nm_modem_check_connection_compatible (NMModem *self, NMConnection *connection);
gboolean nm_modem_check_connection_compatible (NMModem *self,
NMConnection *connection,
GError **error);
gboolean nm_modem_complete_connection (NMModem *self,
NMConnection *connection,

View file

@ -1290,7 +1290,7 @@ find_device_by_iface (NMManager *self,
if (strcmp (nm_device_get_iface (candidate), iface))
continue;
if (connection && !nm_device_check_connection_compatible (candidate, connection))
if (connection && !nm_device_check_connection_compatible (candidate, connection, NULL))
continue;
if (slave) {
if (!nm_device_is_master (candidate))
@ -1707,7 +1707,7 @@ find_parent_device_for_connection (NMManager *self, NMConnection *connection, NM
return candidate;
if ( !first_compatible
&& nm_device_check_connection_compatible (candidate, NM_CONNECTION (parent_connection)))
&& nm_device_check_connection_compatible (candidate, NM_CONNECTION (parent_connection), NULL))
first_compatible = candidate;
}
@ -1877,7 +1877,7 @@ system_create_virtual_device (NMManager *self, NMConnection *connection)
/* See if there's a device that is already compatible with this connection */
c_list_for_each_entry (dev_candidate, &priv->devices_lst_head, devices_lst) {
if (nm_device_check_connection_compatible (dev_candidate, connection)) {
if (nm_device_check_connection_compatible (dev_candidate, connection, NULL)) {
if (nm_device_is_real (dev_candidate)) {
_LOG3D (LOGD_DEVICE, connection, "already created virtual interface name %s",
iface);
@ -1933,7 +1933,7 @@ system_create_virtual_device (NMManager *self, NMConnection *connection)
NMConnection *candidate = NM_CONNECTION (connections[i]);
NMSettingConnection *s_con;
if (!nm_device_check_connection_compatible (device, candidate))
if (!nm_device_check_connection_compatible (device, candidate, NULL))
continue;
s_con = nm_connection_get_setting_connection (candidate);
@ -2460,7 +2460,7 @@ get_existing_connection (NMManager *self,
&& !active_connection_find (self, connection_checked, NULL,
NM_ACTIVE_CONNECTION_STATE_ACTIVATED,
NULL)
&& nm_device_check_connection_compatible (device, NM_CONNECTION (connection_checked))) {
&& nm_device_check_connection_compatible (device, NM_CONNECTION (connection_checked), NULL)) {
if (connection) {
NMConnection *const connections[] = {
@ -2498,7 +2498,7 @@ get_existing_connection (NMManager *self,
NMConnection *con = NM_CONNECTION (connections[i]);
if ( con != NM_CONNECTION (connection_checked)
&& nm_device_check_connection_compatible (device, con))
&& nm_device_check_connection_compatible (device, con, NULL))
connections[j++] = connections[i];
}
connections[j] = NULL;

View file

@ -1444,7 +1444,7 @@ reset_autoconnect_all (NMPolicy *self,
NMSettingsConnection *connection = connections[i];
if ( device
&& !nm_device_check_connection_compatible (device, NM_CONNECTION (connection)))
&& !nm_device_check_connection_compatible (device, NM_CONNECTION (connection), NULL))
continue;
if (only_no_secrets) {

View file

@ -1622,7 +1622,7 @@ have_connection_for_device (NMSettings *self, NMDevice *device)
c_list_for_each_entry (connection, &priv->connections_lst_head, _connections_lst) {
const char *ctype, *iface;
if (!nm_device_check_connection_compatible (device, NM_CONNECTION (connection)))
if (!nm_device_check_connection_compatible (device, NM_CONNECTION (connection), NULL))
continue;
s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));