summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-07-24 09:44:18 +0200
committerThomas Haller <thaller@redhat.com>2018-07-24 09:44:18 +0200
commita6f51fffa1b8fbc38f93f86735b18c8539faba1d (patch)
tree27c6e37d2762fb1613a8d461bb89e4f93f431101
parent159ff23268b13aedcaffd1a27c279d8476cf6503 (diff)
parent3000ade72af4373f3a53e2b6d02d54fc3ce33513 (diff)
downloadNetworkManager-a6f51fffa1b8fbc38f93f86735b18c8539faba1d.tar.gz
device: merge branch 'th/not-available-reason'
https://github.com/NetworkManager/NetworkManager/pull/163
-rw-r--r--libnm-core/nm-connection.c34
-rw-r--r--libnm-core/nm-core-internal.h4
-rw-r--r--libnm-core/tests/test-general.c53
-rw-r--r--shared/nm-utils/nm-macros-internal.h7
-rw-r--r--shared/nm-utils/nm-shared-utils.h37
-rw-r--r--src/devices/adsl/nm-device-adsl.c32
-rw-r--r--src/devices/bluetooth/nm-device-bt.c45
-rw-r--r--src/devices/nm-device-6lowpan.c28
-rw-r--r--src/devices/nm-device-bond.c54
-rw-r--r--src/devices/nm-device-bridge.c96
-rw-r--r--src/devices/nm-device-dummy.c23
-rw-r--r--src/devices/nm-device-ethernet.c84
-rw-r--r--src/devices/nm-device-generic.c30
-rw-r--r--src/devices/nm-device-infiniband.c42
-rw-r--r--src/devices/nm-device-ip-tunnel.c73
-rw-r--r--src/devices/nm-device-macsec.c44
-rw-r--r--src/devices/nm-device-macvlan.c47
-rw-r--r--src/devices/nm-device-ppp.c37
-rw-r--r--src/devices/nm-device-private.h27
-rw-r--r--src/devices/nm-device-tun.c50
-rw-r--r--src/devices/nm-device-veth.c5
-rw-r--r--src/devices/nm-device-vlan.c71
-rw-r--r--src/devices/nm-device-vxlan.c94
-rw-r--r--src/devices/nm-device-wpan.c18
-rw-r--r--src/devices/nm-device.c171
-rw-r--r--src/devices/nm-device.h22
-rw-r--r--src/devices/ovs/nm-device-ovs-bridge.c21
-rw-r--r--src/devices/ovs/nm-device-ovs-interface.c26
-rw-r--r--src/devices/ovs/nm-device-ovs-port.c26
-rw-r--r--src/devices/team/nm-device-team.c50
-rw-r--r--src/devices/wifi/nm-device-iwd.c132
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.c45
-rw-r--r--src/devices/wifi/nm-device-wifi.c94
-rw-r--r--src/devices/wwan/nm-device-modem.c47
-rw-r--r--src/devices/wwan/nm-modem-broadband.c38
-rw-r--r--src/devices/wwan/nm-modem-ofono.c43
-rw-r--r--src/devices/wwan/nm-modem.c50
-rw-r--r--src/devices/wwan/nm-modem.h9
-rw-r--r--src/nm-manager.c102
-rw-r--r--src/nm-policy.c2
-rw-r--r--src/settings/nm-settings.c2
41 files changed, 1144 insertions, 771 deletions
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c
index 2f8cb4e905..29fdd9790a 100644
--- a/libnm-core/nm-connection.c
+++ b/libnm-core/nm-connection.c
@@ -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)
{
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h
index 3808a9e61b..4945118ffd 100644
--- a/libnm-core/nm-core-internal.h
+++ b/libnm-core/nm-core-internal.h
@@ -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
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
index ffa4da0213..093ebf55a8 100644
--- a/libnm-core/tests/test-general.c
+++ b/libnm-core/tests/test-general.c
@@ -7006,6 +7006,57 @@ test_get_start_time_for_pid (void)
/*****************************************************************************/
+static void
+test_nm_va_args_macros (void)
+{
+#define GET_NARG_1(...) \
+ NM_NARG (__VA_ARGS__)
+
+ g_assert_cmpint ( 0, ==, GET_NARG_1 ());
+ g_assert_cmpint ( 1, ==, GET_NARG_1 (x));
+ g_assert_cmpint ( 2, ==, GET_NARG_1 ( , ));
+ g_assert_cmpint ( 2, ==, GET_NARG_1 ( , x));
+ g_assert_cmpint ( 2, ==, GET_NARG_1 (x, ));
+ g_assert_cmpint ( 2, ==, GET_NARG_1 (x, x));
+ g_assert_cmpint ( 3, ==, GET_NARG_1 ( , , ));
+ g_assert_cmpint ( 3, ==, GET_NARG_1 ( , , x));
+ g_assert_cmpint ( 3, ==, GET_NARG_1 ( , x, ));
+ g_assert_cmpint ( 3, ==, GET_NARG_1 ( , x, x));
+ g_assert_cmpint ( 3, ==, GET_NARG_1 (x, , ));
+ g_assert_cmpint ( 3, ==, GET_NARG_1 (x, , x));
+ g_assert_cmpint ( 3, ==, GET_NARG_1 (x, x, ));
+ g_assert_cmpint ( 3, ==, GET_NARG_1 (x, x, x));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 ( , , , ));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 ( , , , x));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 ( , , x, ));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 ( , , x, x));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, , ));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, , x));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, x, ));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, x, x));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 (x, , , ));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 (x, , , x));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 (x, , x, ));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 (x, , x, x));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, , ));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, , x));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, x, ));
+ g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, x, x));
+
+ g_assert_cmpint ( 5, ==, GET_NARG_1 (x, x, x, x, x));
+ g_assert_cmpint ( 6, ==, GET_NARG_1 (x, x, x, x, x, x));
+ g_assert_cmpint ( 7, ==, GET_NARG_1 (x, x, x, x, x, x, x));
+ g_assert_cmpint ( 8, ==, GET_NARG_1 (x, x, x, x, x, x, x, x));
+ g_assert_cmpint ( 9, ==, GET_NARG_1 (x, x, x, x, x, x, x, x, x));
+ g_assert_cmpint (10, ==, GET_NARG_1 (x, x, x, x, x, x, x, x, x, x));
+
+ G_STATIC_ASSERT_EXPR (0 == GET_NARG_1 ());
+ G_STATIC_ASSERT_EXPR (1 == GET_NARG_1 (x));
+ G_STATIC_ASSERT_EXPR (2 == GET_NARG_1 (x, x));
+}
+
+/*****************************************************************************/
+
NMTST_DEFINE ();
int main (int argc, char **argv)
@@ -7161,6 +7212,8 @@ int main (int argc, char **argv)
g_test_add_func ("/core/general/get_start_time_for_pid", test_get_start_time_for_pid);
+ g_test_add_func ("/core/general/test_nm_va_args_macros", test_nm_va_args_macros);
+
return g_test_run ();
}
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h
index 6d5e25b28c..2ff95a288e 100644
--- a/shared/nm-utils/nm-macros-internal.h
+++ b/shared/nm-utils/nm-macros-internal.h
@@ -342,13 +342,16 @@ _nm_auto_freev (gpointer ptr)
/*****************************************************************************/
-/* http://stackoverflow.com/a/2124385/354393 */
+/* http://stackoverflow.com/a/2124385/354393
+ * https://stackoverflow.com/questions/11317474/macro-to-count-number-of-arguments
+ */
#define NM_NARG(...) \
- _NM_NARG(__VA_ARGS__,_NM_NARG_RSEQ_N())
+ _NM_NARG(, ##__VA_ARGS__, _NM_NARG_RSEQ_N())
#define _NM_NARG(...) \
_NM_NARG_ARG_N(__VA_ARGS__)
#define _NM_NARG_ARG_N( \
+ _0, \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h
index 0bac6e4a53..e9885c6e35 100644
--- a/shared/nm-utils/nm-shared-utils.h
+++ b/shared/nm-utils/nm-shared-utils.h
@@ -386,12 +386,40 @@ _nm_g_slice_free_fcn_define (16)
* error reason. Depending on the usage, this might indicate a bug because
* usually the target object should stay alive as long as there are pending
* operations.
+ *
+ * @NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE: used for a very particular
+ * purpose during nm_device_check_connection_compatible() to indicate that
+ * the profile does not match the device already because their type differs.
+ * That is, there is a fundamental reason of trying to check a profile that
+ * cannot possibly match on this device.
+ * @NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE: used for a very particular
+ * purpose during nm_device_check_connection_available(), to indicate that the
+ * device is not available because it is unmanaged.
+ * @NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY: the profile is currently not
+ * available/compatible with the device, but this may be only temporary.
+ *
* @NM_UTILS_ERROR_INVALID_ARGUMENT: invalid argument.
*/
typedef enum {
NM_UTILS_ERROR_UNKNOWN = 0, /*< nick=Unknown >*/
NM_UTILS_ERROR_CANCELLED_DISPOSING, /*< nick=CancelledDisposing >*/
NM_UTILS_ERROR_INVALID_ARGUMENT, /*< nick=InvalidArgument >*/
+
+ /* the following codes have a special meaning and are exactly used for
+ * nm_device_check_connection_compatible() and nm_device_check_connection_available().
+ *
+ * Actually, their meaning is not very important (so, don't think too
+ * hard about the name of these error codes). What is important, is their
+ * relative order (i.e. the integer value of the codes). When manager
+ * searches for a suitable device, it will check all devices whether
+ * a profile can be activated. If they all fail, it will pick the error
+ * message from the device that returned the *highest* error code,
+ * in the hope that this message makes the most sense for the caller.
+ * */
+ NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
+ NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE,
+ NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+
} NMUtilsError;
#define NM_UTILS_ERROR (nm_utils_error_quark ())
@@ -403,6 +431,15 @@ void nm_utils_error_set_cancelled (GError **error,
gboolean nm_utils_error_is_cancelled (GError *error,
gboolean consider_is_disposing);
+static inline void
+nm_utils_error_set_literal (GError **error, int error_code, const char *literal)
+{
+ g_set_error_literal (error, NM_UTILS_ERROR, error_code, literal);
+}
+
+#define nm_utils_error_set(error, error_code, ...) \
+ g_set_error ((error), NM_UTILS_ERROR, error_code, __VA_ARGS__)
+
/*****************************************************************************/
gboolean nm_g_object_set_property (GObject *object,
diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c
index 1450a8369d..c9984f5135 100644
--- a/src/devices/adsl/nm-device-adsl.c
+++ b/src/devices/adsl/nm-device-adsl.c
@@ -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;
}
@@ -669,7 +667,7 @@ nm_device_adsl_class_init (NMDeviceAdslClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
object_class->constructed = constructed;
object_class->dispose = dispose;
@@ -678,14 +676,16 @@ nm_device_adsl_class_init (NMDeviceAdslClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_adsl);
- parent_class->get_generic_capabilities = get_generic_capabilities;
+ device_class->connection_type_check_compatible = NM_SETTING_ADSL_SETTING_NAME;
+
+ device_class->get_generic_capabilities = get_generic_capabilities;
- parent_class->check_connection_compatible = check_connection_compatible;
- parent_class->complete_connection = complete_connection;
+ device_class->check_connection_compatible = check_connection_compatible;
+ device_class->complete_connection = complete_connection;
- parent_class->act_stage2_config = act_stage2_config;
- parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
- parent_class->deactivate = deactivate;
+ device_class->act_stage2_config = act_stage2_config;
+ device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
+ device_class->deactivate = deactivate;
obj_properties[PROP_ATM_INDEX] =
g_param_spec_int (NM_DEVICE_ADSL_ATM_INDEX, "", "",
diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c
index 92ad0b31cc..a11c798698 100644
--- a/src/devices/bluetooth/nm-device-bt.c
+++ b/src/devices/bluetooth/nm-device-bt.c
@@ -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))
+ if (!NM_DEVICE_CLASS (nm_device_bt_parent_class)->check_connection_compatible (device, connection, error))
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))
+ bt_type = get_connection_bt_type (connection);
+ 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);
- if (!s_bt)
- return FALSE;
-
- bt_type = get_connection_bt_type (connection);
- if (!(bt_type & priv->capabilities))
- return FALSE;
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;
}
@@ -195,18 +195,25 @@ static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
NMDeviceCheckConAvailableFlags flags,
- const char *specific_object)
+ const char *specific_object,
+ GError **error)
{
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device);
guint32 bt_type;
bt_type = get_connection_bt_type (connection);
- if (!(bt_type & priv->capabilities))
+ if (!(bt_type & priv->capabilities)) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "device does not support bluetooth type");
return FALSE;
+ }
/* DUN connections aren't available without ModemManager */
- if (bt_type == NM_BT_CAPABILITY_DUN && priv->mm_running == FALSE)
+ if (bt_type == NM_BT_CAPABILITY_DUN && priv->mm_running == FALSE) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "ModemManager missing for DUN profile");
return FALSE;
+ }
return TRUE;
}
@@ -1177,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;
diff --git a/src/devices/nm-device-6lowpan.c b/src/devices/nm-device-6lowpan.c
index 9119ab00c3..52dda3bf74 100644
--- a/src/devices/nm-device-6lowpan.c
+++ b/src/devices/nm-device-6lowpan.c
@@ -175,21 +175,6 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags 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,
const char *specific_object,
@@ -218,7 +203,7 @@ complete_connection (NMDevice *device,
* settings, then there's not enough information to complete the setting.
*/
if ( !nm_setting_6lowpan_get_parent (s_6lowpan)
- && !nm_device_match_hwaddr (device, connection, TRUE)) {
+ && !nm_device_match_parent_hwaddr (device, connection, TRUE)) {
g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION,
"The '6lowpan' setting had no interface name, parent, or hardware address.");
return FALSE;
@@ -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)
@@ -296,14 +282,14 @@ nm_device_6lowpan_class_init (NMDevice6LowpanClass *klass)
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_6LOWPAN)
-
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->connection_type = NM_SETTING_6LOWPAN_SETTING_NAME;
device_class->create_and_realize = create_and_realize;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index ff7ecdbe23..6e7e6ffcd1 100644
--- a/src/devices/nm-device-bond.c
+++ b/src/devices/nm-device-bond.c
@@ -56,23 +56,6 @@ get_generic_capabilities (NMDevice *dev)
}
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,
const char *specific_object,
@@ -631,27 +614,28 @@ static void
nm_device_bond_class_init (NMDeviceBondClass *klass)
{
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
-
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_BOND_SETTING_NAME, NM_LINK_TYPE_BOND)
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_bond);
- parent_class->is_master = TRUE;
- parent_class->get_generic_capabilities = get_generic_capabilities;
- parent_class->check_connection_compatible = check_connection_compatible;
- parent_class->complete_connection = complete_connection;
-
- parent_class->update_connection = update_connection;
- parent_class->master_update_slave_connection = master_update_slave_connection;
-
- parent_class->create_and_realize = create_and_realize;
- parent_class->act_stage1_prepare = act_stage1_prepare;
- parent_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
- parent_class->enslave_slave = enslave_slave;
- parent_class->release_slave = release_slave;
- parent_class->can_reapply_change = can_reapply_change;
- parent_class->reapply_connection = reapply_connection;
+ 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->complete_connection = complete_connection;
+
+ device_class->update_connection = update_connection;
+ device_class->master_update_slave_connection = master_update_slave_connection;
+
+ device_class->create_and_realize = create_and_realize;
+ device_class->act_stage1_prepare = act_stage1_prepare;
+ device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
+ device_class->enslave_slave = enslave_slave;
+ device_class->release_slave = release_slave;
+ device_class->can_reapply_change = can_reapply_change;
+ device_class->reapply_connection = reapply_connection;
}
/*****************************************************************************/
diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c
index c81a025338..e79de95cd4 100644
--- a/src/devices/nm-device-bridge.c
+++ b/src/devices/nm-device-bridge.c
@@ -61,41 +61,63 @@ static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
NMDeviceCheckConAvailableFlags flags,
- const char *specific_object)
+ const char *specific_object,
+ GError **error)
{
NMSettingBluetooth *s_bt;
- if (!NM_DEVICE_CLASS (nm_device_bridge_parent_class)->check_connection_available (device, connection, flags, specific_object))
+ if (!NM_DEVICE_CLASS (nm_device_bridge_parent_class)->check_connection_available (device, connection, flags, specific_object, error))
return FALSE;
s_bt = _nm_connection_get_setting_bluetooth_for_nap (connection);
if (s_bt) {
- return nm_bt_vtable_network_server
- && nm_bt_vtable_network_server->is_available (nm_bt_vtable_network_server,
- nm_setting_bluetooth_get_bdaddr (s_bt));
+ const char *bdaddr;
+
+ if (!nm_bt_vtable_network_server) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "bluetooth plugin not available to activate NAP profile");
+ return FALSE;
+ }
+
+ bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt);
+ if (!nm_bt_vtable_network_server->is_available (nm_bt_vtable_network_server, bdaddr)) {
+ if (bdaddr)
+ nm_utils_error_set (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "not suitable NAP device \"%s\" available", bdaddr);
+ else
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "not suitable NAP device available");
+ return FALSE;
+ }
}
return TRUE;
}
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;
}
@@ -104,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;
@@ -505,28 +530,29 @@ static void
nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
{
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
-
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_BRIDGE_SETTING_NAME, NM_LINK_TYPE_BRIDGE)
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_bridge);
- parent_class->is_master = TRUE;
- parent_class->get_generic_capabilities = get_generic_capabilities;
- parent_class->check_connection_compatible = check_connection_compatible;
- parent_class->check_connection_available = check_connection_available;
- parent_class->complete_connection = complete_connection;
-
- parent_class->update_connection = update_connection;
- parent_class->master_update_slave_connection = master_update_slave_connection;
-
- parent_class->create_and_realize = create_and_realize;
- parent_class->act_stage1_prepare = act_stage1_prepare;
- parent_class->act_stage2_config = act_stage2_config;
- parent_class->deactivate = deactivate;
- parent_class->enslave_slave = enslave_slave;
- parent_class->release_slave = release_slave;
- parent_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
+ device_class->connection_type_supported = NM_SETTING_BRIDGE_SETTING_NAME;
+ device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_BRIDGE);
+
+ device_class->is_master = TRUE;
+ device_class->get_generic_capabilities = get_generic_capabilities;
+ device_class->check_connection_compatible = check_connection_compatible;
+ device_class->check_connection_available = check_connection_available;
+ device_class->complete_connection = complete_connection;
+
+ device_class->update_connection = update_connection;
+ device_class->master_update_slave_connection = master_update_slave_connection;
+
+ device_class->create_and_realize = create_and_realize;
+ device_class->act_stage1_prepare = act_stage1_prepare;
+ device_class->act_stage2_config = act_stage2_config;
+ device_class->deactivate = deactivate;
+ device_class->enslave_slave = enslave_slave;
+ device_class->release_slave = release_slave;
+ device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
}
/*****************************************************************************/
diff --git a/src/devices/nm-device-dummy.c b/src/devices/nm-device-dummy.c
index 9be4d29f20..a905938369 100644
--- a/src/devices/nm-device-dummy.c
+++ b/src/devices/nm-device-dummy.c
@@ -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)
{
@@ -173,13 +158,13 @@ nm_device_dummy_class_init (NMDeviceDummyClass *klass)
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_DUMMY)
-
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_dummy);
- device_class->connection_type = NM_SETTING_DUMMY_SETTING_NAME;
+ 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;
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index a9a9f968e6..0d9038983c 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -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;
@@ -1750,12 +1763,10 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
g_type_class_add_private (object_class, sizeof (NMDeviceEthernetPrivate));
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRED_SETTING_NAME, NM_LINK_TYPE_ETHERNET)
-
object_class->dispose = dispose;
object_class->finalize = finalize;
object_class->get_property = get_property;
@@ -1763,25 +1774,28 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_wired);
- parent_class->get_generic_capabilities = get_generic_capabilities;
- parent_class->check_connection_compatible = check_connection_compatible;
- parent_class->complete_connection = complete_connection;
- parent_class->new_default_connection = new_default_connection;
-
- parent_class->act_stage1_prepare = act_stage1_prepare;
- parent_class->act_stage2_config = act_stage2_config;
- parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
- parent_class->get_configured_mtu = get_configured_mtu;
- parent_class->deactivate = deactivate;
- parent_class->get_s390_subchannels = get_s390_subchannels;
- parent_class->update_connection = update_connection;
- parent_class->carrier_changed_notify = carrier_changed_notify;
- parent_class->link_changed = link_changed;
- parent_class->is_available = is_available;
- parent_class->can_reapply_change = can_reapply_change;
- parent_class->reapply_connection = reapply_connection;
-
- parent_class->state_changed = device_state_changed;
+ device_class->connection_type_supported = NM_SETTING_WIRED_SETTING_NAME;
+ device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_ETHERNET);
+
+ device_class->get_generic_capabilities = get_generic_capabilities;
+ device_class->check_connection_compatible = check_connection_compatible;
+ device_class->complete_connection = complete_connection;
+ device_class->new_default_connection = new_default_connection;
+
+ device_class->act_stage1_prepare = act_stage1_prepare;
+ device_class->act_stage2_config = act_stage2_config;
+ device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
+ device_class->get_configured_mtu = get_configured_mtu;
+ device_class->deactivate = deactivate;
+ device_class->get_s390_subchannels = get_s390_subchannels;
+ device_class->update_connection = update_connection;
+ device_class->carrier_changed_notify = carrier_changed_notify;
+ device_class->link_changed = link_changed;
+ device_class->is_available = is_available;
+ device_class->can_reapply_change = can_reapply_change;
+ device_class->reapply_connection = reapply_connection;
+
+ device_class->state_changed = device_state_changed;
obj_properties[PROP_SPEED] =
g_param_spec_uint (NM_DEVICE_ETHERNET_SPEED, "", "",
diff --git a/src/devices/nm-device-generic.c b/src/devices/nm-device-generic.c
index 27eaf8d6ce..d00aa93bb5 100644
--- a/src/devices/nm-device-generic.c
+++ b/src/devices/nm-device-generic.c
@@ -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;
}
@@ -220,9 +220,7 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
-
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_GENERIC_SETTING_NAME, NM_LINK_TYPE_ANY)
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
object_class->constructor = constructor;
object_class->dispose = dispose;
@@ -231,11 +229,15 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_generic);
- parent_class->realize_start_notify = realize_start_notify;
- parent_class->get_generic_capabilities = get_generic_capabilities;
- parent_class->get_type_description = get_type_description;
- parent_class->check_connection_compatible = check_connection_compatible;
- parent_class->update_connection = update_connection;
+ 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;
+ device_class->get_generic_capabilities = get_generic_capabilities;
+ device_class->get_type_description = get_type_description;
+ device_class->check_connection_compatible = check_connection_compatible;
+ device_class->update_connection = update_connection;
obj_properties[PROP_TYPE_DESCRIPTION] =
g_param_spec_string (NM_DEVICE_GENERIC_TYPE_DESCRIPTION, "", "",
diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c
index 122ae25953..41fac157dd 100644
--- a/src/devices/nm-device-infiniband.c
+++ b/src/devices/nm-device-infiniband.c
@@ -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;
+ }
}
}
@@ -367,24 +365,26 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
-
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_INFINIBAND_SETTING_NAME, NM_LINK_TYPE_INFINIBAND)
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
object_class->get_property = get_property;
object_class->set_property = set_property;
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_infiniband);
- parent_class->create_and_realize = create_and_realize;
- parent_class->unrealize = unrealize;
- parent_class->get_generic_capabilities = get_generic_capabilities;
- parent_class->check_connection_compatible = check_connection_compatible;
- parent_class->complete_connection = complete_connection;
- parent_class->update_connection = update_connection;
+ 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;
+ device_class->unrealize = unrealize;
+ 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;
- parent_class->act_stage1_prepare = act_stage1_prepare;
- parent_class->get_configured_mtu = get_configured_mtu;
+ device_class->act_stage1_prepare = act_stage1_prepare;
+ device_class->get_configured_mtu = get_configured_mtu;
obj_properties[PROP_IS_PARTITION] =
g_param_spec_boolean (NM_DEVICE_INFINIBAND_IS_PARTITION, "", "",
diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c
index 35c9b0b6f6..642bb25447 100644
--- a/src/devices/nm-device-ip-tunnel.c
+++ b/src/devices/nm-device-ip-tunnel.c
@@ -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;
+ }
}
}
@@ -1043,6 +1068,16 @@ 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,
+ NM_LINK_TYPE_IP6GRE,
+ NM_LINK_TYPE_IP6GRETAP,
+ NM_LINK_TYPE_IPIP,
+ NM_LINK_TYPE_SIT);
+
device_class->act_stage1_prepare = act_stage1_prepare;
device_class->link_changed = link_changed;
device_class->can_reapply_change = can_reapply_change;
@@ -1054,16 +1089,6 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass)
device_class->get_configured_mtu = get_configured_mtu;
device_class->unrealize_notify = unrealize_notify;
- NM_DEVICE_CLASS_DECLARE_TYPES (klass,
- NM_SETTING_IP_TUNNEL_SETTING_NAME,
- NM_LINK_TYPE_GRE,
- NM_LINK_TYPE_GRETAP,
- NM_LINK_TYPE_IP6TNL,
- NM_LINK_TYPE_IP6GRE,
- NM_LINK_TYPE_IP6GRETAP,
- NM_LINK_TYPE_IPIP,
- NM_LINK_TYPE_SIT);
-
obj_properties[PROP_MODE] =
g_param_spec_uint (NM_DEVICE_IP_TUNNEL_MODE, "", "",
0, G_MAXUINT, 0,
diff --git a/src/devices/nm-device-macsec.c b/src/devices/nm-device-macsec.c
index 166bfb57a4..8ea4c8b562 100644
--- a/src/devices/nm-device-macsec.c
+++ b/src/devices/nm-device-macsec.c
@@ -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
@@ -841,27 +826,26 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
-
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_MACSEC)
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
object_class->get_property = get_property;
object_class->dispose = dispose;
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_macsec);
- parent_class->act_stage2_config = act_stage2_config;
- parent_class->check_connection_compatible = check_connection_compatible;
- parent_class->create_and_realize = create_and_realize;
- parent_class->deactivate = deactivate;
- parent_class->get_generic_capabilities = get_generic_capabilities;
- parent_class->link_changed = link_changed;
- parent_class->is_available = is_available;
- parent_class->parent_changed_notify = parent_changed_notify;
- parent_class->state_changed = device_state_changed;
- parent_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
-
- parent_class->connection_type = NM_SETTING_MACSEC_SETTING_NAME;
+ 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->create_and_realize = create_and_realize;
+ device_class->deactivate = deactivate;
+ device_class->get_generic_capabilities = get_generic_capabilities;
+ device_class->link_changed = link_changed;
+ device_class->is_available = is_available;
+ device_class->parent_changed_notify = parent_changed_notify;
+ device_class->state_changed = device_state_changed;
+ device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
obj_properties[PROP_SCI] =
g_param_spec_uint64 (NM_DEVICE_MACSEC_SCI, "", "",
diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c
index dc4fb3e835..fa9a7b0d69 100644
--- a/src/devices/nm-device-macvlan.c
+++ b/src/devices/nm-device-macvlan.c
@@ -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_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;
+ }
}
}
@@ -359,7 +377,7 @@ complete_connection (NMDevice *device,
* settings, then there's not enough information to complete the setting.
*/
if ( !nm_setting_macvlan_get_parent (s_macvlan)
- && !nm_device_match_hwaddr (device, connection, TRUE)) {
+ && !nm_device_match_parent_hwaddr (device, connection, TRUE)) {
g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION,
"The 'macvlan' setting had no interface name, parent, or hardware address.");
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)
@@ -495,17 +513,18 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP)
-
object_class->get_property = get_property;
object_class->set_property = set_property;
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;
device_class->check_connection_compatible = check_connection_compatible;
device_class->complete_connection = complete_connection;
- device_class->connection_type = NM_SETTING_MACVLAN_SETTING_NAME;
device_class->create_and_realize = create_and_realize;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
diff --git a/src/devices/nm-device-ppp.c b/src/devices/nm-device-ppp.c
index a6abb228a6..74b4d710ca 100644
--- a/src/devices/nm-device-ppp.c
+++ b/src/devices/nm-device-ppp.c
@@ -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)
{
@@ -275,20 +257,21 @@ nm_device_ppp_class_init (NMDevicePppClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
-
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_PPPOE_SETTING_NAME, NM_LINK_TYPE_PPP)
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
object_class->dispose = dispose;
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ppp);
- parent_class->act_stage2_config = act_stage2_config;
- parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
- parent_class->check_connection_compatible = check_connection_compatible;
- parent_class->create_and_realize = create_and_realize;
- parent_class->deactivate = deactivate;
- parent_class->get_generic_capabilities = get_generic_capabilities;
+ 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->create_and_realize = create_and_realize;
+ device_class->deactivate = deactivate;
+ device_class->get_generic_capabilities = get_generic_capabilities;
}
/*****************************************************************************/
diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h
index ba28e9e429..66c715de90 100644
--- a/src/devices/nm-device-private.h
+++ b/src/devices/nm-device-private.h
@@ -130,12 +130,21 @@ void nm_device_commit_mtu (NMDevice *self);
/*****************************************************************************/
-#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; \
- }
+#define NM_DEVICE_DEFINE_LINK_TYPES(...) \
+ ((NM_NARG (__VA_ARGS__) == 0) \
+ ? NULL \
+ : ({ \
+ static const struct { \
+ const NMLinkType types[NM_NARG (__VA_ARGS__)]; \
+ const NMLinkType sentinel; \
+ } _link_types = { \
+ .types = { __VA_ARGS__ }, \
+ .sentinel = NM_LINK_TYPE_NONE, \
+ }; \
+ \
+ _link_types.types; \
+ })\
+ )
gboolean _nm_device_hash_check_invalid_keys (GHashTable *hash, const char *setting_name,
GError **error, const char **whitelist);
@@ -143,8 +152,8 @@ gboolean _nm_device_hash_check_invalid_keys (GHashTable *hash, const char *setti
_nm_device_hash_check_invalid_keys (hash, setting_name, error, ((const char *[]) { __VA_ARGS__, NULL }))
gboolean nm_device_match_parent (NMDevice *device, const char *parent);
-gboolean nm_device_match_hwaddr (NMDevice *device,
- NMConnection *connection,
- gboolean fail_if_no_hwaddr);
+gboolean nm_device_match_parent_hwaddr (NMDevice *device,
+ NMConnection *connection,
+ gboolean fail_if_no_hwaddr);
#endif /* NM_DEVICE_PRIVATE_H */
diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c
index 3846676c1f..0f76b23a4b 100644
--- a/src/devices/nm-device-tun.c
+++ b/src/devices/nm-device-tun.c
@@ -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;
@@ -430,13 +447,14 @@ nm_device_tun_class_init (NMDeviceTunClass *klass)
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_TUN)
-
object_class->get_property = get_property;
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_tun);
- device_class->connection_type = NM_SETTING_TUN_SETTING_NAME;
+ 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;
device_class->complete_connection = complete_connection;
device_class->check_connection_compatible = check_connection_compatible;
diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c
index 186173eb88..6f90758cd5 100644
--- a/src/devices/nm-device-veth.c
+++ b/src/devices/nm-device-veth.c
@@ -153,12 +153,13 @@ nm_device_veth_class_init (NMDeviceVethClass *klass)
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_VETH)
-
object_class->get_property = get_property;
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_veth);
+ device_class->connection_type_supported = NULL;
+ device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_VETH);
+
device_class->can_unmanaged_external_down = can_unmanaged_external_down;
device_class->link_changed = link_changed;
device_class->parent_changed_notify = parent_changed_notify;
diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c
index b0e746a822..d6376489f4 100644
--- a/src/devices/nm-device-vlan.c
+++ b/src/devices/nm-device-vlan.c
@@ -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;
-
- if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_compatible (device, connection))
- return FALSE;
+ const char *parent;
- s_vlan = nm_connection_get_setting_vlan (connection);
- if (!s_vlan)
+ if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_compatible (device, connection, error))
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_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;
+ }
}
}
@@ -368,12 +374,13 @@ static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
NMDeviceCheckConAvailableFlags flags,
- const char *specific_object)
+ const char *specific_object,
+ GError **error)
{
if (!nm_device_is_real (device))
return TRUE;
- return NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_available (device, connection, flags, specific_object);
+ return NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_available (device, connection, flags, specific_object, error);
}
static gboolean
@@ -405,7 +412,7 @@ complete_connection (NMDevice *device,
* settings, then there's not enough information to complete the setting.
*/
if ( !nm_setting_vlan_get_parent (s_vlan)
- && !nm_device_match_hwaddr (device, connection, TRUE)) {
+ && !nm_device_match_parent_hwaddr (device, connection, TRUE)) {
g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION,
"The 'vlan' setting had no interface name, parent, or hardware address.");
return FALSE;
@@ -454,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)
@@ -599,27 +606,29 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
-
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_VLAN_SETTING_NAME, NM_LINK_TYPE_VLAN)
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
object_class->get_property = get_property;
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_vlan);
- parent_class->create_and_realize = create_and_realize;
- parent_class->link_changed = link_changed;
- parent_class->unrealize_notify = unrealize_notify;
- parent_class->get_generic_capabilities = get_generic_capabilities;
- parent_class->act_stage1_prepare = act_stage1_prepare;
- parent_class->get_configured_mtu = get_configured_mtu;
- parent_class->is_available = is_available;
- parent_class->parent_changed_notify = parent_changed_notify;
-
- parent_class->check_connection_compatible = check_connection_compatible;
- parent_class->check_connection_available = check_connection_available;
- parent_class->complete_connection = complete_connection;
- parent_class->update_connection = update_connection;
+ 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;
+ device_class->link_changed = link_changed;
+ device_class->unrealize_notify = unrealize_notify;
+ device_class->get_generic_capabilities = get_generic_capabilities;
+ device_class->act_stage1_prepare = act_stage1_prepare;
+ device_class->get_configured_mtu = get_configured_mtu;
+ device_class->is_available = is_available;
+ device_class->parent_changed_notify = parent_changed_notify;
+
+ device_class->check_connection_compatible = check_connection_compatible;
+ device_class->check_connection_available = check_connection_available;
+ device_class->complete_connection = complete_connection;
+ device_class->update_connection = update_connection;
obj_properties[PROP_VLAN_ID] =
g_param_spec_uint (NM_DEVICE_VLAN_ID, "", "",
diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c
index e125222374..f6f15729b2 100644
--- a/src/devices/nm-device-vxlan.c
+++ b/src/devices/nm-device-vxlan.c
@@ -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;
}
}
@@ -577,15 +620,16 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass)
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_VXLAN)
-
object_class->get_property = get_property;
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;
device_class->unrealize_notify = unrealize_notify;
- device_class->connection_type = NM_SETTING_VXLAN_SETTING_NAME;
device_class->create_and_realize = create_and_realize;
device_class->check_connection_compatible = check_connection_compatible;
device_class->complete_connection = complete_connection;
diff --git a/src/devices/nm-device-wpan.c b/src/devices/nm-device-wpan.c
index 978dfa00ac..dd2ebac149 100644
--- a/src/devices/nm-device-wpan.c
+++ b/src/devices/nm-device-wpan.c
@@ -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;
@@ -213,11 +214,12 @@ nm_device_wpan_class_init (NMDeviceWpanClass *klass)
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_WPAN)
-
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_wpan);
- device_class->connection_type = NM_SETTING_WPAN_SETTING_NAME;
+ 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;
device_class->check_connection_compatible = check_connection_compatible;
device_class->update_connection = update_connection;
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 7ca2360b27..33faa4bf4f 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -5115,7 +5115,7 @@ nm_device_can_auto_connect (NMDevice *self,
* over and over again. The caller is supposed to do that. */
nm_assert (nm_device_autoconnect_allowed (self));
- if (!nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL))
+ if (!nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL, NULL))
return FALSE;
if (!NM_DEVICE_GET_CLASS (self)->can_auto_connect (self, connection, specific_object))
@@ -5239,8 +5239,10 @@ nm_device_generate_connection (NMDevice *self,
NM_SETTING_CONNECTION_INTERFACE_NAME, ifname,
NM_SETTING_CONNECTION_TIMESTAMP, (guint64) time (NULL),
NULL);
- if (klass->connection_type)
- g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, klass->connection_type, NULL);
+
+ if (klass->connection_type_supported)
+ g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, klass->connection_type_supported, NULL);
+
nm_connection_add_setting (connection, s_con);
/* If the device is a slave, update various slave settings */
@@ -5392,9 +5394,9 @@ nm_device_match_parent (NMDevice *self, const char *parent)
}
gboolean
-nm_device_match_hwaddr (NMDevice *device,
- NMConnection *connection,
- gboolean fail_if_no_hwaddr)
+nm_device_match_parent_hwaddr (NMDevice *device,
+ NMConnection *connection,
+ gboolean fail_if_no_hwaddr)
{
NMSettingWired *s_wired;
NMDevice *parent_device;
@@ -5418,21 +5420,43 @@ nm_device_match_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;
}
@@ -5441,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
@@ -5453,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
@@ -5474,7 +5503,7 @@ nm_device_check_slave_connection_compatible (NMDevice *self, NMConnection *slave
return FALSE;
/* All masters should have connection type set */
- connection_type = NM_DEVICE_GET_CLASS (self)->connection_type;
+ connection_type = NM_DEVICE_GET_CLASS (self)->connection_type_supported;
g_return_val_if_fail (connection_type, FALSE);
s_con = nm_connection_get_setting_connection (slave);
@@ -11337,7 +11366,7 @@ _carrier_wait_check_act_request_must_queue (NMDevice *self, NMActRequest *req)
if (!connection_requires_carrier (connection))
return FALSE;
- if (!nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_ALL, NULL)) {
+ if (!nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_ALL, NULL, NULL)) {
/* We passed all @flags we have, and no @specific_object.
* This equals maximal availability, if a connection is not available
* in this case, it is not waiting for carrier.
@@ -11348,7 +11377,9 @@ _carrier_wait_check_act_request_must_queue (NMDevice *self, NMActRequest *req)
return FALSE;
}
- if (nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_ALL & ~_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER, NULL)) {
+ if (nm_device_check_connection_available (self, connection,
+ NM_DEVICE_CHECK_CON_AVAILABLE_ALL & ~_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER,
+ NULL, NULL)) {
/* The connection was available with flags ALL, and it is still available
* if we pretend not to wait for carrier. That means that the
* connection is available now, and does not wait for carrier.
@@ -13209,38 +13240,88 @@ static gboolean
_nm_device_check_connection_available (NMDevice *self,
NMConnection *connection,
NMDeviceCheckConAvailableFlags flags,
- const char *specific_object)
+ const char *specific_object,
+ 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))
- return nm_device_check_connection_compatible (self, connection);
+ if (nm_device_is_software (self)) {
+ 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;
+ }
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE,
+ "hardware device is not realized");
return FALSE;
}
state = nm_device_get_state (self);
- if (state < NM_DEVICE_STATE_UNMANAGED)
- return FALSE;
- if ( state < NM_DEVICE_STATE_UNAVAILABLE
- && ( ( !NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)
- && !nm_device_get_managed (self, FALSE))
- || ( NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)
- && !nm_device_get_managed (self, TRUE))))
+ if (state < NM_DEVICE_STATE_UNMANAGED) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE,
+ "device is in unknown state");
return FALSE;
+ }
+ if (state < NM_DEVICE_STATE_UNAVAILABLE) {
+ if (NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)) {
+ if (!nm_device_get_managed (self, TRUE)) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE,
+ "device is unmanaged");
+ return FALSE;
+ }
+ } else {
+ if (!nm_device_get_managed (self, FALSE)) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE,
+ "device is unmanaged for interal request");
+ return FALSE;
+ }
+ }
+ }
if ( state < NM_DEVICE_STATE_DISCONNECTED
- && !nm_device_is_software (self)
- && ( ( !NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)
- && !nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE))
- || ( NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)
- && !nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST))))
- return FALSE;
+ && !nm_device_is_software (self)) {
+ if (NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)) {
+ if (!nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST)) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "device is not available");
+ return FALSE;
+ }
+ } else {
+ if (!nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "device is not available for internal request");
+ return FALSE;
+ }
+ }
+ }
- if (!nm_device_check_connection_compatible (self, connection))
+ 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;
+ }
- return NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, flags, specific_object);
+ return NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, flags, specific_object, error);
}
/**
@@ -13253,6 +13334,7 @@ _nm_device_check_connection_available (NMDevice *self,
* @specific_object: a device type dependent argument to further
* filter the result. Passing a non %NULL specific object can only reduce
* the availability of a connection.
+ * @error: optionally give reason why not available.
*
* Check if @connection is available to be activated on @self.
*
@@ -13262,11 +13344,12 @@ gboolean
nm_device_check_connection_available (NMDevice *self,
NMConnection *connection,
NMDeviceCheckConAvailableFlags flags,
- const char *specific_object)
+ const char *specific_object,
+ GError **error)
{
gboolean available;
- available = _nm_device_check_connection_available (self, connection, flags, specific_object);
+ available = _nm_device_check_connection_available (self, connection, flags, specific_object, error);
#if NM_MORE_ASSERTS >= 2
{
@@ -13276,7 +13359,7 @@ nm_device_check_connection_available (NMDevice *self,
gboolean available_all[NM_DEVICE_CHECK_CON_AVAILABLE_ALL + 1] = { FALSE };
for (i = 0; i <= NM_DEVICE_CHECK_CON_AVAILABLE_ALL; i++)
- available_all[i] = _nm_device_check_connection_available (self, connection, i, specific_object);
+ available_all[i] = _nm_device_check_connection_available (self, connection, i, specific_object, NULL);
for (i = 0; i <= NM_DEVICE_CHECK_CON_AVAILABLE_ALL; i++) {
for (j = 1; j <= NM_DEVICE_CHECK_CON_AVAILABLE_ALL; j <<= 1) {
@@ -13318,7 +13401,8 @@ static gboolean
check_connection_available (NMDevice *self,
NMConnection *connection,
NMDeviceCheckConAvailableFlags flags,
- const char *specific_object)
+ const char *specific_object,
+ GError **error)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
@@ -13344,6 +13428,8 @@ check_connection_available (NMDevice *self,
if (nm_device_is_master (self))
return TRUE;
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "device has no carrier");
return FALSE;
}
@@ -13376,6 +13462,7 @@ nm_device_recheck_available_connections (NMDevice *self)
if (nm_device_check_connection_available (self,
connection,
NM_DEVICE_CHECK_CON_AVAILABLE_NONE,
+ NULL,
NULL)) {
if (available_connections_add (self, connection))
changed = TRUE;
@@ -13430,7 +13517,8 @@ nm_device_get_best_connection (NMDevice *self,
&& !nm_device_check_connection_available (self,
NM_CONNECTION (candidate),
_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST,
- specific_object))
+ specific_object,
+ NULL))
continue;
nm_settings_connection_get_timestamp (candidate, &candidate_timestamp);
@@ -13460,6 +13548,7 @@ cp_connection_added_or_updated (NMDevice *self, NMConnection *connection)
if (nm_device_check_connection_available (self,
connection,
_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST,
+ NULL,
NULL))
changed = available_connections_add (self, connection);
else
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index d145f8fc20..41156c1008 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -202,7 +202,12 @@ typedef struct _NMDeviceClass {
struct _NMDeviceClass *default_type_description_klass;
const char *default_type_description;
- const char *connection_type;
+ 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
@@ -317,7 +324,8 @@ typedef struct _NMDeviceClass {
gboolean (* check_connection_available) (NMDevice *self,
NMConnection *connection,
NMDeviceCheckConAvailableFlags flags,
- const char *specific_object);
+ const char *specific_object,
+ GError **error);
gboolean (* complete_connection) (NMDevice *self,
NMConnection *connection,
@@ -533,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);
@@ -742,7 +753,8 @@ NMSettingsConnection *nm_device_get_best_connection (NMDevice *device,
gboolean nm_device_check_connection_available (NMDevice *device,
NMConnection *connection,
NMDeviceCheckConAvailableFlags flags,
- const char *specific_object);
+ const char *specific_object,
+ GError **error);
gboolean nm_device_notify_component_added (NMDevice *device, GObject *component);
diff --git a/src/devices/ovs/nm-device-ovs-bridge.c b/src/devices/ovs/nm-device-ovs-bridge.c
index 2e4d1cbdf8..eff355a3ef 100644
--- a/src/devices/ovs/nm-device-ovs-bridge.c
+++ b/src/devices/ovs/nm-device-ovs-bridge.c
@@ -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,
@@ -152,13 +137,15 @@ 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 = NM_SETTING_OVS_BRIDGE_SETTING_NAME;
+ 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;
device_class->get_type_description = get_type_description;
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;
diff --git a/src/devices/ovs/nm-device-ovs-interface.c b/src/devices/ovs/nm-device-ovs-interface.c
index c59af7a6b1..2b48fae683 100644
--- a/src/devices/ovs/nm-device-ovs-interface.c
+++ b/src/devices/ovs/nm-device-ovs-interface.c
@@ -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;
}
@@ -199,11 +194,12 @@ nm_device_ovs_interface_class_init (NMDeviceOvsInterfaceClass *klass)
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_OPENVSWITCH);
-
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ovs_interface);
- device_class->connection_type = NM_SETTING_OVS_INTERFACE_SETTING_NAME;
+ 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;
device_class->create_and_realize = create_and_realize;
device_class->get_generic_capabilities = get_generic_capabilities;
diff --git a/src/devices/ovs/nm-device-ovs-port.c b/src/devices/ovs/nm-device-ovs-port.c
index a9a2b24a2b..1f9afbab5b 100644
--- a/src/devices/ovs/nm-device-ovs-port.c
+++ b/src/devices/ovs/nm-device-ovs-port.c
@@ -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,
@@ -198,12 +178,14 @@ 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 = NM_SETTING_OVS_PORT_SETTING_NAME;
+ 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;
diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c
index ef7c63b8a8..899932fd4b 100644
--- a/src/devices/team/nm-device-team.c
+++ b/src/devices/team/nm-device-team.c
@@ -85,23 +85,6 @@ get_generic_capabilities (NMDevice *device)
}
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,
const char *specific_object,
@@ -911,9 +894,7 @@ nm_device_team_class_init (NMDeviceTeamClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
-
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_TEAM_SETTING_NAME, NM_LINK_TYPE_TEAM)
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
object_class->constructed = constructed;
object_class->dispose = dispose;
@@ -921,19 +902,22 @@ nm_device_team_class_init (NMDeviceTeamClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_team);
- parent_class->is_master = TRUE;
- parent_class->create_and_realize = create_and_realize;
- parent_class->get_generic_capabilities = get_generic_capabilities;
- parent_class->check_connection_compatible = check_connection_compatible;
- parent_class->complete_connection = complete_connection;
- parent_class->update_connection = update_connection;
- parent_class->master_update_slave_connection = master_update_slave_connection;
-
- parent_class->act_stage1_prepare = act_stage1_prepare;
- parent_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
- parent_class->deactivate = deactivate;
- parent_class->enslave_slave = enslave_slave;
- parent_class->release_slave = release_slave;
+ 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->complete_connection = complete_connection;
+ device_class->update_connection = update_connection;
+ device_class->master_update_slave_connection = master_update_slave_connection;
+
+ device_class->act_stage1_prepare = act_stage1_prepare;
+ device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
+ device_class->deactivate = deactivate;
+ device_class->enslave_slave = enslave_slave;
+ device_class->release_slave = release_slave;
obj_properties[PROP_CONFIG] =
g_param_spec_string (NM_DEVICE_TEAM_CONFIG, "", "",
diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c
index cdb688d9ae..aaf8e81bb5 100644
--- a/src/devices/wifi/nm-device-iwd.c
+++ b/src/devices/wifi/nm-device-iwd.c
@@ -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 ();
- return FALSE;
- }
+ nm_assert (nm_utils_hwaddr_valid (mac_blacklist[i], ETH_ALEN));
- 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,
+ "mac address blacklisted");
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;
@@ -554,7 +557,8 @@ static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
NMDeviceCheckConAvailableFlags flags,
- const char *specific_object)
+ const char *specific_object,
+ GError **error)
{
NMDeviceIwd *self = NM_DEVICE_IWD (device);
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
@@ -566,19 +570,28 @@ check_connection_available (NMDevice *device,
/* Only Infrastrusture mode at this time */
mode = nm_setting_wireless_get_mode (s_wifi);
- if (mode && g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0)
+ if (!NM_IN_SET (mode, NULL, NM_SETTING_WIRELESS_MODE_INFRA)) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "iwd only supports infrastructure mode connections");
return FALSE;
+ }
/* Hidden SSIDs not supported yet */
- if (nm_setting_wireless_get_hidden (s_wifi))
+ if (nm_setting_wireless_get_hidden (s_wifi)) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "hidden networks not supported by iwd");
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,
+ "network is not known to iwd");
return FALSE;
+ }
}
/* a connection that is available for a certain @specific_object, MUST
@@ -588,14 +601,29 @@ check_connection_available (NMDevice *device,
NMWifiAP *ap;
ap = nm_wifi_ap_lookup_for_device (NM_DEVICE (self), specific_object);
- return ap ? nm_wifi_ap_check_compatible (ap, connection) : FALSE;
+ if (!ap) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "requested access point not found");
+ return FALSE;
+ }
+ if (!nm_wifi_ap_check_compatible (ap, connection)) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "requested access point is not compatible with profile");
+ return FALSE;
+ }
+ return TRUE;
}
if (NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP))
return TRUE;
- /* Check at least one AP is compatible with this connection */
- return !!nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection);
+ if (!nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection)) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "no compatible access point found");
+ return FALSE;
+ }
+
+ return TRUE;
}
static gboolean
@@ -1952,9 +1980,7 @@ nm_device_iwd_class_init (NMDeviceIwdClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
-
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRELESS_SETTING_NAME, NM_LINK_TYPE_WIFI)
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
object_class->get_property = get_property;
object_class->set_property = set_property;
@@ -1962,25 +1988,29 @@ nm_device_iwd_class_init (NMDeviceIwdClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&nm_interface_info_device_wireless);
- parent_class->can_auto_connect = can_auto_connect;
- parent_class->is_available = is_available;
- parent_class->get_autoconnect_allowed = get_autoconnect_allowed;
- parent_class->check_connection_compatible = check_connection_compatible;
- parent_class->check_connection_available = check_connection_available;
- parent_class->complete_connection = complete_connection;
- parent_class->get_enabled = get_enabled;
- parent_class->set_enabled = set_enabled;
- parent_class->get_type_description = get_type_description;
-
- parent_class->act_stage1_prepare = act_stage1_prepare;
- parent_class->act_stage2_config = act_stage2_config;
- parent_class->get_configured_mtu = get_configured_mtu;
- parent_class->deactivate = deactivate;
- parent_class->deactivate_async = deactivate_async;
- parent_class->deactivate_async_finish = deactivate_async_finish;
- parent_class->can_reapply_change = can_reapply_change;
-
- parent_class->state_changed = device_state_changed;
+ 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;
+ device_class->is_available = is_available;
+ device_class->get_autoconnect_allowed = get_autoconnect_allowed;
+ device_class->check_connection_compatible = check_connection_compatible;
+ device_class->check_connection_available = check_connection_available;
+ device_class->complete_connection = complete_connection;
+ device_class->get_enabled = get_enabled;
+ device_class->set_enabled = set_enabled;
+ device_class->get_type_description = get_type_description;
+
+ device_class->act_stage1_prepare = act_stage1_prepare;
+ device_class->act_stage2_config = act_stage2_config;
+ device_class->get_configured_mtu = get_configured_mtu;
+ device_class->deactivate = deactivate;
+ device_class->deactivate_async = deactivate_async;
+ device_class->deactivate_async_finish = deactivate_async_finish;
+ device_class->can_reapply_change = can_reapply_change;
+
+ device_class->state_changed = device_state_changed;
klass->scanning_prohibited = scanning_prohibited;
diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c
index fd7bf3f76f..7737f19a71 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.c
+++ b/src/devices/wifi/nm-device-olpc-mesh.c
@@ -80,28 +80,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)
{
return FALSE;
@@ -515,9 +493,7 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
-
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_OLPC_MESH_SETTING_NAME, NM_LINK_TYPE_OLPC_MESH)
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
object_class->constructed = constructed;
object_class->get_property = get_property;
@@ -525,14 +501,17 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_olpc_mesh);
- parent_class->check_connection_compatible = check_connection_compatible;
- parent_class->get_autoconnect_allowed = get_autoconnect_allowed;
- parent_class->complete_connection = complete_connection;
- parent_class->is_available = is_available;
- parent_class->act_stage1_prepare = act_stage1_prepare;
- parent_class->act_stage2_config = act_stage2_config;
- parent_class->state_changed = state_changed;
- parent_class->get_dhcp_timeout = get_dhcp_timeout;
+ 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->get_autoconnect_allowed = get_autoconnect_allowed;
+ device_class->complete_connection = complete_connection;
+ device_class->is_available = is_available;
+ device_class->act_stage1_prepare = act_stage1_prepare;
+ device_class->act_stage2_config = act_stage2_config;
+ device_class->state_changed = state_changed;
+ device_class->get_dhcp_timeout = get_dhcp_timeout;
obj_properties[PROP_COMPANION] =
g_param_spec_string (NM_DEVICE_OLPC_MESH_COMPANION, "", "",
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 83f8afb6de..d43559a3a0 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -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);
@@ -678,7 +669,8 @@ static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
NMDeviceCheckConAvailableFlags flags,
- const char *specific_object)
+ const char *specific_object,
+ GError **error)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (device);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
@@ -695,7 +687,17 @@ check_connection_available (NMDevice *device,
NMWifiAP *ap;
ap = nm_wifi_ap_lookup_for_device (NM_DEVICE (self), specific_object);
- return ap ? nm_wifi_ap_check_compatible (ap, connection) : FALSE;
+ if (!ap) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "requested access point not found");
+ return FALSE;
+ }
+ if (!nm_wifi_ap_check_compatible (ap, connection)) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "requested access point is not compatible with profile");
+ return FALSE;
+ }
+ return TRUE;
}
/* Ad-Hoc and AP connections are always available because they may be
@@ -714,11 +716,17 @@ check_connection_available (NMDevice *device,
* activating but the network isn't available let the device recheck
* availability.
*/
- if (nm_setting_wireless_get_hidden (s_wifi) || NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP))
+ if ( nm_setting_wireless_get_hidden (s_wifi)
+ || NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP))
return TRUE;
- /* check at least one AP is compatible with this connection */
- return !!nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection);
+ if (!nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection)) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "no compatible access point found");
+ return FALSE;
+ }
+
+ return TRUE;
}
static gboolean
@@ -3311,9 +3319,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
- NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
-
- NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRELESS_SETTING_NAME, NM_LINK_TYPE_WIFI)
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
object_class->constructed = constructed;
object_class->get_property = get_property;
@@ -3323,29 +3329,33 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&nm_interface_info_device_wireless);
- parent_class->can_auto_connect = can_auto_connect;
- parent_class->get_autoconnect_allowed = get_autoconnect_allowed;
- parent_class->is_available = is_available;
- parent_class->check_connection_compatible = check_connection_compatible;
- parent_class->check_connection_available = check_connection_available;
- parent_class->complete_connection = complete_connection;
- parent_class->get_enabled = get_enabled;
- parent_class->set_enabled = set_enabled;
-
- parent_class->act_stage1_prepare = act_stage1_prepare;
- parent_class->act_stage2_config = act_stage2_config;
- parent_class->get_configured_mtu = get_configured_mtu;
- parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
- parent_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
- parent_class->act_stage4_ip4_config_timeout = act_stage4_ip4_config_timeout;
- parent_class->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout;
- parent_class->deactivate = deactivate;
- parent_class->deactivate_reset_hw_addr = deactivate_reset_hw_addr;
- parent_class->unmanaged_on_quit = unmanaged_on_quit;
- parent_class->can_reapply_change = can_reapply_change;
- parent_class->reapply_connection = reapply_connection;
-
- parent_class->state_changed = device_state_changed;
+ 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;
+ device_class->get_autoconnect_allowed = get_autoconnect_allowed;
+ device_class->is_available = is_available;
+ device_class->check_connection_compatible = check_connection_compatible;
+ device_class->check_connection_available = check_connection_available;
+ device_class->complete_connection = complete_connection;
+ device_class->get_enabled = get_enabled;
+ device_class->set_enabled = set_enabled;
+
+ device_class->act_stage1_prepare = act_stage1_prepare;
+ device_class->act_stage2_config = act_stage2_config;
+ device_class->get_configured_mtu = get_configured_mtu;
+ 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->act_stage4_ip4_config_timeout = act_stage4_ip4_config_timeout;
+ device_class->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout;
+ device_class->deactivate = deactivate;
+ device_class->deactivate_reset_hw_addr = deactivate_reset_hw_addr;
+ device_class->unmanaged_on_quit = unmanaged_on_quit;
+ device_class->can_reapply_change = can_reapply_change;
+ device_class->reapply_connection = reapply_connection;
+
+ device_class->state_changed = device_state_changed;
klass->scanning_prohibited = scanning_prohibited;
diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c
index 352b1c3e8b..4119d5987a 100644
--- a/src/devices/wwan/nm-device-modem.c
+++ b/src/devices/wwan/nm-device-modem.c
@@ -397,34 +397,67 @@ 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
check_connection_available (NMDevice *device,
NMConnection *connection,
NMDeviceCheckConAvailableFlags flags,
- const char *specific_object)
+ const char *specific_object,
+ GError **error)
{
NMDeviceModem *self = NM_DEVICE_MODEM (device);
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self);
NMModemState state;
- if (!priv->rf_enabled || !priv->modem)
+ if (!priv->rf_enabled) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "RFKILL for modem enabled");
return FALSE;
+ }
+
+ if (!priv->modem) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "modem not available");
+ return FALSE;
+ }
state = nm_modem_get_state (priv->modem);
- if (state <= NM_MODEM_STATE_INITIALIZING)
+ if (state <= NM_MODEM_STATE_INITIALIZING) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "modem not initalized");
return FALSE;
+ }
if (state == NM_MODEM_STATE_LOCKED) {
- if (!nm_connection_get_setting_gsm (connection))
+ if (!nm_connection_get_setting_gsm (connection)) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+ "modem is locked without pin available");
return FALSE;
+ }
}
return TRUE;
diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c
index 678c92bf7e..253574d589 100644
--- a/src/devices/wwan/nm-modem-broadband.c
+++ b/src/devices/wwan/nm-modem-broadband.c
@@ -617,44 +617,40 @@ act_stage1_prepare (NMModem *_self,
/*****************************************************************************/
static gboolean
-check_connection_compatible (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;
}
@@ -1476,7 +1472,7 @@ nm_modem_broadband_class_init (NMModemBroadbandClass *klass)
modem_class->deactivate_cleanup = deactivate_cleanup;
modem_class->set_mm_enabled = set_mm_enabled;
modem_class->get_user_pass = get_user_pass;
- modem_class->check_connection_compatible = check_connection_compatible;
+ modem_class->check_connection_compatible_with_modem = check_connection_compatible_with_modem;
modem_class->complete_connection = complete_connection;
modem_class->act_stage1_prepare = act_stage1_prepare;
modem_class->owns_port = owns_port;
diff --git a/src/devices/wwan/nm-modem-ofono.c b/src/devices/wwan/nm-modem-ofono.c
index 1ced1335e8..ea66859038 100644
--- a/src/devices/wwan/nm-modem-ofono.c
+++ b/src/devices/wwan/nm-modem-ofono.c
@@ -279,47 +279,42 @@ deactivate_cleanup (NMModem *modem, NMDevice *device)
}
static gboolean
-check_connection_compatible (NMModem *modem,
- NMConnection *connection)
+check_connection_compatible_with_modem (NMModem *modem,
+ 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);
- return FALSE;
- }
+ id = nm_connection_get_id (connection);
- if (!g_strrstr (id, "/context")) {
- _LOGD ("skipping %s/%s: unexpected ID", uuid, id);
+ 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, priv->imsi)) {
- _LOGD ("skipping %s/%s: ID doesn't contain IMSI", 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;
}
- _LOGD ("%s/%s compatible with IMSI %s", uuid, id, priv->imsi);
return TRUE;
}
@@ -1326,7 +1321,7 @@ nm_modem_ofono_class_init (NMModemOfonoClass *klass)
modem_class->disconnect = disconnect;
modem_class->disconnect_finish = disconnect_finish;
modem_class->deactivate_cleanup = deactivate_cleanup;
- modem_class->check_connection_compatible = check_connection_compatible;
+ modem_class->check_connection_compatible_with_modem = check_connection_compatible_with_modem;
modem_class->act_stage1_prepare = act_stage1_prepare;
modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start;
diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c
index 62e95cc795..59b081e980 100644
--- a/src/devices/wwan/nm-modem.c
+++ b/src/devices/wwan/nm-modem.c
@@ -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)
- return NM_MODEM_GET_CLASS (self)->check_connection_compatible (self, connection);
- return FALSE;
+ return NM_MODEM_GET_CLASS (self)->check_connection_compatible_with_modem (self, connection, error);
}
/*****************************************************************************/
diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h
index 1f05d07dae..c73745cef3 100644
--- a/src/devices/wwan/nm-modem.h
+++ b/src/devices/wwan/nm-modem.h
@@ -121,8 +121,9 @@ typedef struct {
const char **user,
const char **pass);
- gboolean (*check_connection_compatible) (NMModem *modem,
- NMConnection *connection);
+ gboolean (*check_connection_compatible_with_modem) (NMModem *modem,
+ 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,
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 37d789a0ad..630180963a 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -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;
@@ -3236,7 +3236,8 @@ static NMDevice *
nm_manager_get_best_device_for_connection (NMManager *self,
NMConnection *connection,
gboolean for_user_request,
- GHashTable *unavailable_devices)
+ GHashTable *unavailable_devices,
+ GError **error)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
NMActiveConnectionState ac_state;
@@ -3245,6 +3246,7 @@ nm_manager_get_best_device_for_connection (NMManager *self,
NMDevice *device;
NMDeviceCheckConAvailableFlags flags;
gs_unref_ptrarray GPtrArray *all_ac_arr = NULL;
+ gs_free_error GError *local_best = NULL;
flags = for_user_request ? NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST : NM_DEVICE_CHECK_CON_AVAILABLE_NONE;
@@ -3254,7 +3256,7 @@ nm_manager_get_best_device_for_connection (NMManager *self,
ac_device = nm_active_connection_get_device (ac);
if ( ac_device
&& ( (unavailable_devices && g_hash_table_contains (unavailable_devices, ac_device))
- || !nm_device_check_connection_available (ac_device, connection, flags, NULL)))
+ || !nm_device_check_connection_available (ac_device, connection, flags, NULL, NULL)))
ac_device = NULL;
if (all_ac_arr) {
@@ -3271,7 +3273,7 @@ nm_manager_get_best_device_for_connection (NMManager *self,
if ( !ac_device2
|| (unavailable_devices && g_hash_table_contains (unavailable_devices, ac_device2))
- || !nm_device_check_connection_available (ac_device2, connection, flags, NULL))
+ || !nm_device_check_connection_available (ac_device2, connection, flags, NULL, NULL))
continue;
ac_state2 = nm_active_connection_get_state (ac2);
@@ -3319,15 +3321,53 @@ found_better:
/* Pick the first device that's compatible with the connection. */
c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) {
+ GError *local = NULL;
- if (unavailable_devices && g_hash_table_contains (unavailable_devices, device))
+ if ( unavailable_devices
+ && g_hash_table_contains (unavailable_devices, device))
continue;
- if (nm_device_check_connection_available (device, connection, flags, NULL))
+ if (nm_device_check_connection_available (device,
+ connection,
+ flags,
+ NULL,
+ error ? &local : NULL))
return device;
+
+ if (error) {
+ gboolean reset_error;
+
+ if (!local_best)
+ reset_error = TRUE;
+ else if (local_best->domain != NM_UTILS_ERROR)
+ reset_error = (local->domain == NM_UTILS_ERROR);
+ else {
+ reset_error = ( local->domain == NM_UTILS_ERROR
+ && local_best->code < local->code);
+ }
+
+ if (reset_error) {
+ g_clear_error (&local_best);
+ g_set_error (&local_best,
+ local->domain,
+ local->code,
+ "device %s not available because %s",
+ nm_device_get_iface (device),
+ local->message);
+ }
+ g_error_free (local);
+ }
}
- /* No luck. :( */
+ if (error) {
+ if (local_best)
+ g_propagate_error (error, g_steal_pointer (&local_best));
+ else {
+ nm_utils_error_set_literal (error,
+ NM_UTILS_ERROR_UNKNOWN,
+ "no suitable device found");
+ }
+ }
return NULL;
}
@@ -3650,7 +3690,11 @@ ensure_master_active_connection (NMManager *self,
if (!is_compatible_with_slave (NM_CONNECTION (candidate), connection))
continue;
- if (nm_device_check_connection_available (master_device, NM_CONNECTION (candidate), NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL)) {
+ if (nm_device_check_connection_available (master_device,
+ NM_CONNECTION (candidate),
+ NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST,
+ NULL,
+ NULL)) {
master_ac = nm_manager_activate_connection (self,
candidate,
NULL,
@@ -3686,7 +3730,11 @@ ensure_master_active_connection (NMManager *self,
continue;
}
- if (!nm_device_check_connection_available (candidate, NM_CONNECTION (master_connection), NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL))
+ if (!nm_device_check_connection_available (candidate,
+ NM_CONNECTION (master_connection),
+ NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST,
+ NULL,
+ NULL))
continue;
if (!nm_device_is_software (candidate)) {
@@ -3774,7 +3822,8 @@ find_slaves (NMManager *manager,
slave_device = nm_manager_get_best_device_for_connection (manager,
candidate,
FALSE,
- devices);
+ devices,
+ NULL);
if (!slaves) {
/* what we allocate is quite likely much too large. Don't bother, it is only
@@ -4038,6 +4087,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
NMConnection *existing_connection = NULL;
NMActiveConnection *master_ac = NULL;
NMAuthSubject *subject;
+ GError *local = NULL;
g_return_val_if_fail (NM_IS_MANAGER (self), FALSE);
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (active), FALSE);
@@ -4071,10 +4121,13 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
}
/* Final connection must be available on device */
- if (!nm_device_check_connection_available (device, applied, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL)) {
+ if (!nm_device_check_connection_available (device, applied, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL, &local)) {
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
- "Connection '%s' is not available on the device %s at this time.",
- nm_settings_connection_get_id (connection), nm_device_get_iface (device));
+ "Connection '%s' is not available on device %s because %s",
+ nm_settings_connection_get_id (connection),
+ nm_device_get_iface (device),
+ local->message);
+ g_error_free (local);
return FALSE;
}
@@ -4581,17 +4634,20 @@ validate_activation_request (NMManager *self,
return NULL;
}
} else if (!is_vpn) {
- device = nm_manager_get_best_device_for_connection (self, connection, TRUE, NULL);
+ gs_free_error GError *local = NULL;
+
+ device = nm_manager_get_best_device_for_connection (self, connection, TRUE, NULL, &local);
if (!device) {
gs_free char *iface = NULL;
/* VPN and software-device connections don't need a device yet,
* but non-virtual connections do ... */
if (!nm_connection_is_virtual (connection)) {
- g_set_error_literal (error,
- NM_MANAGER_ERROR,
- NM_MANAGER_ERROR_UNKNOWN_DEVICE,
- "No suitable device found for this connection.");
+ g_set_error (error,
+ NM_MANAGER_ERROR,
+ NM_MANAGER_ERROR_UNKNOWN_DEVICE,
+ "No suitable device found for this connection (%s).",
+ local->message);
return NULL;
}
diff --git a/src/nm-policy.c b/src/nm-policy.c
index 07f0092a7b..4e9af023af 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -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) {
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index 5bb629dca2..a4d47f5346 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -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));