Commit 570e1fa7 authored by Thomas Haller's avatar Thomas Haller

core: give better error reason why device is unavailable

The error reason is still unused.
parent 246b7475
......@@ -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;
}
......
......@@ -61,18 +61,34 @@ 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;
......
......@@ -368,12 +368,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
......
......@@ -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))
......@@ -11339,7 +11339,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.
......@@ -11350,7 +11350,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.
......@@ -13211,38 +13213,71 @@ 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;
/* 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)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
"profile is not compatible with software device");
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)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
"profile is not compatible with device");
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);
}
/**
......@@ -13255,6 +13290,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.
*
......@@ -13264,11 +13300,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
{
......@@ -13278,7 +13315,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) {
......@@ -13320,7 +13357,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);
......@@ -13346,6 +13384,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;
}
......@@ -13378,6 +13418,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;
......@@ -13432,7 +13473,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);
......@@ -13462,6 +13504,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
......
......@@ -317,7 +317,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,
......@@ -742,7 +743,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);
......
......@@ -554,7 +554,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 +567,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 +598,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
......
......@@ -678,7 +678,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 +696,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 +725,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
......
......@@ -409,22 +409,38 @@ 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;
......
......@@ -3254,7 +3254,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 +3271,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);
......@@ -3323,7 +3323,7 @@ found_better:
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, NULL))
return device;
}
......@@ -3650,7 +3650,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 +3690,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)) {
......@@ -4071,7 +4079,7 @@ _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, NULL)) {
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));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment