mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-24 16:00:07 +01:00
merge: 'ssids' RequestScan() option, nmcli connecting hidden SSID (rh #752173)
Add 'ssids' option to RequestScan() DBus call allowing scanning multiple SSIDs, support that in libnm and nmcli. And fix nmcli for connecting to hidden SSIDs. https://bugzilla.gnome.org/show_bug.cgi?id=752173
This commit is contained in:
commit
32c34a8ccd
8 changed files with 338 additions and 68 deletions
|
|
@ -264,8 +264,8 @@ usage (void)
|
|||
" delete <ifname> ...\n\n"
|
||||
" wifi [list [ifname <ifname>] [bssid <BSSID>]]\n\n"
|
||||
" wifi connect <(B)SSID> [password <password>] [wep-key-type key|phrase] [ifname <ifname>]\n"
|
||||
" [bssid <BSSID>] [name <name>] [private yes|no]\n\n"
|
||||
" wifi rescan [[ifname] <ifname>]\n\n"
|
||||
" [bssid <BSSID>] [name <name>] [private yes|no] [hidden yes|no]\n\n"
|
||||
" wifi rescan [ifname <ifname>] [[ssid <SSID to scan>] ...]\n\n"
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -345,7 +345,7 @@ usage_device_wifi (void)
|
|||
"used to list APs for a particular interface, or with a specific BSSID.\n"
|
||||
"\n"
|
||||
"ARGUMENTS := connect <(B)SSID> [password <password>] [wep-key-type key|phrase] [ifname <ifname>]\n"
|
||||
" [bssid <BSSID>] [name <name>] [private yes|no]\n"
|
||||
" [bssid <BSSID>] [name <name>] [private yes|no] [hidden yes|no]\n"
|
||||
"\n"
|
||||
"Connect to a Wi-Fi network specified by SSID or BSSID. The command creates\n"
|
||||
"a new connection and then activates it on a device. This is a command-line\n"
|
||||
|
|
@ -356,12 +356,14 @@ usage_device_wifi (void)
|
|||
"only open, WEP and WPA-PSK networks are supported at the moment. It is also\n"
|
||||
"assumed that IP configuration is obtained via DHCP.\n"
|
||||
"\n"
|
||||
"ARGUMENTS := rescan [[ifname] <ifname>]\n"
|
||||
"ARGUMENTS := rescan [ifname <ifname>] [[ssid <SSID to scan>] ...]\n"
|
||||
"\n"
|
||||
"Request that NetworkManager immediately re-scan for available access points.\n"
|
||||
"NetworkManager scans Wi-Fi networks periodically, but in some cases it might\n"
|
||||
"be useful to start scanning manually. Note that this command does not show\n"
|
||||
"the APs, use 'nmcli device wifi list' for that.\n\n"));
|
||||
"be useful to start scanning manually. 'ssid' allows scanning for a specific\n"
|
||||
"SSID, which is useful for APs with hidden SSIDs. More 'ssid' parameters can be\n"
|
||||
"given. Note that this command does not show the APs,\n"
|
||||
"use 'nmcli device wifi list' for that.\n\n"));
|
||||
}
|
||||
|
||||
/* quit main loop */
|
||||
|
|
@ -2228,9 +2230,9 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
|
|||
{
|
||||
NMDevice *device = NULL;
|
||||
NMAccessPoint *ap = NULL;
|
||||
NM80211ApFlags ap_flags;
|
||||
NM80211ApSecurityFlags ap_wpa_flags;
|
||||
NM80211ApSecurityFlags ap_rsn_flags;
|
||||
NM80211ApFlags ap_flags = NM_802_11_AP_FLAGS_NONE;
|
||||
NM80211ApSecurityFlags ap_wpa_flags = NM_802_11_AP_SEC_NONE;
|
||||
NM80211ApSecurityFlags ap_rsn_flags = NM_802_11_AP_SEC_NONE;
|
||||
NMConnection *connection = NULL;
|
||||
NMSettingConnection *s_con;
|
||||
NMSettingWireless *s_wifi;
|
||||
|
|
@ -2242,6 +2244,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
|
|||
const char *password = NULL;
|
||||
const char *con_name = NULL;
|
||||
gboolean private = FALSE;
|
||||
gboolean hidden = FALSE;
|
||||
gboolean wep_passphrase = FALSE;
|
||||
GByteArray *bssid1_arr = NULL;
|
||||
GByteArray *bssid2_arr = NULL;
|
||||
|
|
@ -2341,6 +2344,19 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
|
|||
g_clear_error (&err_tmp);
|
||||
goto error;
|
||||
}
|
||||
} else if (strcmp (*argv, "hidden") == 0) {
|
||||
GError *err_tmp = NULL;
|
||||
if (next_arg (&argc, &argv) != 0) {
|
||||
g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1));
|
||||
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
||||
goto error;
|
||||
}
|
||||
if (!nmc_string_to_bool (*argv, &hidden, &err_tmp)) {
|
||||
g_string_printf (nmc->return_text, _("Error: %s: %s."), *(argv-1), err_tmp->message);
|
||||
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
||||
g_clear_error (&err_tmp);
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
g_printerr (_("Unknown parameter: %s\n"), *argv);
|
||||
}
|
||||
|
|
@ -2377,14 +2393,41 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
|
|||
goto error;
|
||||
}
|
||||
|
||||
/* For hidden SSID first scan it so that NM learns about the AP */
|
||||
if (hidden) {
|
||||
GVariantBuilder builder, array_builder;
|
||||
GVariant *options;
|
||||
GError *scan_err = NULL;
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
|
||||
g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aay"));
|
||||
g_variant_builder_add (&array_builder, "@ay",
|
||||
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, param_user, strlen (param_user), 1));
|
||||
g_variant_builder_add (&builder, "{sv}", "ssids", g_variant_builder_end (&array_builder));
|
||||
options = g_variant_builder_end (&builder);
|
||||
|
||||
nm_device_wifi_request_scan_options (NM_DEVICE_WIFI (device), options, NULL, &scan_err);
|
||||
if (scan_err) {
|
||||
g_string_printf (nmc->return_text, _("Error: Failed to scan hidden SSID: %s."),
|
||||
scan_err->message);
|
||||
g_clear_error (&scan_err);
|
||||
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find an AP to connect to */
|
||||
ap = find_ap_on_device (device, bssid1_arr, bssid1_arr ? NULL : param_user);
|
||||
if (!ap && !ifname) {
|
||||
/* AP not found. ifname was not specified, so try finding the AP on another device. */
|
||||
while ((device = find_wifi_device_by_iface (devices, NULL, &devices_idx)) != NULL) {
|
||||
ap = find_ap_on_device (device, bssid1_arr, bssid1_arr ? NULL : param_user);
|
||||
if (ap)
|
||||
NMDevice *dev;
|
||||
|
||||
/* AP not found, ifname was not specified, so try finding the AP on another device. */
|
||||
while ((dev = find_wifi_device_by_iface (devices, NULL, &devices_idx)) != NULL) {
|
||||
ap = find_ap_on_device (dev, bssid1_arr, bssid1_arr ? NULL : param_user);
|
||||
if (ap) {
|
||||
device = dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2399,7 +2442,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
|
|||
|
||||
/* If there are some connection data from user, create a connection and
|
||||
* fill them into proper settings. */
|
||||
if (con_name || private || bssid2_arr || password)
|
||||
if (con_name || private || bssid2_arr || password || hidden)
|
||||
connection = nm_simple_connection_new ();
|
||||
|
||||
if (con_name || private) {
|
||||
|
|
@ -2414,12 +2457,24 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
|
|||
if (private)
|
||||
nm_setting_connection_add_permission (s_con, "user", g_get_user_name (), NULL);
|
||||
}
|
||||
if (bssid2_arr) {
|
||||
if (bssid2_arr || hidden) {
|
||||
s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
|
||||
nm_connection_add_setting (connection, NM_SETTING (s_wifi));
|
||||
|
||||
/* 'bssid' parameter is used to restrict the conenction only to the BSSID */
|
||||
g_object_set (s_wifi, NM_SETTING_WIRELESS_BSSID, bssid2_arr, NULL);
|
||||
/* 'bssid' parameter is used to restrict the connection only to the BSSID */
|
||||
if (bssid2_arr)
|
||||
g_object_set (s_wifi, NM_SETTING_WIRELESS_BSSID, bssid2_arr, NULL);
|
||||
|
||||
/* 'hidden' parameter is used to indicate that SSID is not broadcasted */
|
||||
if (hidden) {
|
||||
GBytes *ssid = g_bytes_new (param_user, strlen (param_user));
|
||||
|
||||
g_object_set (s_wifi,
|
||||
NM_SETTING_WIRELESS_SSID, ssid,
|
||||
NM_SETTING_WIRELESS_HIDDEN, hidden,
|
||||
NULL);
|
||||
g_bytes_unref (ssid);
|
||||
}
|
||||
}
|
||||
|
||||
/* handle password */
|
||||
|
|
@ -2510,21 +2565,44 @@ do_device_wifi_rescan (NmCli *nmc, int argc, char **argv)
|
|||
{
|
||||
NMDevice *device;
|
||||
const char *ifname = NULL;
|
||||
GPtrArray *ssids;
|
||||
const GPtrArray *devices;
|
||||
int devices_idx;
|
||||
GVariantBuilder builder, array_builder;
|
||||
GVariant *options;
|
||||
const char *ssid;
|
||||
int i;
|
||||
|
||||
nmc->should_wait = TRUE;
|
||||
|
||||
ssids = g_ptr_array_new ();
|
||||
|
||||
/* Get the parameters */
|
||||
if (argc > 0) {
|
||||
while (argc > 0) {
|
||||
if (strcmp (*argv, "ifname") == 0) {
|
||||
if (ifname) {
|
||||
g_string_printf (nmc->return_text, _("Error: '%s' cannot repeat."), *(argv-1));
|
||||
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
||||
goto error;
|
||||
}
|
||||
if (next_arg (&argc, &argv) != 0) {
|
||||
g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1));
|
||||
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
ifname = *argv;
|
||||
ifname = *argv;
|
||||
} else if (strcmp (*argv, "ssid") == 0) {
|
||||
if (next_arg (&argc, &argv) != 0) {
|
||||
g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1));
|
||||
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
||||
goto error;
|
||||
}
|
||||
g_ptr_array_add (ssids, *argv);
|
||||
} else
|
||||
g_printerr (_("Unknown parameter: %s\n"), *argv);
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
/* Find Wi-Fi device to scan on. When no ifname is provided, the first Wi-Fi is used. */
|
||||
|
|
@ -2541,12 +2619,31 @@ do_device_wifi_rescan (NmCli *nmc, int argc, char **argv)
|
|||
goto error;
|
||||
}
|
||||
|
||||
nm_device_wifi_request_scan_async (NM_DEVICE_WIFI (device), NULL,
|
||||
request_rescan_cb, nmc);
|
||||
|
||||
if (ssids->len) {
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
|
||||
g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aay"));
|
||||
|
||||
for (i = 0; i < ssids->len; i++) {
|
||||
ssid = g_ptr_array_index (ssids, i);
|
||||
g_variant_builder_add (&array_builder, "@ay",
|
||||
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, ssid, strlen (ssid), 1));
|
||||
}
|
||||
|
||||
g_variant_builder_add (&builder, "{sv}", "ssids", g_variant_builder_end (&array_builder));
|
||||
options = g_variant_builder_end (&builder);
|
||||
|
||||
nm_device_wifi_request_scan_options_async (NM_DEVICE_WIFI (device), options,
|
||||
NULL, request_rescan_cb, nmc);
|
||||
} else
|
||||
nm_device_wifi_request_scan_async (NM_DEVICE_WIFI (device),
|
||||
NULL, request_rescan_cb, nmc);
|
||||
|
||||
g_ptr_array_free (ssids, FALSE);
|
||||
return nmc->return_value;
|
||||
error:
|
||||
nmc->should_wait = FALSE;
|
||||
g_ptr_array_free (ssids, FALSE);
|
||||
return nmc->return_value;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -495,6 +495,7 @@ _nmcli_compl_ARGS()
|
|||
stp| \
|
||||
hairpin| \
|
||||
save| \
|
||||
hidden| \
|
||||
private)
|
||||
if [[ "${#words[@]}" -eq 2 ]]; then
|
||||
_nmcli_list "yes no"
|
||||
|
|
@ -579,7 +580,9 @@ _nmcli_compl_ARGS()
|
|||
# remove the options already seen.
|
||||
for i in ${!OPTIONS[*]}; do
|
||||
if [[ "${OPTIONS[$i]}" = "${REMOVE_OPTIONS[0]}" || "${OPTIONS[$i]}" = "${REMOVE_OPTIONS[1]}" ]]; then
|
||||
unset OPTIONS[$i]
|
||||
if ! _nmcli_array_has_value OPTIONS_REPEATABLE "${OPTIONS[$i]}" ; then
|
||||
unset OPTIONS[$i]
|
||||
fi
|
||||
fi
|
||||
done
|
||||
for i in ${!OPTIONS_MANDATORY[*]}; do
|
||||
|
|
@ -737,7 +740,7 @@ _nmcli()
|
|||
cur=''
|
||||
fi
|
||||
|
||||
local OPTIONS_UNKNOWN_OPTION OPTIONS_TYPE OPTIONS_TYPED OPTIONS OPTIONS_MANDATORY COMMAND_ARGS_WAIT_OPTIONS OPTIONS_IP OPTIONS_MANDATORY OPTIONS_NEXT_GROUP OPTIONS_SEP
|
||||
local OPTIONS_UNKNOWN_OPTION OPTIONS_TYPE OPTIONS_TYPED OPTIONS OPTIONS_MANDATORY COMMAND_ARGS_WAIT_OPTIONS OPTIONS_IP OPTIONS_MANDATORY OPTIONS_NEXT_GROUP OPTIONS_SEP OPTIONS_REPEATABLE
|
||||
local COMMAND_CONNECTION_TYPE COMMAND_CONNECTION_ID OPTIONS_MANDATORY_IFNAME HELP_ONLY_AS_FIRST
|
||||
local COMMAND_CONNECTION_ACTIVE=""
|
||||
|
||||
|
|
@ -1287,13 +1290,14 @@ _nmcli()
|
|||
fi
|
||||
else
|
||||
_nmcli_array_delete_at words 0 3
|
||||
local OPTIONS=(password wep-key-type ifname bssid name private)
|
||||
local OPTIONS=(password wep-key-type ifname bssid name private hidden)
|
||||
_nmcli_compl_ARGS
|
||||
fi
|
||||
;;
|
||||
r|re|res|resc|resca|rescan)
|
||||
_nmcli_array_delete_at words 0 2
|
||||
OPTIONS=(ifname)
|
||||
OPTIONS_REPEATABLE=(ssid)
|
||||
OPTIONS=(ifname ssid)
|
||||
_nmcli_compl_ARGS
|
||||
;;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@
|
|||
<method name="RequestScan">
|
||||
<arg name="options" type="a{sv}" direction="in">
|
||||
<tp:docstring>
|
||||
Options of scan (currently unused argument).
|
||||
Options of scan.
|
||||
Currently 'ssids' option with value of "aay" type is supported.
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring>
|
||||
|
|
|
|||
|
|
@ -851,6 +851,8 @@ global:
|
|||
nm_access_point_get_last_seen;
|
||||
nm_device_get_metered;
|
||||
nm_device_get_nm_plugin_missing;
|
||||
nm_device_wifi_request_scan_options;
|
||||
nm_device_wifi_request_scan_options_async;
|
||||
nm_metered_get_type;
|
||||
nm_setting_802_1x_check_cert_scheme;
|
||||
nm_setting_bridge_get_multicast_snooping;
|
||||
|
|
|
|||
|
|
@ -269,6 +269,52 @@ nm_device_wifi_get_access_point_by_path (NMDeviceWifi *device,
|
|||
return ap;
|
||||
}
|
||||
|
||||
static GVariant *
|
||||
prepare_scan_options (GVariant *options)
|
||||
{
|
||||
|
||||
GVariant *variant;
|
||||
GVariantIter iter;
|
||||
GVariantBuilder builder;
|
||||
char *key;
|
||||
GVariant *value;
|
||||
|
||||
if (!options)
|
||||
variant = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
|
||||
else {
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
|
||||
g_variant_iter_init (&iter, options);
|
||||
while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
|
||||
{
|
||||
// FIXME: verify options here?
|
||||
g_variant_builder_add (&builder, "{sv}", key, value);
|
||||
}
|
||||
variant = g_variant_builder_end (&builder);
|
||||
}
|
||||
return variant;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_device_wifi_request_scan (NMDeviceWifi *device,
|
||||
GVariant *options,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret;
|
||||
GVariant *variant;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), FALSE);
|
||||
|
||||
variant = prepare_scan_options (options);
|
||||
|
||||
ret = nmdbus_device_wifi_call_request_scan_sync (NM_DEVICE_WIFI_GET_PRIVATE (device)->proxy,
|
||||
variant,
|
||||
cancellable, error);
|
||||
if (error && *error)
|
||||
g_dbus_error_strip_remote_error (*error);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_wifi_request_scan:
|
||||
* @device: a #NMDeviceWifi
|
||||
|
|
@ -287,17 +333,36 @@ nm_device_wifi_request_scan (NMDeviceWifi *device,
|
|||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret;
|
||||
return _device_wifi_request_scan (device, NULL, cancellable, error);
|
||||
}
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), FALSE);
|
||||
|
||||
ret = nmdbus_device_wifi_call_request_scan_sync (NM_DEVICE_WIFI_GET_PRIVATE (device)->proxy,
|
||||
g_variant_new_array (G_VARIANT_TYPE ("{sv}"),
|
||||
NULL, 0),
|
||||
cancellable, error);
|
||||
if (error && *error)
|
||||
g_dbus_error_strip_remote_error (*error);
|
||||
return ret;
|
||||
/**
|
||||
* nm_device_wifi_request_scan_options:
|
||||
* @device: a #NMDeviceWifi
|
||||
* @options: dictionary with options for RequestScan(), or %NULL
|
||||
* @cancellable: a #GCancellable, or %NULL
|
||||
* @error: location for a #GError, or %NULL
|
||||
*
|
||||
* Request NM to scan for access points on @device. Note that the function
|
||||
* returns immediately after requesting the scan, and it may take some time
|
||||
* after that for the scan to complete.
|
||||
* This is the same as @nm_device_wifi_request_scan except it accepts @options
|
||||
* for the scanning. The argument is the dictionary passed to RequestScan()
|
||||
* D-Bus call. Valid otions inside the dictionary are:
|
||||
* 'ssids' => array of SSIDs (saay)
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE on error, in which case @error will be
|
||||
* set.
|
||||
*
|
||||
* Since: 1.2
|
||||
**/
|
||||
gboolean
|
||||
nm_device_wifi_request_scan_options (NMDeviceWifi *device,
|
||||
GVariant *options,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return _device_wifi_request_scan (device, options, cancellable, error);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -324,19 +389,9 @@ request_scan_cb (GObject *source,
|
|||
g_slice_free (RequestScanInfo, info);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_wifi_request_scan_async:
|
||||
* @device: a #NMDeviceWifi
|
||||
* @cancellable: a #GCancellable, or %NULL
|
||||
* @callback: callback to be called when the scan has been requested
|
||||
* @user_data: caller-specific data passed to @callback
|
||||
*
|
||||
* Request NM to scan for access points on @device. Note that @callback will be
|
||||
* called immediately after requesting the scan, and it may take some time after
|
||||
* that for the scan to complete.
|
||||
**/
|
||||
void
|
||||
nm_device_wifi_request_scan_async (NMDeviceWifi *device,
|
||||
static void
|
||||
_device_wifi_request_scan_async (NMDeviceWifi *device,
|
||||
GVariant *options,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
|
|
@ -344,6 +399,7 @@ nm_device_wifi_request_scan_async (NMDeviceWifi *device,
|
|||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
|
||||
RequestScanInfo *info;
|
||||
GSimpleAsyncResult *simple;
|
||||
GVariant *variant;
|
||||
|
||||
g_return_if_fail (NM_IS_DEVICE_WIFI (device));
|
||||
|
||||
|
|
@ -362,12 +418,62 @@ nm_device_wifi_request_scan_async (NMDeviceWifi *device,
|
|||
info->device = device;
|
||||
info->simple = simple;
|
||||
|
||||
variant = prepare_scan_options (options);
|
||||
|
||||
priv->scan_info = info;
|
||||
nmdbus_device_wifi_call_request_scan (NM_DEVICE_WIFI_GET_PRIVATE (device)->proxy,
|
||||
g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0),
|
||||
variant,
|
||||
cancellable, request_scan_cb, info);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_wifi_request_scan_async:
|
||||
* @device: a #NMDeviceWifi
|
||||
* @cancellable: a #GCancellable, or %NULL
|
||||
* @callback: callback to be called when the scan has been requested
|
||||
* @user_data: caller-specific data passed to @callback
|
||||
*
|
||||
* Request NM to scan for access points on @device. Note that @callback will be
|
||||
* called immediately after requesting the scan, and it may take some time after
|
||||
* that for the scan to complete.
|
||||
**/
|
||||
void
|
||||
nm_device_wifi_request_scan_async (NMDeviceWifi *device,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
_device_wifi_request_scan_async (device, NULL, cancellable, callback, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_wifi_request_scan_options_async:
|
||||
* @device: a #NMDeviceWifi
|
||||
* @options: dictionary with options for RequestScan(), or %NULL
|
||||
* @cancellable: a #GCancellable, or %NULL
|
||||
* @callback: callback to be called when the scan has been requested
|
||||
* @user_data: caller-specific data passed to @callback
|
||||
*
|
||||
* Request NM to scan for access points on @device. Note that @callback will be
|
||||
* called immediately after requesting the scan, and it may take some time after
|
||||
* that for the scan to complete.
|
||||
* This is the same as @nm_device_wifi_request_scan_async except it accepts @options
|
||||
* for the scanning. The argument is the dictionary passed to RequestScan()
|
||||
* D-Bus call. Valid otions inside the dictionary are:
|
||||
* 'ssids' => array of SSIDs (saay)
|
||||
*
|
||||
* Since: 1.2
|
||||
**/
|
||||
void
|
||||
nm_device_wifi_request_scan_options_async (NMDeviceWifi *device,
|
||||
GVariant *options,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
_device_wifi_request_scan_async (device, options, cancellable, callback, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_wifi_request_scan_finish:
|
||||
* @device: a #NMDeviceWifi
|
||||
|
|
|
|||
|
|
@ -77,11 +77,21 @@ const GPtrArray * nm_device_wifi_get_access_points (NMDeviceWifi *
|
|||
gboolean nm_device_wifi_request_scan (NMDeviceWifi *device,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
NM_AVAILABLE_IN_1_2
|
||||
gboolean nm_device_wifi_request_scan_options (NMDeviceWifi *device,
|
||||
GVariant *options,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
void nm_device_wifi_request_scan_async (NMDeviceWifi *device,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
NM_AVAILABLE_IN_1_2
|
||||
void nm_device_wifi_request_scan_options_async (NMDeviceWifi *device,
|
||||
GVariant *options,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean nm_device_wifi_request_scan_finish (NMDeviceWifi *device,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
.\"
|
||||
.\" Copyright 2010 - 2015 Red Hat, Inc.
|
||||
.\"
|
||||
.TH NMCLI "1" "19 February 2015"
|
||||
.TH NMCLI "1" "12 August 2015"
|
||||
|
||||
.SH NAME
|
||||
nmcli \- command\(hyline tool for controlling NetworkManager
|
||||
|
|
@ -802,7 +802,8 @@ List available Wi\(hyFi access points. The \fIifname\fP and \fIbssid\fP options
|
|||
can be used to list APs for a particular interface or with a specific BSSID,
|
||||
respectively.
|
||||
.TP
|
||||
.B wifi connect <(B)SSID> [password <password>] [wep\-key\-type key|phrase] [ifname <ifname>] [bssid <BSSID>] [name <name>] [private yes|no]
|
||||
.B wifi connect <(B)SSID> [password <password>] [wep\-key\-type key|phrase] [ifname <ifname>] [bssid <BSSID>] [name <name>]
|
||||
.B [private yes|no] [hidden yes|no]
|
||||
.br
|
||||
Connect to a Wi\(hyFi network specified by SSID or BSSID. The command creates a new
|
||||
connection and then activates it on a device. This is a command\(hyline counterpart
|
||||
|
|
@ -830,13 +831,20 @@ Available options are:
|
|||
.IP \fIprivate\fP 13
|
||||
\(en if set to \fByes\fP, the connection will only be visible to the user who created it.
|
||||
Otherwise the connection is system\(hywide, which is the default.
|
||||
.IP \fIhidden\fP 13
|
||||
\(en set to \fByes\fP when connecting for the first time to an AP not broadcasting its SSID.
|
||||
Otherwise the SSID would not be found and the connection attempt would fail.
|
||||
.RE
|
||||
.TP
|
||||
.B wifi rescan [[ifname] <ifname>]
|
||||
.B wifi rescan [ifname <ifname>] [[ssid <SSID>] ...]
|
||||
.br
|
||||
Request that \fINetworkManager\fP immediately re-scan for available access points.
|
||||
NetworkManager scans Wi\(hyFi networks periodically, but in some cases it can be
|
||||
useful to start scanning manually (e.g. after resuming the computer).
|
||||
useful to start scanning manually (e.g. after resuming the computer). By using
|
||||
\fIssid\fP, it is possible to scan for a specific SSID, which is useful for APs
|
||||
with hidden SSIDs. You can provide multiple \fIssid\fP parameters in order to
|
||||
scan more SSIDs.
|
||||
.br
|
||||
This command does not show the APs, use 'nmcli device wifi list' for that.
|
||||
|
||||
.TP
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include "nm-enum-types.h"
|
||||
#include "nm-wifi-enum-types.h"
|
||||
#include "nm-connection-provider.h"
|
||||
#include "nm-core-internal.h"
|
||||
|
||||
#include "nmdbus-device-wifi.h"
|
||||
|
||||
|
|
@ -160,7 +161,7 @@ static void supplicant_iface_notify_current_bss (NMSupplicantInterface *iface,
|
|||
GParamSpec *pspec,
|
||||
NMDeviceWifi *self);
|
||||
|
||||
static gboolean request_wireless_scan (gpointer user_data);
|
||||
static void request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options);
|
||||
|
||||
static void emit_ap_added_removed (NMDeviceWifi *self,
|
||||
guint signum,
|
||||
|
|
@ -534,7 +535,7 @@ deactivate (NMDevice *device)
|
|||
/* Ensure we trigger a scan after deactivating a Hotspot */
|
||||
if (old_mode == NM_802_11_MODE_AP) {
|
||||
cancel_pending_scan (self);
|
||||
request_wireless_scan (self);
|
||||
request_wireless_scan (self, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1051,6 +1052,7 @@ request_scan_cb (NMDevice *device,
|
|||
gpointer user_data)
|
||||
{
|
||||
NMDeviceWifi *self = NM_DEVICE_WIFI (device);
|
||||
gs_unref_variant GVariant *new_scan_options = user_data;
|
||||
|
||||
if (error) {
|
||||
g_dbus_method_invocation_return_gerror (context, error);
|
||||
|
|
@ -1066,7 +1068,7 @@ request_scan_cb (NMDevice *device,
|
|||
}
|
||||
|
||||
cancel_pending_scan (self);
|
||||
request_wireless_scan (self);
|
||||
request_wireless_scan (self, new_scan_options);
|
||||
g_dbus_method_invocation_return_value (context, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -1115,7 +1117,7 @@ impl_device_wifi_request_scan (NMDeviceWifi *self,
|
|||
NM_AUTH_PERMISSION_NETWORK_CONTROL,
|
||||
TRUE,
|
||||
request_scan_cb,
|
||||
NULL);
|
||||
options ? g_variant_ref (options) : NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -1276,23 +1278,58 @@ build_hidden_probe_list (NMDeviceWifi *self)
|
|||
return ssids;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
request_wireless_scan (gpointer user_data)
|
||||
static GPtrArray *
|
||||
ssids_options_to_ptrarray (GVariant *value)
|
||||
{
|
||||
GPtrArray *ssids = NULL;
|
||||
GByteArray *ssid_array;
|
||||
GVariant *v;
|
||||
const guint8 *bytes;
|
||||
gsize len;
|
||||
int num_ssids, i;
|
||||
|
||||
num_ssids = g_variant_n_children (value);
|
||||
if (num_ssids) {
|
||||
ssids = g_ptr_array_new_full (num_ssids, (GDestroyNotify) g_byte_array_unref);
|
||||
for (i = 0; i < num_ssids; i++) {
|
||||
v = g_variant_get_child_value (value, i);
|
||||
bytes = g_variant_get_fixed_array (v, &len, sizeof (guint8));
|
||||
ssid_array = g_byte_array_new ();
|
||||
g_byte_array_append (ssid_array, bytes, len);
|
||||
g_ptr_array_add (ssids, ssid_array);
|
||||
}
|
||||
}
|
||||
return ssids;
|
||||
}
|
||||
|
||||
static void
|
||||
request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options)
|
||||
{
|
||||
NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
gboolean backoff = FALSE;
|
||||
GPtrArray *ssids = NULL;
|
||||
|
||||
if (priv->requested_scan) {
|
||||
/* There's already a scan in progress */
|
||||
return FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (check_scanning_allowed (self)) {
|
||||
_LOGD (LOGD_WIFI_SCAN, "scanning requested");
|
||||
|
||||
ssids = build_hidden_probe_list (self);
|
||||
if (scan_options) {
|
||||
GVariant *val = g_variant_lookup_value (scan_options, "ssids", NULL);
|
||||
|
||||
if (val) {
|
||||
if (g_variant_is_of_type (val, G_VARIANT_TYPE ("aay")))
|
||||
ssids = ssids_options_to_ptrarray (val);
|
||||
else
|
||||
_LOGD (LOGD_WIFI_SCAN, "ignoring invalid 'ssids' scan option");
|
||||
g_variant_unref (val);
|
||||
}
|
||||
}
|
||||
if (!ssids)
|
||||
ssids = build_hidden_probe_list (self);
|
||||
|
||||
if (nm_logging_enabled (LOGL_DEBUG, LOGD_WIFI_SCAN)) {
|
||||
if (ssids) {
|
||||
|
|
@ -1327,9 +1364,14 @@ request_wireless_scan (gpointer user_data)
|
|||
|
||||
priv->pending_scan_id = 0;
|
||||
schedule_scan (self, backoff);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
request_wireless_scan_periodic (gpointer user_data)
|
||||
{
|
||||
request_wireless_scan (user_data, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* schedule_scan
|
||||
|
|
@ -1357,7 +1399,7 @@ schedule_scan (NMDeviceWifi *self, gboolean backoff)
|
|||
factor = 1;
|
||||
|
||||
priv->pending_scan_id = g_timeout_add_seconds (next_scan,
|
||||
request_wireless_scan,
|
||||
request_wireless_scan_periodic,
|
||||
self);
|
||||
|
||||
priv->scheduled_scan_time = now + priv->scan_interval;
|
||||
|
|
@ -2771,7 +2813,7 @@ device_state_changed (NMDevice *device,
|
|||
/* Kick off a scan to get latest results */
|
||||
priv->scan_interval = SCAN_INTERVAL_MIN;
|
||||
cancel_pending_scan (self);
|
||||
request_wireless_scan (self);
|
||||
request_wireless_scan (self, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue