device: merge branch 'th/not-available-reason'

https://github.com/NetworkManager/NetworkManager/pull/163
This commit is contained in:
Thomas Haller 2018-07-24 09:44:18 +02:00
commit a6f51fffa1
41 changed files with 1133 additions and 760 deletions

View file

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

View file

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

View file

@ -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 ();
}

View file

@ -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, \

View file

@ -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,

View file

@ -87,25 +87,23 @@ get_generic_capabilities (NMDevice *dev)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingAdsl *s_adsl;
const char *protocol;
if (!NM_DEVICE_CLASS (nm_device_adsl_parent_class)->check_connection_compatible (device, connection))
return FALSE;
if (!nm_connection_is_type (connection, NM_SETTING_ADSL_SETTING_NAME))
if (!NM_DEVICE_CLASS (nm_device_adsl_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_adsl = nm_connection_get_setting_adsl (connection);
if (!s_adsl)
return FALSE;
/* FIXME: we don't yet support IPoATM */
protocol = nm_setting_adsl_get_protocol (s_adsl);
if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM) == 0)
if (nm_streq0 (protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM)) {
/* FIXME: we don't yet support IPoATM */
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"IPoATM protocol is not yet supported");
return FALSE;
}
return TRUE;
}
@ -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;
parent_class->check_connection_compatible = check_connection_compatible;
parent_class->complete_connection = complete_connection;
device_class->get_generic_capabilities = get_generic_capabilities;
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->check_connection_compatible = check_connection_compatible;
device_class->complete_connection = complete_connection;
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, "", "",

View file

@ -157,36 +157,36 @@ can_auto_connect (NMDevice *device,
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device);
NMSettingConnection *s_con;
NMSettingBluetooth *s_bt;
const char *bdaddr;
guint32 bt_type;
if (!NM_DEVICE_CLASS (nm_device_bt_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_BLUETOOTH_SETTING_NAME))
return FALSE;
s_bt = nm_connection_get_setting_bluetooth (connection);
if (!s_bt)
if (!NM_DEVICE_CLASS (nm_device_bt_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
bt_type = get_connection_bt_type (connection);
if (!(bt_type & priv->capabilities))
if (!NM_FLAGS_ALL (priv->capabilities, bt_type)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"device does not support bluetooth type of profile");
return FALSE;
}
s_bt = nm_connection_get_setting_bluetooth (connection);
bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt);
if (!bdaddr)
if (!bdaddr) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"profile lacks bdaddr setting");
return FALSE;
if (!nm_utils_hwaddr_matches (priv->bdaddr, -1, bdaddr, -1))
}
if (!nm_utils_hwaddr_matches (priv->bdaddr, -1, bdaddr, -1)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"devices bdaddr setting mismatches");
return FALSE;
}
return TRUE;
}
@ -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;

View file

@ -174,21 +174,6 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
return NM_DEVICE_CLASS (nm_device_6lowpan_parent_class)->is_available (device, flags);
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSetting6Lowpan *s_6lowpan;
if (!NM_DEVICE_CLASS (nm_device_6lowpan_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_6lowpan = nm_connection_get_setting_6lowpan (connection);
if (!s_6lowpan)
return FALSE;
return TRUE;
}
static gboolean
complete_connection (NMDevice *device,
NMConnection *connection,
@ -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;

View file

@ -55,23 +55,6 @@ get_generic_capabilities (NMDevice *dev)
return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingBond *s_bond;
if (!NM_DEVICE_CLASS (nm_device_bond_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_bond = nm_connection_get_setting_bond (connection);
if (!s_bond || !nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME))
return FALSE;
/* FIXME: match bond properties like mode, etc? */
return TRUE;
}
static gboolean
complete_connection (NMDevice *device,
NMConnection *connection,
@ -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;
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);
parent_class->update_connection = update_connection;
parent_class->master_update_slave_connection = master_update_slave_connection;
device_class->is_master = TRUE;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->complete_connection = complete_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->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;
}
/*****************************************************************************/

View file

@ -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;
device_class->connection_type_supported = NM_SETTING_BRIDGE_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_BRIDGE);
parent_class->update_connection = update_connection;
parent_class->master_update_slave_connection = master_update_slave_connection;
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;
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->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;
}
/*****************************************************************************/

View file

