device/wifi: merge branch 'th/device-wifi-wait-for-scan-bgo770938'

https://bugzilla.gnome.org/show_bug.cgi?id=770938
https://bugzilla.gnome.org/show_bug.cgi?id=777831

(cherry picked from commit fe6204ffc7)
This commit is contained in:
Thomas Haller 2017-02-17 19:25:24 +01:00
commit 1dbb6b3150
12 changed files with 771 additions and 677 deletions

View file

@ -483,8 +483,8 @@ modem_prepare_result (NMModem *modem,
* the device to be auto-activated anymore, which would risk locking
* the SIM if the incorrect PIN continues to be used.
*/
nm_device_set_autoconnect (device, FALSE);
_LOGI (LOGD_MB, "disabling autoconnect due to failed SIM PIN");
nm_device_set_autoconnect_intern (device, FALSE);
}
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);

View file

@ -71,7 +71,6 @@ typedef struct Supplicant {
NMSupplicantInterface *iface;
/* signal handler ids */
gulong iface_error_id;
gulong iface_state_id;
/* Timeouts and idles */
@ -423,22 +422,12 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
/* 802.1X */
static void
supplicant_interface_clear_handlers (NMDeviceEthernet *self)
supplicant_interface_release (NMDeviceEthernet *self)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
nm_clear_g_source (&priv->supplicant_timeout_id);
nm_clear_g_source (&priv->supplicant.con_timeout_id);
nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_error_id);
}
static void
supplicant_interface_release (NMDeviceEthernet *self)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
supplicant_interface_clear_handlers (self);
nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_state_id);
if (priv->supplicant.iface) {
@ -594,10 +583,25 @@ build_supplicant_config (NMDeviceEthernet *self,
return config;
}
static void
supplicant_iface_assoc_cb (NMSupplicantInterface *iface,
GError *error,
gpointer user_data)
{
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
if (error && !nm_utils_error_is_cancelled (error, TRUE)) {
supplicant_interface_release (self);
nm_device_queue_state (NM_DEVICE (self),
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
}
}
static void
supplicant_iface_state_cb (NMSupplicantInterface *iface,
guint32 new_state,
guint32 old_state,
int new_state_i,
int old_state_i,
int disconnect_reason,
gpointer user_data)
{
@ -605,9 +609,10 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
NMDevice *device = NM_DEVICE (self);
NMSupplicantConfig *config;
gboolean success = FALSE;
NMDeviceState devstate;
GError *error = NULL;
NMSupplicantInterfaceState new_state = new_state_i;
NMSupplicantInterfaceState old_state = old_state_i;
if (new_state == old_state)
return;
@ -622,30 +627,23 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
case NM_SUPPLICANT_INTERFACE_STATE_READY:
config = build_supplicant_config (self, &error);
if (config) {
success = nm_supplicant_interface_set_config (priv->supplicant.iface, config, &error);
nm_supplicant_interface_assoc (priv->supplicant.iface, config,
supplicant_iface_assoc_cb, self);
g_object_unref (config);
if (!success) {
_LOGE (LOGD_DEVICE | LOGD_ETHER,
"Activation: (ethernet) couldn't send security configuration to the supplicant: %s",
error->message);
g_clear_error (&error);
}
} else {
_LOGE (LOGD_DEVICE | LOGD_ETHER,
"Activation: (ethernet) couldn't build security configuration: %s",
error->message);
g_clear_error (&error);
}
if (!success) {
nm_device_state_changed (device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
}
break;
case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED:
supplicant_interface_clear_handlers (self);
nm_clear_g_source (&priv->supplicant_timeout_id);
nm_clear_g_source (&priv->supplicant.con_timeout_id);
/* If this is the initial association during device activation,
* schedule the next activation stage.
@ -677,24 +675,6 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
}
}
static void
supplicant_iface_connection_error_cb (NMSupplicantInterface *iface,
const char *name,
const char *message,
gpointer user_data)
{
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
_LOGW (LOGD_DEVICE | LOGD_ETHER,
"Activation: (ethernet) association request to the supplicant failed: %s - %s",
name, message);
supplicant_interface_release (self);
nm_device_queue_state (NM_DEVICE (self),
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
}
static NMActStageReturn
handle_auth_or_fail (NMDeviceEthernet *self,
NMActRequest *req,
@ -790,12 +770,6 @@ supplicant_interface_init (NMDeviceEthernet *self)
G_CALLBACK (supplicant_iface_state_cb),
self);
/* Hook up error signal handler to capture association errors */
priv->supplicant.iface_error_id = g_signal_connect (priv->supplicant.iface,
NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR,
G_CALLBACK (supplicant_iface_connection_error_cb),
self);
/* Set up a timeout on the connection attempt to fail it after 25 seconds */
priv->supplicant.con_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self);

View file

@ -45,7 +45,6 @@ typedef struct Supplicant {
NMSupplicantInterface *iface;
/* signal handler ids */
gulong iface_error_id;
gulong iface_state_id;
/* Timeouts and idles */
@ -248,22 +247,12 @@ build_supplicant_config (NMDeviceMacsec *self, GError **error)
}
static void
supplicant_interface_clear_handlers (NMDeviceMacsec *self)
supplicant_interface_release (NMDeviceMacsec *self)
{
NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self);
nm_clear_g_source (&priv->supplicant_timeout_id);
nm_clear_g_source (&priv->supplicant.con_timeout_id);
nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_error_id);
}
static void
supplicant_interface_release (NMDeviceMacsec *self)
{
NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self);
supplicant_interface_clear_handlers (self);
nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_state_id);
if (priv->supplicant.iface) {
@ -273,21 +262,18 @@ supplicant_interface_release (NMDeviceMacsec *self)
}
static void
supplicant_iface_connection_error_cb (NMSupplicantInterface *iface,
const char *name,
const char *message,
gpointer user_data)
supplicant_iface_assoc_cb (NMSupplicantInterface *iface,
GError *error,
gpointer user_data)
{
NMDeviceMacsec *self = NM_DEVICE_MACSEC (user_data);
_LOGW (LOGD_DEVICE,
"Activation: association request to the supplicant failed: %s - %s",
name, message);
supplicant_interface_release (self);
nm_device_queue_state (NM_DEVICE (self),
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
if (error && !nm_utils_error_is_cancelled (error, TRUE)) {
supplicant_interface_release (self);
nm_device_queue_state (NM_DEVICE (self),
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
}
}
static void
@ -412,8 +398,8 @@ time_out:
static void
supplicant_iface_state_cb (NMSupplicantInterface *iface,
guint32 new_state,
guint32 old_state,
int new_state_i,
int old_state_i,
int disconnect_reason,
gpointer user_data)
{
@ -421,9 +407,10 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self);
NMDevice *device = NM_DEVICE (self);
NMSupplicantConfig *config;
gboolean success = FALSE;
NMDeviceState devstate;
GError *error = NULL;
NMSupplicantInterfaceState new_state = new_state_i;
NMSupplicantInterfaceState old_state = old_state_i;
if (new_state == old_state)
return;
@ -438,30 +425,23 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
case NM_SUPPLICANT_INTERFACE_STATE_READY:
config = build_supplicant_config (self, &error);
if (config) {
success = nm_supplicant_interface_set_config (priv->supplicant.iface, config, &error);
nm_supplicant_interface_assoc (priv->supplicant.iface, config,
supplicant_iface_assoc_cb, self);
g_object_unref (config);
if (!success) {
_LOGE (LOGD_DEVICE,
"Activation: couldn't send security configuration to the supplicant: %s",
error->message);
g_clear_error (&error);
}
} else {
_LOGE (LOGD_DEVICE,
"Activation: couldn't build security configuration: %s",
error->message);
g_clear_error (&error);
}
if (!success) {
nm_device_state_changed (device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
}
break;
case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED:
supplicant_interface_clear_handlers (self);
nm_clear_g_source (&priv->supplicant_timeout_id);
nm_clear_g_source (&priv->supplicant.con_timeout_id);
nm_device_bring_up (device, TRUE, NULL);
/* If this is the initial association during device activation,
@ -593,12 +573,6 @@ supplicant_interface_init (NMDeviceMacsec *self)
G_CALLBACK (supplicant_iface_state_cb),
self);
/* Hook up error signal handler to capture association errors */
priv->supplicant.iface_error_id = g_signal_connect (priv->supplicant.iface,
NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR,
G_CALLBACK (supplicant_iface_connection_error_cb),
self);
/* Set up a timeout on the connection attempt to fail it after 25 seconds */
priv->supplicant.con_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self);

View file

@ -416,7 +416,8 @@ typedef struct _NMDevicePrivate {
gboolean needs_ip6_subnet;
/* allow autoconnect feature */
bool autoconnect;
bool autoconnect_intern:1;
bool autoconnect_user:1;
/* master interface for bridge/bond/team slave */
NMDevice * master;
@ -482,6 +483,9 @@ static NMActStageReturn linklocal6_start (NMDevice *self);
static void _carrier_wait_check_queued_act_request (NMDevice *self);
static void nm_device_set_autoconnect_both (NMDevice *self, gboolean autoconnect);
static void nm_device_set_autoconnect_full (NMDevice *self, int autoconnect_intern, int autoconnect_user);
static const char *_activation_func_to_string (ActivationHandleFunc func);
static void activation_source_handle_cb (NMDevice *self, int family);
@ -2652,6 +2656,8 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink)
if (real_rate)
priv->stats.timeout_id = g_timeout_add (real_rate, _stats_timeout_cb, self);
nm_device_set_autoconnect_full (self, !!DEFAULT_AUTOCONNECT, TRUE);
klass->realize_start_notify (self, plink);
/* Do not manage externally created software devices until they are IFF_UP
@ -2846,7 +2852,7 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
priv->real = FALSE;
_notify (self, PROP_REAL);
nm_device_set_autoconnect (self, DEFAULT_AUTOCONNECT);
nm_device_set_autoconnect_both (self, FALSE);
g_object_thaw_notify (G_OBJECT (self));
@ -3398,25 +3404,50 @@ nm_device_set_enabled (NMDevice *self, gboolean enabled)
gboolean
nm_device_get_autoconnect (NMDevice *self)
{
NMDevicePrivate *priv;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
return NM_DEVICE_GET_PRIVATE (self)->autoconnect;
priv = NM_DEVICE_GET_PRIVATE (self);
return priv->autoconnect_intern && priv->autoconnect_user;
}
void
nm_device_set_autoconnect (NMDevice *self, gboolean autoconnect)
static void
nm_device_set_autoconnect_full (NMDevice *self, int autoconnect_intern, int autoconnect_user)
{
NMDevicePrivate *priv;
gboolean old_value;
g_return_if_fail (NM_IS_DEVICE (self));
autoconnect = !!autoconnect;
priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->autoconnect != autoconnect) {
priv->autoconnect = autoconnect;
old_value = nm_device_get_autoconnect (self);
if (autoconnect_intern != -1)
priv->autoconnect_intern = autoconnect_intern;
if (autoconnect_user != -1)
priv->autoconnect_user = autoconnect_user;
if (old_value != nm_device_get_autoconnect (self))
_notify (self, PROP_AUTOCONNECT);
}
}
void
nm_device_set_autoconnect_intern (NMDevice *self, gboolean autoconnect)
{
nm_device_set_autoconnect_full (self, !!autoconnect, -1);
}
static void
nm_device_set_autoconnect_both (NMDevice *self, gboolean autoconnect)
{
autoconnect = !!autoconnect;
nm_device_set_autoconnect_full (self, autoconnect, autoconnect);
}
static gboolean
get_autoconnect_allowed (NMDevice *self)
{
return TRUE;
}
static gboolean
@ -3441,10 +3472,12 @@ gboolean
nm_device_autoconnect_allowed (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self);
GValue instance = G_VALUE_INIT;
GValue retval = G_VALUE_INIT;
if (!priv->autoconnect)
if ( !nm_device_get_autoconnect (self)
|| !klass->get_autoconnect_allowed (self))
return FALSE;
/* Unrealized devices can always autoconnect. */
@ -8832,7 +8865,7 @@ disconnect_cb (NMDevice *self,
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, FALSE, subject, local->message);
g_dbus_method_invocation_take_error (context, local);
} else {
nm_device_set_autoconnect (self, FALSE);
nm_device_set_autoconnect_intern (self, FALSE);
nm_device_state_changed (self,
NM_DEVICE_STATE_DEACTIVATING,
@ -11996,7 +12029,7 @@ _set_state_full (NMDevice *self,
/* Reset autoconnect flag when the device is activating or connected. */
if ( state >= NM_DEVICE_STATE_PREPARE
&& state <= NM_DEVICE_STATE_ACTIVATED)
nm_device_set_autoconnect (self, TRUE);
nm_device_set_autoconnect_intern (self, TRUE);
_notify (self, PROP_STATE);
_notify (self, PROP_STATE_REASON);
@ -12950,7 +12983,6 @@ nm_device_init (NMDevice *self)
priv->state_reason = NM_DEVICE_STATE_REASON_NONE;
priv->dhcp_timeout = 0;
priv->rfkill_type = RFKILL_TYPE_UNKNOWN;
priv->autoconnect = DEFAULT_AUTOCONNECT;
priv->unmanaged_flags = NM_UNMANAGED_PLATFORM_INIT;
priv->unmanaged_mask = priv->unmanaged_flags;
priv->available_connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
@ -13222,7 +13254,7 @@ set_property (GObject *object, guint prop_id,
}
break;
case PROP_AUTOCONNECT:
nm_device_set_autoconnect (self, g_value_get_boolean (value));
nm_device_set_autoconnect_both (self, g_value_get_boolean (value));
break;
case PROP_FIRMWARE_MISSING:
/* construct-only */
@ -13348,7 +13380,7 @@ get_property (GObject *object, guint prop_id,
g_value_set_boolean (value, nm_device_get_state (self) > NM_DEVICE_STATE_UNMANAGED);
break;
case PROP_AUTOCONNECT:
g_value_set_boolean (value, priv->autoconnect);
g_value_set_boolean (value, nm_device_get_autoconnect (self));
break;
case PROP_FIRMWARE_MISSING:
g_value_set_boolean (value, priv->firmware_missing);
@ -13475,6 +13507,7 @@ nm_device_class_init (NMDeviceClass *klass)
klass->have_any_ready_slaves = have_any_ready_slaves;
klass->get_type_description = get_type_description;
klass->get_autoconnect_allowed = get_autoconnect_allowed;
klass->can_auto_connect = can_auto_connect;
klass->check_connection_compatible = check_connection_compatible;
klass->check_connection_available = check_connection_available;

View file

@ -243,6 +243,11 @@ typedef struct {
void (* set_enabled) (NMDevice *self, gboolean enabled);
/* allow derived classes to override the result of nm_device_autoconnect_allowed().
* If the value changes, the class should call nm_device_emit_recheck_auto_activate(),
* which emits NM_DEVICE_RECHECK_AUTO_ACTIVATE signal. */
gboolean (* get_autoconnect_allowed) (NMDevice *self);
gboolean (* can_auto_connect) (NMDevice *self,
NMConnection *connection,
char **specific_object);
@ -577,7 +582,7 @@ gboolean nm_device_unrealize (NMDevice *device,
GError **error);
gboolean nm_device_get_autoconnect (NMDevice *device);
void nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect);
void nm_device_set_autoconnect_intern (NMDevice *device, gboolean autoconnect);
void nm_device_emit_recheck_auto_activate (NMDevice *device);
void nm_device_state_changed (NMDevice *device,

View file

@ -152,16 +152,11 @@ static void cleanup_association_attempt (NMDeviceWifi * self,
gboolean disconnect);
static void supplicant_iface_state_cb (NMSupplicantInterface *iface,
guint32 new_state,
guint32 old_state,
int new_state_i,
int old_state_i,
int disconnect_reason,
gpointer user_data);
static void supplicant_iface_new_bss_cb (NMSupplicantInterface * iface,
const char *object_path,
GVariant *properties,
NMDeviceWifi * self);
static void supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface,
const char *object_path,
GVariant *properties,
@ -190,8 +185,6 @@ static void ap_add_remove (NMDeviceWifi *self,
NMWifiAP *ap,
gboolean recheck_available_connections);
static void remove_supplicant_interface_error_handler (NMDeviceWifi *self);
static void _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset);
/*****************************************************************************/
@ -262,10 +255,6 @@ supplicant_interface_acquire (NMDeviceWifi *self)
NM_SUPPLICANT_INTERFACE_STATE,
G_CALLBACK (supplicant_iface_state_cb),
self);
g_signal_connect (priv->sup_iface,
NM_SUPPLICANT_INTERFACE_NEW_BSS,
G_CALLBACK (supplicant_iface_new_bss_cb),
self);
g_signal_connect (priv->sup_iface,
NM_SUPPLICANT_INTERFACE_BSS_UPDATED,
G_CALLBACK (supplicant_iface_bss_updated_cb),
@ -306,8 +295,10 @@ _requested_scan_set (NMDeviceWifi *self, gboolean value)
priv->requested_scan = value;
if (value)
nm_device_add_pending_action ((NMDevice *) self, NM_PENDING_ACTION_WIFI_SCAN, TRUE);
else
else {
nm_device_emit_recheck_auto_activate (NM_DEVICE (self));
nm_device_remove_pending_action ((NMDevice *) self, NM_PENDING_ACTION_WIFI_SCAN, TRUE);
}
}
static void
@ -428,7 +419,7 @@ periodic_update (NMDeviceWifi *self)
guint32 new_rate;
int percent;
NMDeviceState state;
guint32 supplicant_state;
NMSupplicantInterfaceState supplicant_state;
/* BSSID and signal strength have meaningful values only if the device
* is activated and not scanning.
@ -455,7 +446,8 @@ periodic_update (NMDeviceWifi *self)
/* Smooth out the strength to work around crappy drivers */
percent = nm_platform_wifi_get_quality (NM_PLATFORM_GET, ifindex);
if (percent >= 0 || ++priv->invalid_strength_counter > 3) {
nm_wifi_ap_set_strength (priv->current_ap, (gint8) percent);
if (nm_wifi_ap_set_strength (priv->current_ap, (gint8) percent))
_ap_dump (self, priv->current_ap, "updated", 0);
priv->invalid_strength_counter = 0;
}
}
@ -488,7 +480,9 @@ ap_add_remove (NMDeviceWifi *self,
g_hash_table_insert (priv->aps,
(gpointer) nm_exported_object_export ((NMExportedObject *) ap),
g_object_ref (ap));
}
_ap_dump (self, ap, "added", 0);
} else
_ap_dump (self, ap, "removed", 0);
g_signal_emit (self, signals[signum], 0, ap);
@ -955,7 +949,7 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (device);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
guint32 state;
NMSupplicantInterfaceState supplicant_state;
if (!priv->enabled)
return FALSE;
@ -963,14 +957,26 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
if (!priv->sup_iface)
return FALSE;
state = nm_supplicant_interface_get_state (priv->sup_iface);
if ( state < NM_SUPPLICANT_INTERFACE_STATE_READY
|| state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED)
supplicant_state = nm_supplicant_interface_get_state (priv->sup_iface);
if ( supplicant_state < NM_SUPPLICANT_INTERFACE_STATE_READY
|| supplicant_state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED)
return FALSE;
return TRUE;
}
static gboolean
get_autoconnect_allowed (NMDevice *device)
{
NMDeviceWifiPrivate *priv;
if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->get_autoconnect_allowed (device))
return FALSE;
priv = NM_DEVICE_WIFI_GET_PRIVATE (NM_DEVICE_WIFI (device));
return !priv->requested_scan;
}
static gboolean
can_auto_connect (NMDevice *device,
NMConnection *connection,
@ -1242,7 +1248,7 @@ static gboolean
scanning_allowed (NMDeviceWifi *self)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
guint32 sup_state;
NMSupplicantInterfaceState supplicant_state;
NMConnection *connection;
g_return_val_if_fail (priv->sup_iface != NULL, FALSE);
@ -1274,11 +1280,11 @@ scanning_allowed (NMDeviceWifi *self)
}
/* Don't scan if the supplicant is busy */
sup_state = nm_supplicant_interface_get_state (priv->sup_iface);
if ( sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING
|| sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED
|| sup_state == NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE
|| sup_state == NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE
supplicant_state = nm_supplicant_interface_get_state (priv->sup_iface);
if ( supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING
|| supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED
|| supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE
|| supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE
|| nm_supplicant_interface_get_scanning (priv->sup_iface))
return FALSE;
@ -1424,9 +1430,7 @@ static void
request_wireless_scan (NMDeviceWifi *self, gboolean force_if_scanning, GVariant *scan_options)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
gboolean backoff = FALSE;
GPtrArray *ssids = NULL;
gboolean new_scan_requested = FALSE;
gboolean request_started = FALSE;
nm_clear_g_source (&priv->pending_scan_id);
@ -1436,6 +1440,8 @@ request_wireless_scan (NMDeviceWifi *self, gboolean force_if_scanning, GVariant
}
if (check_scanning_allowed (self)) {
gs_unref_ptrarray GPtrArray *ssids = NULL;
_LOGD (LOGD_WIFI, "wifi-scan: scanning requested");
if (scan_options) {
@ -1473,22 +1479,14 @@ request_wireless_scan (NMDeviceWifi *self, gboolean force_if_scanning, GVariant
_hw_addr_set_scanning (self, FALSE);
if (nm_supplicant_interface_request_scan (priv->sup_iface, ssids)) {
/* success */
backoff = TRUE;
_requested_scan_set (self, TRUE);
new_scan_requested = TRUE;
}
if (ssids)
g_ptr_array_unref (ssids);
nm_supplicant_interface_request_scan (priv->sup_iface, ssids);
request_started = TRUE;
} else
_LOGD (LOGD_WIFI, "wifi-scan: scanning requested but not allowed at this time");
if (!new_scan_requested)
_requested_scan_set (self, FALSE);
_requested_scan_set (self, request_started);
schedule_scan (self, backoff);
schedule_scan (self, request_started);
}
static gboolean
@ -1639,14 +1637,13 @@ try_fill_ssid_for_hidden_ap (NMDeviceWifi *self,
}
static void
supplicant_iface_new_bss_cb (NMSupplicantInterface *iface,
const char *object_path,
GVariant *properties,
NMDeviceWifi *self)
supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface,
const char *object_path,
GVariant *properties,
NMDeviceWifi *self)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
NMDeviceState state;
NMWifiAP *ap;
NMWifiAP *found_ap = NULL;
const GByteArray *ssid;
@ -1661,41 +1658,41 @@ supplicant_iface_new_bss_cb (NMSupplicantInterface *iface,
if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP)
return;
ap = nm_wifi_ap_new_from_properties (object_path, properties);
if (!ap) {
_LOGD (LOGD_WIFI, "invalid AP properties received for %s", object_path);
return;
}
/* Let the manager try to fill in the SSID from seen-bssids lists */
ssid = nm_wifi_ap_get_ssid (ap);
if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) {
/* Try to fill the SSID from the AP database */
try_fill_ssid_for_hidden_ap (self, ap);
ssid = nm_wifi_ap_get_ssid (ap);
if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) {
/* Yay, matched it, no longer treat as hidden */
_LOGD (LOGD_WIFI, "matched hidden AP %s => '%s'",
nm_wifi_ap_get_address (ap), nm_utils_escape_ssid (ssid->data, ssid->len));
} else {
/* Didn't have an entry for this AP in the database */
_LOGD (LOGD_WIFI, "failed to match hidden AP %s",
nm_wifi_ap_get_address (ap));
}
}
found_ap = get_ap_by_supplicant_path (self, object_path);
if (found_ap) {
_ap_dump (self, ap, "updated", 0);
nm_wifi_ap_update_from_properties (found_ap, object_path, properties);
if (!nm_wifi_ap_update_from_properties (found_ap, object_path, properties))
return;
_ap_dump (self, found_ap, "updated", 0);
} else {
_ap_dump (self, ap, "added", 0);
gs_unref_object NMWifiAP *ap = NULL;
ap = nm_wifi_ap_new_from_properties (object_path, properties);
if (!ap) {
_LOGD (LOGD_WIFI, "invalid AP properties received for %s", object_path);
return;
}
/* Let the manager try to fill in the SSID from seen-bssids lists */
ssid = nm_wifi_ap_get_ssid (ap);
if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) {
/* Try to fill the SSID from the AP database */
try_fill_ssid_for_hidden_ap (self, ap);
ssid = nm_wifi_ap_get_ssid (ap);
if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) {
/* Yay, matched it, no longer treat as hidden */
_LOGD (LOGD_WIFI, "matched hidden AP %s => '%s'",
nm_wifi_ap_get_address (ap), nm_utils_escape_ssid (ssid->data, ssid->len));
} else {
/* Didn't have an entry for this AP in the database */
_LOGD (LOGD_WIFI, "failed to match hidden AP %s",
nm_wifi_ap_get_address (ap));
}
}
ap_add_remove (self, ACCESS_POINT_ADDED, ap, TRUE);
}
g_object_unref (ap);
/* Update the current AP if the supplicant notified a current BSS change
* before it sent the current BSS's scan result.
*/
@ -1705,32 +1702,6 @@ supplicant_iface_new_bss_cb (NMSupplicantInterface *iface,
schedule_ap_list_dump (self);
}
static void
supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface,
const char *object_path,
GVariant *properties,
NMDeviceWifi *self)
{
NMDeviceState state;
NMWifiAP *ap;
g_return_if_fail (self != NULL);
g_return_if_fail (object_path != NULL);
g_return_if_fail (properties != NULL);
/* Ignore new APs when unavailable or unmanaged */
state = nm_device_get_state (NM_DEVICE (self));
if (state <= NM_DEVICE_STATE_UNAVAILABLE)
return;
ap = get_ap_by_supplicant_path (self, object_path);
if (ap) {
_ap_dump (self, ap, "updated", 0);
nm_wifi_ap_update_from_properties (ap, object_path, properties);
schedule_ap_list_dump (self);
}
}
static void
supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface,
const char *object_path,
@ -1744,38 +1715,30 @@ supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface,
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
ap = get_ap_by_supplicant_path (self, object_path);
if (ap) {
if (ap == priv->current_ap) {
/* The current AP cannot be removed (to prevent NM indicating that
* it is connected, but to nothing), but it must be removed later
* when the current AP is changed or cleared. Set 'fake' to
* indicate that this AP is now unknown to the supplicant.
*/
nm_wifi_ap_set_fake (ap, TRUE);
} else {
_ap_dump (self, ap, "removed", 0);
ap_add_remove (self, ACCESS_POINT_REMOVED, ap, TRUE);
schedule_ap_list_dump (self);
}
if (!ap)
return;
if (ap == priv->current_ap) {
/* The current AP cannot be removed (to prevent NM indicating that
* it is connected, but to nothing), but it must be removed later
* when the current AP is changed or cleared. Set 'fake' to
* indicate that this AP is now unknown to the supplicant.
*/
if (nm_wifi_ap_set_fake (ap, TRUE))
_ap_dump (self, ap, "updated", 0);
} else {
ap_add_remove (self, ACCESS_POINT_REMOVED, ap, TRUE);
schedule_ap_list_dump (self);
}
}
static void
remove_supplicant_timeouts (NMDeviceWifi *self)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
nm_clear_g_source (&priv->sup_timeout_id);
nm_clear_g_source (&priv->link_timeout_id);
}
static void
cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
remove_supplicant_interface_error_handler (self);
remove_supplicant_timeouts (self);
nm_clear_g_source (&priv->sup_timeout_id);
nm_clear_g_source (&priv->link_timeout_id);
if (disconnect && priv->sup_iface)
nm_supplicant_interface_disconnect (priv->sup_iface);
}
@ -1893,7 +1856,7 @@ link_timeout_cb (gpointer user_data)
static gboolean
need_new_8021x_secrets (NMDeviceWifi *self,
guint32 old_state,
NMSupplicantInterfaceState old_state,
const char **setting_name)
{
NMSetting8021x *s_8021x;
@ -1947,7 +1910,7 @@ need_new_8021x_secrets (NMDeviceWifi *self,
static gboolean
need_new_wpa_psk (NMDeviceWifi *self,
guint32 old_state,
NMSupplicantInterfaceState old_state,
gint disconnect_reason,
const char **setting_name)
{
@ -1988,8 +1951,8 @@ need_new_wpa_psk (NMDeviceWifi *self,
static gboolean
handle_8021x_or_psk_auth_fail (NMDeviceWifi *self,
guint32 new_state,
guint32 old_state,
NMSupplicantInterfaceState new_state,
NMSupplicantInterfaceState old_state,
int disconnect_reason)
{
NMDevice *device = NM_DEVICE (self);
@ -2042,8 +2005,8 @@ reacquire_interface_cb (gpointer user_data)
static void
supplicant_iface_state_cb (NMSupplicantInterface *iface,
guint32 new_state,
guint32 old_state,
int new_state_i,
int old_state_i,
int disconnect_reason,
gpointer user_data)
{
@ -2052,6 +2015,8 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
NMDevice *device = NM_DEVICE (self);
NMDeviceState devstate;
gboolean scanning;
NMSupplicantInterfaceState new_state = new_state_i;
NMSupplicantInterfaceState old_state = old_state_i;
if (new_state == old_state)
return;
@ -2080,8 +2045,8 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
nm_device_remove_pending_action (device, NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, TRUE);
break;
case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED:
remove_supplicant_interface_error_handler (self);
remove_supplicant_timeouts (self);
nm_clear_g_source (&priv->sup_timeout_id);
nm_clear_g_source (&priv->link_timeout_id);
/* If this is the initial association during device activation,
* schedule the next activation stage.
@ -2171,35 +2136,20 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
}
static void
supplicant_iface_connection_error_cb (NMSupplicantInterface *iface,
const char *name,
const char *message,
NMDeviceWifi *self)
supplicant_iface_assoc_cb (NMSupplicantInterface *iface,
GError *error,
gpointer user_data)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
NMDevice *device = NM_DEVICE (self);
if (nm_device_is_activating (device)) {
_LOGW (LOGD_DEVICE | LOGD_WIFI,
"Activation: (wifi) supplicant association failed: %s - %s",
name, message);
if ( error && !nm_utils_error_is_cancelled (error, TRUE)
&& nm_device_is_activating (device)) {
cleanup_association_attempt (self, TRUE);
nm_device_queue_state (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
}
}
static void
remove_supplicant_interface_error_handler (NMDeviceWifi *self)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
if (priv->sup_iface) {
g_signal_handlers_disconnect_by_func (priv->sup_iface,
supplicant_iface_connection_error_cb,
self);
}
}
static void
supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface,
GParamSpec *pspec,
@ -2567,7 +2517,8 @@ ensure_hotspot_frequency (NMDeviceWifi *self,
if (!freq)
freq = (g_strcmp0 (band, "a") == 0) ? 5180 : 2462;
nm_wifi_ap_set_freq (ap, freq);
if (nm_wifi_ap_set_freq (ap, freq))
_ap_dump (self, ap, "updated", 0);
}
static void
@ -2618,7 +2569,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
remove_supplicant_timeouts (self);
nm_clear_g_source (&priv->sup_timeout_id);
nm_clear_g_source (&priv->link_timeout_id);
req = nm_device_get_act_request (device);
g_assert (req);
@ -2682,20 +2634,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
goto out;
}
/* Hook up error signal handler to capture association errors */
g_signal_connect (priv->sup_iface,
NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR,
G_CALLBACK (supplicant_iface_connection_error_cb),
self);
if (!nm_supplicant_interface_set_config (priv->sup_iface, config, &error)) {
_LOGE (LOGD_DEVICE | LOGD_WIFI,
"Activation: (wifi) couldn't send wireless configuration to the supplicant: %s",
error->message);
g_clear_error (&error);
*reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED;
goto out;
}
nm_supplicant_interface_assoc (priv->sup_iface, config,
supplicant_iface_assoc_cb, self);
/* Set up a timeout on the association attempt to fail after 25 seconds */
priv->sup_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self);
@ -2927,6 +2867,8 @@ activation_success_handler (NMDevice *device)
g_warn_if_fail (priv->current_ap);
if (priv->current_ap) {
if (nm_wifi_ap_get_fake (priv->current_ap)) {
gboolean ap_changed = FALSE;
/* If the activation AP hasn't been seen by the supplicant in a scan
* yet, it will be "fake". This usually happens for Ad-Hoc and
* AP-mode connections. Fill in the details from the device itself
@ -2939,13 +2881,16 @@ activation_success_handler (NMDevice *device)
if ( nm_platform_wifi_get_bssid (NM_PLATFORM_GET, ifindex, bssid)
&& nm_ethernet_address_is_valid (bssid, ETH_ALEN)) {
bssid_str = nm_utils_hwaddr_ntoa (bssid, ETH_ALEN);
nm_wifi_ap_set_address (priv->current_ap, bssid_str);
ap_changed |= nm_wifi_ap_set_address (priv->current_ap, bssid_str);
}
}
if (!nm_wifi_ap_get_freq (priv->current_ap))
nm_wifi_ap_set_freq (priv->current_ap, nm_platform_wifi_get_frequency (NM_PLATFORM_GET, ifindex));
ap_changed |= nm_wifi_ap_set_freq (priv->current_ap, nm_platform_wifi_get_frequency (NM_PLATFORM_GET, ifindex));
if (!nm_wifi_ap_get_max_bitrate (priv->current_ap))
nm_wifi_ap_set_max_bitrate (priv->current_ap, nm_platform_wifi_get_rate (NM_PLATFORM_GET, ifindex));
ap_changed |= nm_wifi_ap_set_max_bitrate (priv->current_ap, nm_platform_wifi_get_rate (NM_PLATFORM_GET, ifindex));
if (ap_changed)
_ap_dump (self, priv->current_ap, "updated", 0);
}
nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req),
@ -3253,6 +3198,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
object_class->finalize = finalize;
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;

View file

@ -29,6 +29,7 @@
#include "NetworkManagerUtils.h"
#include "nm-utils.h"
#include "nm-core-internal.h"
#include "platform/nm-platform.h"
#include "nm-setting-wireless.h"
@ -68,8 +69,8 @@ typedef struct {
NM80211ApSecurityFlags rsn_flags; /* RSN (WPA2) -related flags */
/* Non-scanned attributes */
bool fake; /* Whether or not the AP is from a scan */
bool hotspot; /* Whether the AP is a local device's hotspot network */
bool fake:1; /* Whether or not the AP is from a scan */
bool hotspot:1; /* Whether the AP is a local device's hotspot network */
gint32 last_seen; /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */
} NMWifiAPPrivate;
@ -122,20 +123,20 @@ const GByteArray * nm_wifi_ap_get_ssid (const NMWifiAP *ap)
return NM_WIFI_AP_GET_PRIVATE (ap)->ssid;
}
void
gboolean
nm_wifi_ap_set_ssid (NMWifiAP *ap, const guint8 *ssid, gsize len)
{
NMWifiAPPrivate *priv;
g_return_if_fail (NM_IS_WIFI_AP (ap));
g_return_if_fail (ssid == NULL || len > 0);
g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
g_return_val_if_fail (ssid == NULL || len > 0, FALSE);
priv = NM_WIFI_AP_GET_PRIVATE (ap);
/* same SSID */
if ((ssid && priv->ssid) && (len == priv->ssid->len)) {
if (!memcmp (ssid, priv->ssid->data, len))
return;
return FALSE;
}
if (priv->ssid) {
@ -149,49 +150,56 @@ nm_wifi_ap_set_ssid (NMWifiAP *ap, const guint8 *ssid, gsize len)
}
_notify (ap, PROP_SSID);
return TRUE;
}
static void
static gboolean
nm_wifi_ap_set_flags (NMWifiAP *ap, NM80211ApFlags flags)
{
NMWifiAPPrivate *priv;
g_return_if_fail (NM_IS_WIFI_AP (ap));
g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
priv = NM_WIFI_AP_GET_PRIVATE (ap);
if (priv->flags != flags) {
priv->flags = flags;
_notify (ap, PROP_FLAGS);
return TRUE;
}
return FALSE;
}
static void
static gboolean
nm_wifi_ap_set_wpa_flags (NMWifiAP *ap, NM80211ApSecurityFlags flags)
{
NMWifiAPPrivate *priv;
g_return_if_fail (NM_IS_WIFI_AP (ap));
g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
priv = NM_WIFI_AP_GET_PRIVATE (ap);
if (priv->wpa_flags != flags) {
priv->wpa_flags = flags;
_notify (ap, PROP_WPA_FLAGS);
return TRUE;
}
return FALSE;
}
static void
static gboolean
nm_wifi_ap_set_rsn_flags (NMWifiAP *ap, NM80211ApSecurityFlags flags)
{
NMWifiAPPrivate *priv;
g_return_if_fail (NM_IS_WIFI_AP (ap));
g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
priv = NM_WIFI_AP_GET_PRIVATE (ap);
if (priv->rsn_flags != flags) {
priv->rsn_flags = flags;
_notify (ap, PROP_RSN_FLAGS);
return TRUE;
}
return FALSE;
}
const char *
@ -202,25 +210,34 @@ nm_wifi_ap_get_address (const NMWifiAP *ap)
return NM_WIFI_AP_GET_PRIVATE (ap)->address;
}
void
nm_wifi_ap_set_address (NMWifiAP *ap, const char *addr)
static gboolean
nm_wifi_ap_set_address_bin (NMWifiAP *ap, const guint8 *addr /* ETH_ALEN bytes */)
{
NMWifiAPPrivate *priv;
guint8 addr_buf[ETH_ALEN];
g_return_if_fail (NM_IS_WIFI_AP (ap));
if ( !addr
|| !nm_utils_hwaddr_aton (addr, addr_buf, sizeof (addr_buf)))
g_return_if_reached ();
priv = NM_WIFI_AP_GET_PRIVATE (ap);
if ( !priv->address
|| !nm_utils_hwaddr_matches (addr_buf, sizeof (addr_buf), priv->address, -1)) {
|| !nm_utils_hwaddr_matches (addr, ETH_ALEN, priv->address, -1)) {
g_free (priv->address);
priv->address = nm_utils_hwaddr_ntoa (addr_buf, sizeof (addr_buf));
priv->address = nm_utils_hwaddr_ntoa (addr, ETH_ALEN);
_notify (ap, PROP_HW_ADDRESS);
return TRUE;
}
return FALSE;
}
gboolean
nm_wifi_ap_set_address (NMWifiAP *ap, const char *addr)
{
guint8 addr_buf[ETH_ALEN];
g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
if ( !addr
|| !nm_utils_hwaddr_aton (addr, addr_buf, sizeof (addr_buf)))
g_return_val_if_reached (FALSE);
return nm_wifi_ap_set_address_bin (ap, addr_buf);
}
NM80211Mode
@ -231,21 +248,23 @@ nm_wifi_ap_get_mode (NMWifiAP *ap)
return NM_WIFI_AP_GET_PRIVATE (ap)->mode;
}
static void
static gboolean
nm_wifi_ap_set_mode (NMWifiAP *ap, const NM80211Mode mode)
{
NMWifiAPPrivate *priv;
g_return_if_fail (NM_IS_WIFI_AP (ap));
g_return_if_fail ( mode == NM_802_11_MODE_ADHOC
|| mode == NM_802_11_MODE_INFRA);
g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
g_return_val_if_fail ( mode == NM_802_11_MODE_ADHOC
|| mode == NM_802_11_MODE_INFRA, FALSE);
priv = NM_WIFI_AP_GET_PRIVATE (ap);
if (priv->mode != mode) {
priv->mode = mode;
_notify (ap, PROP_MODE);
return TRUE;
}
return FALSE;
}
gboolean
@ -264,19 +283,21 @@ nm_wifi_ap_get_strength (NMWifiAP *ap)
return NM_WIFI_AP_GET_PRIVATE (ap)->strength;
}
void
gboolean
nm_wifi_ap_set_strength (NMWifiAP *ap, const gint8 strength)
{
NMWifiAPPrivate *priv;
g_return_if_fail (NM_IS_WIFI_AP (ap));
g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
priv = NM_WIFI_AP_GET_PRIVATE (ap);
if (priv->strength != strength) {
priv->strength = strength;
_notify (ap, PROP_STRENGTH);
return TRUE;
}
return FALSE;
}
guint32
@ -287,20 +308,22 @@ nm_wifi_ap_get_freq (NMWifiAP *ap)
return NM_WIFI_AP_GET_PRIVATE (ap)->freq;
}
void
gboolean
nm_wifi_ap_set_freq (NMWifiAP *ap,
const guint32 freq)
{
NMWifiAPPrivate *priv;
g_return_if_fail (NM_IS_WIFI_AP (ap));
g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
priv = NM_WIFI_AP_GET_PRIVATE (ap);
if (priv->freq != freq) {
priv->freq = freq;
_notify (ap, PROP_FREQUENCY);
return TRUE;
}
return FALSE;
}
guint32
@ -312,19 +335,21 @@ nm_wifi_ap_get_max_bitrate (NMWifiAP *ap)
return NM_WIFI_AP_GET_PRIVATE (ap)->max_bitrate;
}
void
gboolean
nm_wifi_ap_set_max_bitrate (NMWifiAP *ap, guint32 bitrate)
{
NMWifiAPPrivate *priv;
g_return_if_fail (NM_IS_WIFI_AP (ap));
g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
priv = NM_WIFI_AP_GET_PRIVATE (ap);
if (priv->max_bitrate != bitrate) {
priv->max_bitrate = bitrate;
_notify (ap, PROP_MAX_BITRATE);
return TRUE;
}
return FALSE;
}
gboolean
@ -335,27 +360,37 @@ nm_wifi_ap_get_fake (const NMWifiAP *ap)
return NM_WIFI_AP_GET_PRIVATE (ap)->fake;
}
void
gboolean
nm_wifi_ap_set_fake (NMWifiAP *ap, gboolean fake)
{
g_return_if_fail (NM_IS_WIFI_AP (ap));
NMWifiAPPrivate *priv;
NM_WIFI_AP_GET_PRIVATE (ap)->fake = fake;
g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
priv = NM_WIFI_AP_GET_PRIVATE (ap);
if (priv->fake != !!fake) {
priv->fake = fake;
return TRUE;
}
return FALSE;
}
static void
static gboolean
nm_wifi_ap_set_last_seen (NMWifiAP *ap, gint32 last_seen)
{
NMWifiAPPrivate *priv;
g_return_if_fail (NM_IS_WIFI_AP (ap));
g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
priv = NM_WIFI_AP_GET_PRIVATE (ap);
if (priv->last_seen != last_seen) {
priv->last_seen = last_seen;
_notify (ap, PROP_LAST_SEEN);
return TRUE;
}
return FALSE;
}
/*****************************************************************************/
@ -400,13 +435,12 @@ security_from_vardict (GVariant *security)
return flags;
}
void
gboolean
nm_wifi_ap_update_from_properties (NMWifiAP *ap,
const char *supplicant_path,
GVariant *properties)
{
NMWifiAPPrivate *priv;
char *addr;
const guint8 *bytes;
GVariant *v;
gsize len;
@ -414,28 +448,30 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap,
const char *s;
gint16 i16;
guint16 u16;
gboolean changed = FALSE;
g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
g_return_val_if_fail (properties, FALSE);
g_return_if_fail (ap != NULL);
g_return_if_fail (properties != NULL);
priv = NM_WIFI_AP_GET_PRIVATE (ap);
g_object_freeze_notify (G_OBJECT (ap));
if (g_variant_lookup (properties, "Privacy", "b", &b) && b)
nm_wifi_ap_set_flags (ap, priv->flags | NM_802_11_AP_FLAGS_PRIVACY);
changed |= nm_wifi_ap_set_flags (ap, priv->flags | NM_802_11_AP_FLAGS_PRIVACY);
if (g_variant_lookup (properties, "Mode", "&s", &s)) {
if (!g_strcmp0 (s, "infrastructure"))
nm_wifi_ap_set_mode (ap, NM_802_11_MODE_INFRA);
changed |= nm_wifi_ap_set_mode (ap, NM_802_11_MODE_INFRA);
else if (!g_strcmp0 (s, "ad-hoc"))
nm_wifi_ap_set_mode (ap, NM_802_11_MODE_ADHOC);
changed |= nm_wifi_ap_set_mode (ap, NM_802_11_MODE_ADHOC);
}
if (g_variant_lookup (properties, "Signal", "n", &i16))
nm_wifi_ap_set_strength (ap, nm_wifi_utils_level_to_quality (i16));
changed |= nm_wifi_ap_set_strength (ap, nm_wifi_utils_level_to_quality (i16));
if (g_variant_lookup (properties, "Frequency", "q", &u16))
nm_wifi_ap_set_freq (ap, u16);
changed |= nm_wifi_ap_set_freq (ap, u16);
v = g_variant_lookup_value (properties, "SSID", G_VARIANT_TYPE_BYTESTRING);
if (v) {
@ -446,7 +482,7 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap,
if ( bytes && len
&& !(((len == 8) || (len == 9)) && !memcmp (bytes, "<hidden>", 8))
&& !nm_utils_is_empty_ssid (bytes, len))
nm_wifi_ap_set_ssid (ap, bytes, len);
changed |= nm_wifi_ap_set_ssid (ap, bytes, len);
g_variant_unref (v);
}
@ -454,11 +490,10 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap,
v = g_variant_lookup_value (properties, "BSSID", G_VARIANT_TYPE_BYTESTRING);
if (v) {
bytes = g_variant_get_fixed_array (v, &len, 1);
if (len == ETH_ALEN) {
addr = nm_utils_hwaddr_ntoa (bytes, len);
nm_wifi_ap_set_address (ap, addr);
g_free (addr);
}
if ( len == ETH_ALEN
&& memcmp (bytes, nm_ip_addr_zero.addr_eth, ETH_ALEN) != 0
&& memcmp (bytes, (char[ETH_ALEN]) { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, ETH_ALEN) != 0)
changed |= nm_wifi_ap_set_address_bin (ap, bytes);
g_variant_unref (v);
}
@ -470,33 +505,37 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap,
/* Find the max AP rate */
for (i = 0; i < len; i++) {
if (rates[i] > maxrate) {
if (rates[i] > maxrate)
maxrate = rates[i];
nm_wifi_ap_set_max_bitrate (ap, rates[i] / 1000);
}
}
if (maxrate)
changed |= nm_wifi_ap_set_max_bitrate (ap, maxrate / 1000);
g_variant_unref (v);
}
v = g_variant_lookup_value (properties, "WPA", G_VARIANT_TYPE_VARDICT);
if (v) {
nm_wifi_ap_set_wpa_flags (ap, priv->wpa_flags | security_from_vardict (v));
changed |= nm_wifi_ap_set_wpa_flags (ap, priv->wpa_flags | security_from_vardict (v));
g_variant_unref (v);
}
v = g_variant_lookup_value (properties, "RSN", G_VARIANT_TYPE_VARDICT);
if (v) {
nm_wifi_ap_set_rsn_flags (ap, priv->rsn_flags | security_from_vardict (v));
changed |= nm_wifi_ap_set_rsn_flags (ap, priv->rsn_flags | security_from_vardict (v));
g_variant_unref (v);
}
if (!priv->supplicant_path)
if (!priv->supplicant_path) {
priv->supplicant_path = g_strdup (supplicant_path);
changed = TRUE;
}
nm_wifi_ap_set_last_seen (ap, nm_utils_get_monotonic_timestamp_s ());
priv->fake = FALSE;
changed |= nm_wifi_ap_set_last_seen (ap, nm_utils_get_monotonic_timestamp_s ());
changed |= nm_wifi_ap_set_fake (ap, FALSE);
g_object_thaw_notify (G_OBJECT (ap));
return changed;
}
static gboolean
@ -583,6 +622,7 @@ nm_wifi_ap_to_string (const NMWifiAP *self,
{
const NMWifiAPPrivate *priv;
const char *supplicant_id = "-";
const char *export_path;
guint32 chan;
char b1[200];
@ -591,10 +631,16 @@ nm_wifi_ap_to_string (const NMWifiAP *self,
priv = NM_WIFI_AP_GET_PRIVATE (self);
chan = nm_utils_wifi_freq_to_channel (priv->freq);
if (priv->supplicant_path)
supplicant_id = strrchr (priv->supplicant_path, '/');
supplicant_id = strrchr (priv->supplicant_path, '/') ?: supplicant_id;
export_path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (self));
if (export_path)
export_path = strrchr (export_path, '/') ?: export_path;
else
export_path = "/";
g_snprintf (str_buf, buf_len,
"%17s %-32s [ %c %3u %3u%% %c W:%04X R:%04X ] %3us %s",
"%17s %-32s [ %c %3u %3u%% %c W:%04X R:%04X ] %3us sup:%s [nm:%s]",
priv->address ?: "(none)",
nm_sprintf_buf (b1, "%s%s%s",
NM_PRINT_FMT_QUOTED (priv->ssid, "\"", nm_utils_escape_ssid (priv->ssid->data, priv->ssid->len), "\"", "(none)")),
@ -611,7 +657,8 @@ nm_wifi_ap_to_string (const NMWifiAP *self,
priv->wpa_flags & 0xFFFF,
priv->rsn_flags & 0xFFFF,
priv->last_seen > 0 ? ((now_s > 0 ? now_s : nm_utils_get_monotonic_timestamp_s ()) - priv->last_seen) : -1,
supplicant_id);
supplicant_id,
export_path);
return str_buf;
}
@ -793,10 +840,7 @@ nm_wifi_ap_init (NMWifiAP *ap)
NMWifiAP *
nm_wifi_ap_new_from_properties (const char *supplicant_path, GVariant *properties)
{
const char bad_bssid1[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
const char bad_bssid2[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
NMWifiAP *ap;
const char *addr;
g_return_val_if_fail (supplicant_path != NULL, NULL);
g_return_val_if_fail (properties != NULL, NULL);
@ -805,10 +849,7 @@ nm_wifi_ap_new_from_properties (const char *supplicant_path, GVariant *propertie
nm_wifi_ap_update_from_properties (ap, supplicant_path, properties);
/* ignore APs with invalid or missing BSSIDs */
addr = nm_wifi_ap_get_address (ap);
if ( !addr
|| nm_utils_hwaddr_matches (addr, -1, bad_bssid1, ETH_ALEN)
|| nm_utils_hwaddr_matches (addr, -1, bad_bssid2, ETH_ALEN)) {
if (!nm_wifi_ap_get_address (ap)) {
g_object_unref (ap);
return NULL;
}

View file

@ -53,7 +53,7 @@ NMWifiAP * nm_wifi_ap_new_from_properties (const char *supplicant_path,
GVariant *properties);
NMWifiAP * nm_wifi_ap_new_fake_from_connection (NMConnection *connection);
void nm_wifi_ap_update_from_properties (NMWifiAP *ap,
gboolean nm_wifi_ap_update_from_properties (NMWifiAP *ap,
const char *supplicant_path,
GVariant *properties);
@ -68,25 +68,25 @@ gboolean nm_wifi_ap_complete_connection (NMWifiAP *self,
const char * nm_wifi_ap_get_supplicant_path (NMWifiAP *ap);
guint64 nm_wifi_ap_get_id (NMWifiAP *ap);
const GByteArray *nm_wifi_ap_get_ssid (const NMWifiAP *ap);
void nm_wifi_ap_set_ssid (NMWifiAP *ap,
gboolean nm_wifi_ap_set_ssid (NMWifiAP *ap,
const guint8 *ssid,
gsize len);
const char * nm_wifi_ap_get_address (const NMWifiAP *ap);
void nm_wifi_ap_set_address (NMWifiAP *ap,
gboolean nm_wifi_ap_set_address (NMWifiAP *ap,
const char *addr);
NM80211Mode nm_wifi_ap_get_mode (NMWifiAP *ap);
gboolean nm_wifi_ap_is_hotspot (NMWifiAP *ap);
gint8 nm_wifi_ap_get_strength (NMWifiAP *ap);
void nm_wifi_ap_set_strength (NMWifiAP *ap,
gboolean nm_wifi_ap_set_strength (NMWifiAP *ap,
gint8 strength);
guint32 nm_wifi_ap_get_freq (NMWifiAP *ap);
void nm_wifi_ap_set_freq (NMWifiAP *ap,
gboolean nm_wifi_ap_set_freq (NMWifiAP *ap,
guint32 freq);
guint32 nm_wifi_ap_get_max_bitrate (NMWifiAP *ap);
void nm_wifi_ap_set_max_bitrate (NMWifiAP *ap,
gboolean nm_wifi_ap_set_max_bitrate (NMWifiAP *ap,
guint32 bitrate);
gboolean nm_wifi_ap_get_fake (const NMWifiAP *ap);
void nm_wifi_ap_set_fake (NMWifiAP *ap,
gboolean nm_wifi_ap_set_fake (NMWifiAP *ap,
gboolean fake);
const char *nm_wifi_ap_to_string (const NMWifiAP *self,

View file

@ -128,7 +128,7 @@ modem_prepare_result (NMModem *modem,
* the device to be auto-activated anymore, which would risk locking
* the SIM if the incorrect PIN continues to be used.
*/
nm_device_set_autoconnect (device, FALSE);
nm_device_set_autoconnect_intern (device, FALSE);
_LOGI (LOGD_MB, "disabling autoconnect due to failed SIM PIN");
}

View file

@ -4240,7 +4240,7 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed)
nm_device_set_enabled (device, enabled);
}
nm_device_set_autoconnect (device, TRUE);
nm_device_set_autoconnect_intern (device, TRUE);
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, FALSE, NM_DEVICE_STATE_REASON_NOW_MANAGED);
}

File diff suppressed because it is too large Load diff

View file

@ -28,7 +28,8 @@
* Supplicant interface states
* A mix of wpa_supplicant interface states and internal states.
*/
enum {
typedef enum {
NM_SUPPLICANT_INTERFACE_STATE_INVALID = -1,
NM_SUPPLICANT_INTERFACE_STATE_INIT = 0,
NM_SUPPLICANT_INTERFACE_STATE_STARTING,
NM_SUPPLICANT_INTERFACE_STATE_READY,
@ -43,8 +44,7 @@ enum {
NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE,
NM_SUPPLICANT_INTERFACE_STATE_COMPLETED,
NM_SUPPLICANT_INTERFACE_STATE_DOWN,
NM_SUPPLICANT_INTERFACE_STATE_LAST
};
} NMSupplicantInterfaceState;
#define NM_TYPE_SUPPLICANT_INTERFACE (nm_supplicant_interface_get_type ())
#define NM_SUPPLICANT_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterface))
@ -64,11 +64,9 @@ enum {
/* Signals */
#define NM_SUPPLICANT_INTERFACE_STATE "state"
#define NM_SUPPLICANT_INTERFACE_REMOVED "removed"
#define NM_SUPPLICANT_INTERFACE_NEW_BSS "new-bss"
#define NM_SUPPLICANT_INTERFACE_BSS_UPDATED "bss-updated"
#define NM_SUPPLICANT_INTERFACE_BSS_REMOVED "bss-removed"
#define NM_SUPPLICANT_INTERFACE_SCAN_DONE "scan-done"
#define NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR "connection-error"
#define NM_SUPPLICANT_INTERFACE_CREDENTIALS_REQUEST "credentials-request"
typedef struct _NMSupplicantInterfaceClass NMSupplicantInterfaceClass;
@ -83,19 +81,25 @@ NMSupplicantInterface * nm_supplicant_interface_new (const char *ifname,
void nm_supplicant_interface_set_supplicant_available (NMSupplicantInterface *self,
gboolean available);
gboolean nm_supplicant_interface_set_config (NMSupplicantInterface * iface,
NMSupplicantConfig * cfg,
GError **error);
typedef void (*NMSupplicantInterfaceAssocCb) (NMSupplicantInterface *iface,
GError *error,
gpointer user_data);
void
nm_supplicant_interface_assoc (NMSupplicantInterface *self,
NMSupplicantConfig *cfg,
NMSupplicantInterfaceAssocCb callback,
gpointer user_data);
void nm_supplicant_interface_disconnect (NMSupplicantInterface * iface);
const char *nm_supplicant_interface_get_object_path (NMSupplicantInterface * iface);
gboolean nm_supplicant_interface_request_scan (NMSupplicantInterface * self, const GPtrArray *ssids);
void nm_supplicant_interface_request_scan (NMSupplicantInterface * self, const GPtrArray *ssids);
guint32 nm_supplicant_interface_get_state (NMSupplicantInterface * self);
NMSupplicantInterfaceState nm_supplicant_interface_get_state (NMSupplicantInterface * self);
const char *nm_supplicant_interface_state_to_string (guint32 state);
const char *nm_supplicant_interface_state_to_string (NMSupplicantInterfaceState state);
gboolean nm_supplicant_interface_get_scanning (NMSupplicantInterface *self);