wifi: add on-demand WiFi scan support

A new D-Bus method was added to invoke the on-demand WiFi scan.
This commit is contained in:
Gary Ching-Pang Lin 2012-06-05 11:19:41 +08:00 committed by Dan Williams
parent 5903392887
commit 5e3e19d02b
3 changed files with 73 additions and 38 deletions

38
TODO
View file

@ -53,44 +53,6 @@ provide Ad-Hoc connection sharing support for those devices and switch between
Ad-Hoc and AP mode depending on device capabilities.
* On-Demand WiFi Scan support
Single-user and embedded devices often use a continuous wifi scan when the
networking configuration interface is open to quickly allow users to find their
wifi network. NM periodically scans, but this could take as long as 2 mintues
to update the list. Note that WiFi scans require 2 - 10 seconds to complete,
and during this time normal traffic (video, VOIP, streaming music, downloads,
etc) is not transmitted, so a WiFi scan is a disruptive operation to the user.
A D-Bus method should be added to the NMDeviceWifi device to allow user
applications to request a scan. This request should be rate-limited to no
more than once every 10 seconds to give time for traffic to resume when the
scan is done, and to lessen the effect of any DDoS by malicious user
applications. This request should also be restricted by one or more PolicyKit
permissions like org.freedesktop.NetworkManager.network-control.
To begin, a new method definition should be added to the
introspection/nm-device-wifi.xml for a method called "RequestScan" which takes
an argument called "options" of type of "a{sv}". This argument will be used
later. An annotation (like the other functions have) should be added so that
the method will be called "impl_device_request_scan".
Next, the corresponding method implementation should be added to
src/nm-device-wifi.c by adding the prototype for impl_device_request_scan
near the top of the file, and implementing it below. The implementation will
recieve a GHashTable corresponding to the "a{sv}" argument list from the XML
file, but we can ignore that for now.
The incoming request should be authenticated using nm_auth_get_caller_uid()
and additionally starting a PolicyKit authentication check with
with nm_auth_chain_new(). See the function manager_device_disconnect_request()
in src/nm-manager.c for an example of this.
Only after the caller is authorized to scan should the request be checked
against the last scan timestamp, and if the last scan was 10 seconds or more
ago, a new scan should be requested.
* Reconnect to WiFi Networks Only If They Succeeded Once
Currently, NetworkManager will attempt to connect to a previously attempted

View file

@ -14,6 +14,19 @@
</tp:docstring>
</method>
<method name="RequestScan">
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_device_request_scan"/>
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="options" type="a{sv}" direction="in">
<tp:docstring>
Options of scan
</tp:docstring>
</arg>
<tp:docstring>
Request the device to scan
</tp:docstring>
</method>
<property name="HwAddress" type="s" access="read">
<tp:docstring>
The active hardware address of the device.

View file

@ -56,6 +56,7 @@
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
#include "nm-system.h"
#include "nm-manager-auth.h"
#include "nm-settings-connection.h"
#include "nm-enum-types.h"
#include "wifi-utils.h"
@ -64,6 +65,10 @@ static gboolean impl_device_get_access_points (NMDeviceWifi *device,
GPtrArray **aps,
GError **err);
static void impl_device_request_scan (NMDeviceWifi *device,
GHashTable *options,
DBusGMethodInvocation *context);
#include "nm-device-wifi-glue.h"
@ -150,6 +155,8 @@ struct _NMDeviceWifiPrivate {
guint periodic_source_id;
guint link_timeout_id;
glong request_scan_time;
NMDeviceWifiCapabilities capabilities;
};
@ -191,6 +198,8 @@ static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface * iface,
static void schedule_scanlist_cull (NMDeviceWifi *self);
static gboolean request_wireless_scan (gpointer user_data);
/*****************************************************************/
#define NM_WIFI_ERROR (nm_wifi_error_quark ())
@ -330,6 +339,8 @@ constructor (GType type,
}
priv->ipw_rfkill_state = nm_device_wifi_get_ipw_rfkill_state (self);
priv->request_scan_time = 0;
return object;
}
@ -1441,6 +1452,55 @@ impl_device_get_access_points (NMDeviceWifi *self,
return TRUE;
}
static void
request_scan_cb (NMDevice *device,
DBusGMethodInvocation *context,
GError *error,
gpointer user_data)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (device);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
GTimeVal now;
if (error) {
dbus_g_method_return_error (context, error);
g_clear_error (&error);
} else {
g_get_current_time (&now);
cancel_pending_scan (self);
request_wireless_scan (self);
priv->request_scan_time = now.tv_sec;
dbus_g_method_return (context);
}
}
static void
impl_device_request_scan (NMDeviceWifi *self,
GHashTable *options,
DBusGMethodInvocation *context)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
GTimeVal now;
g_get_current_time (&now);
if (!priv->enabled || now.tv_sec - priv->request_scan_time < 10) {
dbus_g_method_return (context);
return;
}
/* Ask the manager to authenticate this request for us */
g_signal_emit_by_name (NM_DEVICE (self),
NM_DEVICE_AUTH_REQUEST,
context,
NM_AUTH_PERMISSION_NETWORK_CONTROL,
TRUE,
request_scan_cb,
NULL);
return;
}
static gboolean
scanning_allowed (NMDeviceWifi *self)
{