@ -117,21 +117,6 @@ create_and_realize (NMDevice *device,
return TRUE;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingDummy *s_dummy;
if (!NM_DEVICE_CLASS (nm_device_dummy_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_dummy = nm_connection_get_setting_dummy (connection);
if (!s_dummy)
return FALSE;
return TRUE;
}
static NMActStageReturn
act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
{
@ -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;

View file

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

View file

@ -86,19 +86,19 @@ realize_start_notify (NMDevice *device, const NMPlatformLink *plink)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingConnection *s_con;
if (!NM_DEVICE_CLASS (nm_device_generic_parent_class)->check_connection_compatible (device, connection))
return FALSE;
if (!nm_connection_is_type (connection, NM_SETTING_GENERIC_SETTING_NAME))
if (!NM_DEVICE_CLASS (nm_device_generic_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_con = nm_connection_get_setting_connection (connection);
if (!nm_setting_connection_get_interface_name (s_con))
if (!nm_setting_connection_get_interface_name (s_con)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"generic profiles need an interface name");
return FALSE;
}
return TRUE;
}
@ -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, "", "",

View file

@ -123,30 +123,28 @@ get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingInfiniband *s_infiniband;
if (!NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->check_connection_compatible (device, connection))
return FALSE;
if (!nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME))
return FALSE;
s_infiniband = nm_connection_get_setting_infiniband (connection);
if (!s_infiniband)
if (!NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
if (nm_device_is_real (device)) {
const char *mac;
const char *hw_addr;
s_infiniband = nm_connection_get_setting_infiniband (connection);
mac = nm_setting_infiniband_get_mac_address (s_infiniband);
if (mac) {
hw_addr = nm_device_get_permanent_hw_address (device);
if ( !hw_addr
|| !nm_utils_hwaddr_matches (mac, -1, hw_addr, -1))
|| !nm_utils_hwaddr_matches (mac, -1, hw_addr, -1)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"MAC address mismatches");
return FALSE;
}
}
}
@ -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);
parent_class->act_stage1_prepare = act_stage1_prepare;
parent_class->get_configured_mtu = get_configured_mtu;
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;
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, "", "",

View file

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

View file

@ -627,21 +627,6 @@ deactivate (NMDevice *device)
supplicant_interface_release (self);
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingMacsec *s_macsec;
if (!NM_DEVICE_CLASS (nm_device_macsec_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_macsec = nm_connection_get_setting_macsec (connection);
if (!s_macsec)
return FALSE;
return TRUE;
}
/******************************************************************/
static NMDeviceCapabilities
@ -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;
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);
parent_class->connection_type = NM_SETTING_MACSEC_SETTING_NAME;
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, "", "",

View file

@ -290,40 +290,58 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
/*****************************************************************************/
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE ((NMDeviceMacvlan *) device);
NMSettingMacvlan *s_macvlan;
const char *parent = NULL;
if (!NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->check_connection_compatible (device, connection))
if (!NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_macvlan = nm_connection_get_setting_macvlan (connection);
if (!s_macvlan)
return FALSE;
if (nm_setting_macvlan_get_tap (s_macvlan) != priv->props.tap)
if (nm_setting_macvlan_get_tap (s_macvlan) != priv->props.tap) {
if (priv->props.tap) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"macvtap device does not match macvlan profile");
} else {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"macvlan device does not match macvtap profile");
}
return FALSE;
}
/* Before the device is realized some properties will not be set */
if (nm_device_is_real (device)) {
if (setting_mode_to_platform (nm_setting_macvlan_get_mode (s_macvlan)) != priv->props.mode)
if (setting_mode_to_platform (nm_setting_macvlan_get_mode (s_macvlan)) != priv->props.mode) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"macvlan mode setting differs");
return FALSE;
}
if (nm_setting_macvlan_get_promiscuous (s_macvlan) == priv->props.no_promisc)
if (nm_setting_macvlan_get_promiscuous (s_macvlan) == priv->props.no_promisc) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"macvlan promiscuous setting differs");
return FALSE;
}
/* Check parent interface; could be an interface name or a UUID */
parent = nm_setting_macvlan_get_parent (s_macvlan);
if (parent) {
if (!nm_device_match_parent (device, parent))
if (!nm_device_match_parent (device, parent)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"macvlan parent setting differs");
return FALSE;
}
} else {
/* Parent could be a MAC address in an NMSettingWired */
if (!nm_device_match_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;

View file

@ -49,24 +49,6 @@ G_DEFINE_TYPE (NMDevicePpp, nm_device_ppp, NM_TYPE_DEVICE)
#define NM_DEVICE_PPP_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDevicePpp, NM_IS_DEVICE_PPP)
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingPppoe *s_pppoe;
if (!NM_DEVICE_CLASS (nm_device_ppp_parent_class)->check_connection_compatible (device, connection))
return FALSE;
if (!nm_streq0 (nm_connection_get_connection_type (connection),
NM_SETTING_PPPOE_SETTING_NAME))
return FALSE;
s_pppoe = nm_connection_get_setting_pppoe (connection);
nm_assert (s_pppoe);
return !!nm_setting_pppoe_get_parent (s_pppoe);
}
static NMDeviceCapabilities
get_generic_capabilities (NMDevice *device)
{
@ -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;
}
/*****************************************************************************/

View file

@ -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 */

View file

@ -289,18 +289,14 @@ _same_og (const char *str, gboolean og_valid, guint32 og_num)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceTun *self = NM_DEVICE_TUN (device);
NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self);
NMSettingTunMode mode;
NMSettingTun *s_tun;
if (!NM_DEVICE_CLASS (nm_device_tun_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_tun = nm_connection_get_setting_tun (connection);
if (!s_tun)
if (!NM_DEVICE_CLASS (nm_device_tun_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
if (nm_device_is_real (device)) {
@ -308,22 +304,43 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
case IFF_TUN: mode = NM_SETTING_TUN_MODE_TUN; break;
case IFF_TAP: mode = NM_SETTING_TUN_MODE_TAP; break;
default:
/* Huh? */
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"invalid tun type on device");
return FALSE;
}
if (mode != nm_setting_tun_get_mode (s_tun))
s_tun = nm_connection_get_setting_tun (connection);
if (mode != nm_setting_tun_get_mode (s_tun)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"tun mode setting mismatches");
return FALSE;
if (!_same_og (nm_setting_tun_get_owner (s_tun), priv->props.owner_valid, priv->props.owner))
}
if (!_same_og (nm_setting_tun_get_owner (s_tun), priv->props.owner_valid, priv->props.owner)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"tun owner setting mismatches");
return FALSE;
if (!_same_og (nm_setting_tun_get_group (s_tun), priv->props.group_valid, priv->props.group))
}
if (!_same_og (nm_setting_tun_get_group (s_tun), priv->props.group_valid, priv->props.group)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"tun group setting mismatches");
return FALSE;
if (nm_setting_tun_get_pi (s_tun) != priv->props.pi)
}
if (nm_setting_tun_get_pi (s_tun) != priv->props.pi) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"tun pi setting mismatches");
return FALSE;
if (nm_setting_tun_get_vnet_hdr (s_tun) != priv->props.vnet_hdr)
}
if (nm_setting_tun_get_vnet_hdr (s_tun) != priv->props.vnet_hdr) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"tun vnet-hdr setting mismatches");
return FALSE;
if (nm_setting_tun_get_multi_queue (s_tun) != priv->props.multi_queue)
}
if (nm_setting_tun_get_multi_queue (s_tun) != priv->props.multi_queue) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"tun multi-queue setting mismatches");
return FALSE;
}
}
return TRUE;
@ -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;

