diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index afc4f0932b..5fbbac7aa2 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -144,7 +144,6 @@ struct _NMDeviceWifiPrivate { gboolean enabled; /* rfkilled or not */ time_t scheduled_scan_time; - time_t request_scan_time; guint8 scan_interval; /* seconds */ guint pending_scan_id; guint scanlist_cull_id; @@ -159,6 +158,8 @@ struct _NMDeviceWifiPrivate { NMDeviceWifiCapabilities capabilities; }; +static gboolean check_scanning_allowed (NMDeviceWifi *self); + static void schedule_scan (NMDeviceWifi *self, gboolean backoff); static void cancel_pending_scan (NMDeviceWifi *self); @@ -1456,16 +1457,19 @@ request_scan_cb (NMDevice *device, gpointer user_data) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); if (error) { dbus_g_method_return_error (context, error); g_clear_error (&error); + } else if (!check_scanning_allowed (self)) { + error = g_error_new_literal (NM_WIFI_ERROR, + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, + "Scanning not allowed at this time"); + dbus_g_method_return_error (context, error); + g_error_free (error); } else { cancel_pending_scan (self); request_wireless_scan (self); - priv->request_scan_time = time (NULL); - dbus_g_method_return (context); } } @@ -1476,22 +1480,48 @@ impl_device_request_scan (NMDeviceWifi *self, DBusGMethodInvocation *context) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (self); + time_t last_scan; + GError *error; - if (!priv->enabled || (time (NULL) - priv->request_scan_time) < 10) { - dbus_g_method_return (context); - return; + if ( !priv->enabled + || !priv->supplicant.iface + || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED + || nm_device_is_activating (device)) { + error = g_error_new_literal (NM_WIFI_ERROR, + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, + "Scanning not allowed while unavailable or activating"); + goto error; + } + + if (nm_supplicant_interface_get_scanning (priv->supplicant.iface)) { + error = g_error_new_literal (NM_WIFI_ERROR, + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, + "Scanning not allowed while already scanning"); + goto error; + } + + last_scan = nm_supplicant_interface_get_last_scan_time (priv->supplicant.iface); + if ((time (NULL) - last_scan) < 10) { + error = g_error_new_literal (NM_WIFI_ERROR, + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, + "Scanning not allowed immediately following previous scan"); + goto error; } /* Ask the manager to authenticate this request for us */ - g_signal_emit_by_name (NM_DEVICE (self), + g_signal_emit_by_name (device, NM_DEVICE_AUTH_REQUEST, context, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE, request_scan_cb, NULL); - return; + +error: + dbus_g_method_return_error (context, error); + g_error_free (error); } static gboolean diff --git a/src/nm-device-wifi.h b/src/nm-device-wifi.h index 1e665fc3a6..b22c78b3a3 100644 --- a/src/nm-device-wifi.h +++ b/src/nm-device-wifi.h @@ -46,6 +46,7 @@ typedef enum { NM_WIFI_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND, /*< nick=AccessPointNotFound >*/ + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, /*< nick=ScanNotAllowed >*/ } NMWifiError; #define NM_DEVICE_WIFI_HW_ADDRESS "hw-address" diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index 208545ab5d..cbe7032f0a 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -261,6 +261,10 @@ bss_properties_changed (DBusGProxy *proxy, gpointer user_data) { NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + if (priv->scanning) + priv->last_scan = time (NULL); if (g_strcmp0 (interface, WPAS_DBUS_IFACE_BSS) == 0) g_signal_emit (self, signals[BSS_UPDATED], 0, dbus_g_proxy_get_path (proxy), props); @@ -272,6 +276,10 @@ old_bss_properties_changed (DBusGProxy *proxy, gpointer user_data) { NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + if (priv->scanning) + priv->last_scan = time (NULL); g_signal_emit (self, signals[BSS_UPDATED], 0, dbus_g_proxy_get_path (proxy), props); } @@ -350,7 +358,13 @@ wpas_iface_bss_added (DBusGProxy *proxy, GHashTable *props, gpointer user_data) { - handle_new_bss (NM_SUPPLICANT_INTERFACE (user_data), object_path, props); + NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + if (priv->scanning) + priv->last_scan = time (NULL); + + handle_new_bss (self, object_path, props); } static void @@ -449,6 +463,11 @@ set_state (NMSupplicantInterface *self, guint32 new_state) } priv->state = new_state; + + if ( priv->state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING + || old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING) + priv->last_scan = time (NULL); + g_signal_emit (self, signals[STATE], 0, priv->state, old_state); } @@ -494,6 +513,12 @@ nm_supplicant_interface_get_scanning (NMSupplicantInterface *self) return FALSE; } +time_t +nm_supplicant_interface_get_last_scan_time (NMSupplicantInterface *self) +{ + return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->last_scan; +} + static void wpas_iface_scan_done (DBusGProxy *proxy, gboolean success, @@ -504,7 +529,6 @@ wpas_iface_scan_done (DBusGProxy *proxy, /* Cache last scan completed time */ priv->last_scan = time (NULL); - g_signal_emit (self, signals[SCAN_DONE], 0, success); } diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h index 77abec0758..b99c0f2690 100644 --- a/src/supplicant-manager/nm-supplicant-interface.h +++ b/src/supplicant-manager/nm-supplicant-interface.h @@ -136,6 +136,8 @@ const char *nm_supplicant_interface_state_to_string (guint32 state); gboolean nm_supplicant_interface_get_scanning (NMSupplicantInterface *self); +time_t nm_supplicant_interface_get_last_scan_time (NMSupplicantInterface *self); + const char *nm_supplicant_interface_get_ifname (NMSupplicantInterface *self); guint nm_supplicant_interface_get_max_scan_ssids (NMSupplicantInterface *self);