View file

@ -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;

View file

@ -331,33 +331,39 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
/*****************************************************************************/
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE ((NMDeviceVlan *) device);
NMSettingVlan *s_vlan;
const char *parent = NULL;
const char *parent;
if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_compatible (device, connection))
if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_vlan = nm_connection_get_setting_vlan (connection);
if (!s_vlan)
return FALSE;
/* Before the device is realized some properties will not be set */
if (nm_device_is_real (device)) {
if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id)
s_vlan = nm_connection_get_setting_vlan (connection);
if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vlan id setting mismatches");
return FALSE;
}
/* Check parent interface; could be an interface name or a UUID */
parent = nm_setting_vlan_get_parent (s_vlan);
if (parent) {
if (!nm_device_match_parent (device, parent))
if (!nm_device_match_parent (device, parent)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"vlan parent setting differs");
return FALSE;
}
} else {
/* Parent could be a MAC address in an NMSettingWired */
if (!nm_device_match_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;
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);
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->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, "", "",

View file

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

View file

@ -91,23 +91,24 @@ update_connection (NMDevice *device, NMConnection *connection)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingWpan *s_wpan;
const char *mac, *hw_addr;
if (!NM_DEVICE_CLASS (nm_device_wpan_parent_class)->check_connection_compatible (device, connection))
if (!NM_DEVICE_CLASS (nm_device_wpan_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_wpan = nm_connection_get_setting_wpan (connection);
if (!s_wpan)
return FALSE;
mac = nm_setting_wpan_get_mac_address (s_wpan);
if (mac) {
hw_addr = nm_device_get_hw_address (device);
if (!nm_utils_hwaddr_matches (mac, -1, hw_addr, -1))
if (!nm_utils_hwaddr_matches (mac, -1, hw_addr, -1)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"MAC address mismatches");
return FALSE;
}
}
return TRUE;
@ -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;

View file

@ -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

View file

@ -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);

View file

@ -76,21 +76,6 @@ get_generic_capabilities (NMDevice *device)
return NM_DEVICE_CAP_IS_SOFTWARE;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
const char *connection_type;
if (!NM_DEVICE_CLASS (nm_device_ovs_bridge_parent_class)->check_connection_compatible (device, connection))
return FALSE;
connection_type = nm_connection_get_connection_type (connection);
if (!nm_streq0 (connection_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME))
return FALSE;
return TRUE;
}
static NMActStageReturn
act_stage3_ip4_config_start (NMDevice *device,
NMIP4Config **out_config,
@ -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;

View file

@ -85,25 +85,20 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingConnection *s_con;
NMSettingOvsInterface *s_ovs_iface;
if (!NM_DEVICE_CLASS (nm_device_ovs_interface_parent_class)->check_connection_compatible (device, connection))
if (!NM_DEVICE_CLASS (nm_device_ovs_interface_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_ovs_iface = nm_connection_get_setting_ovs_interface (connection);
if (!s_ovs_iface)
return FALSE;
if (!NM_IN_STRSET (nm_setting_ovs_interface_get_interface_type (s_ovs_iface),
"internal", "patch")) {
return FALSE;
}
s_con = nm_connection_get_setting_connection (connection);
if (g_strcmp0 (nm_setting_connection_get_connection_type (s_con),
NM_SETTING_OVS_INTERFACE_SETTING_NAME) != 0) {
if (!NM_IN_STRSET (nm_setting_ovs_interface_get_interface_type (s_ovs_iface),
"internal",
"patch")) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"unsupported OVS interface type in profile");
return FALSE;
}
@ -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;

View file

@ -70,26 +70,6 @@ get_generic_capabilities (NMDevice *device)
return NM_DEVICE_CAP_IS_SOFTWARE;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingConnection *s_con;
const char *connection_type;
if (!NM_DEVICE_CLASS (nm_device_ovs_port_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_con = nm_connection_get_setting_connection (connection);
connection_type = nm_setting_connection_get_connection_type (s_con);
if (!connection_type)
return FALSE;
if (strcmp (connection_type, NM_SETTING_OVS_PORT_SETTING_NAME) == 0)
return TRUE;
return FALSE;
}
static NMActStageReturn
act_stage3_ip4_config_start (NMDevice *device,
NMIP4Config **out_config,
@ -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;

View file

@ -84,23 +84,6 @@ get_generic_capabilities (NMDevice *device)
return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingTeam *s_team;
if (!NM_DEVICE_CLASS (nm_device_team_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_team = nm_connection_get_setting_team (connection);
if (!s_team || !nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME))
return FALSE;
/* FIXME: match team properties like mode, etc? */
return TRUE;
}
static gboolean
complete_connection (NMDevice *device,
NMConnection *connection,
@ -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;
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);
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->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, "", "",

View file

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

View file

@ -79,28 +79,6 @@ G_DEFINE_TYPE (NMDeviceOlpcMesh, nm_device_olpc_mesh, NM_TYPE_DEVICE)
/*****************************************************************************/
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingConnection *s_con;
NMSettingOlpcMesh *s_mesh;
if (!NM_DEVICE_CLASS (nm_device_olpc_mesh_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_OLPC_MESH_SETTING_NAME))
return FALSE;
s_mesh = nm_connection_get_setting_olpc_mesh (connection);
if (!s_mesh)
return FALSE;
return TRUE;
}
static gboolean
get_autoconnect_allowed (NMDevice *device)
{
@ -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, "", "",

View file

@ -604,11 +604,10 @@ is_adhoc_wpa (NMConnection *connection)
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (device);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
NMSettingConnection *s_con;
NMSettingWireless *s_wireless;
const char *mac;
const char * const *mac_blacklist;
@ -616,18 +615,10 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
const char *mode;
const char *perm_hw_addr;
if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_WIRELESS_SETTING_NAME))
if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->check_connection_compatible (device, connection, error))
return FALSE;
s_wireless = nm_connection_get_setting_wireless (connection);
if (!s_wireless)
return FALSE;
perm_hw_addr = nm_device_get_permanent_hw_address (device);
mac = nm_setting_wireless_get_mac_address (s_wireless);
@ -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;
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);
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;
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;
parent_class->state_changed = device_state_changed;
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;

View file

@ -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;

View file

@ -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;

View file

@ -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);
id = nm_connection_get_id (connection);
if (!strstr (id, "/context")) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"the connection ID has no context");
return FALSE;
}
if (!g_strrstr (id, "/context")) {
_LOGD ("skipping %s/%s: unexpected ID", uuid, id);
if (!strstr (id, priv->imsi)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"the connection ID does not contain the IMSI");
return FALSE;
}
if (!g_strrstr (id, priv->imsi)) {
_LOGD ("skipping %s/%s: ID doesn't contain IMSI", uuid, id);
return FALSE;
}
_LOGD ("%s/%s compatible with IMSI %s", uuid, id, priv->imsi);
return TRUE;
}
@ -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;

View file

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

View file

@ -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,

View file

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

View file

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

View file

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