mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-25 17:59:25 +01:00
network: delay connect if ANQP has not completed
Using the new station ANQP watch network can delay the connection request until after ANQP has finished. Since station may be autoconnecting we must also add a check in network_autoconnect which prevents it from autoconnecting if we have a pending Connect request.
This commit is contained in:
parent
60e2c4647c
commit
248190b0ed
@ -52,6 +52,7 @@
|
|||||||
#include "src/util.h"
|
#include "src/util.h"
|
||||||
|
|
||||||
static uint32_t known_networks_watch;
|
static uint32_t known_networks_watch;
|
||||||
|
static uint32_t anqp_watch;
|
||||||
|
|
||||||
struct network {
|
struct network {
|
||||||
char ssid[33];
|
char ssid[33];
|
||||||
@ -72,7 +73,10 @@ struct network {
|
|||||||
bool update_psk:1; /* Whether PSK should be written to storage */
|
bool update_psk:1; /* Whether PSK should be written to storage */
|
||||||
bool ask_passphrase:1; /* Whether we should force-ask agent */
|
bool ask_passphrase:1; /* Whether we should force-ask agent */
|
||||||
bool is_hs20:1;
|
bool is_hs20:1;
|
||||||
|
bool anqp_pending:1; /* Set if there is a pending ANQP request */
|
||||||
int rank;
|
int rank;
|
||||||
|
/* Holds DBus Connect() message if it comes in before ANQP finishes */
|
||||||
|
struct l_dbus_message *connect_after_anqp;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool network_settings_load(struct network *network)
|
static bool network_settings_load(struct network *network)
|
||||||
@ -521,6 +525,10 @@ int network_autoconnect(struct network *network, struct scan_bss *bss)
|
|||||||
bool is_rsn;
|
bool is_rsn;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* already waiting for an agent request, connect in progress */
|
||||||
|
if (network->agent_request)
|
||||||
|
return -EALREADY;
|
||||||
|
|
||||||
switch (security) {
|
switch (security) {
|
||||||
case SECURITY_NONE:
|
case SECURITY_NONE:
|
||||||
is_rsn = false;
|
is_rsn = false;
|
||||||
@ -1156,6 +1164,22 @@ static struct l_dbus_message *network_connect(struct l_dbus *dbus,
|
|||||||
station_connect_network(station, network, bss, message);
|
station_connect_network(station, network, bss, message);
|
||||||
return NULL;
|
return NULL;
|
||||||
case SECURITY_8021X:
|
case SECURITY_8021X:
|
||||||
|
if (network->connect_after_anqp)
|
||||||
|
return dbus_error_busy(message);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there is an ongoing ANQP request we must wait for that to
|
||||||
|
* finish. Save the message and wait for the ANQP watch to
|
||||||
|
* fire
|
||||||
|
*/
|
||||||
|
if (network->anqp_pending) {
|
||||||
|
network->connect_after_anqp =
|
||||||
|
l_dbus_message_ref(message);
|
||||||
|
l_debug("Pending ANQP request, delaying connect to %s",
|
||||||
|
network->ssid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!network_settings_load(network))
|
if (!network_settings_load(network))
|
||||||
return dbus_error_not_configured(message);
|
return dbus_error_not_configured(message);
|
||||||
|
|
||||||
@ -1484,6 +1508,35 @@ static void known_networks_changed(enum known_networks_event event,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void anqp_watch_changed(enum station_anqp_state state,
|
||||||
|
struct network *network, void *user_data)
|
||||||
|
{
|
||||||
|
network->anqp_pending = state == STATION_ANQP_STARTED;
|
||||||
|
|
||||||
|
if (state == STATION_ANQP_FINISHED && network->connect_after_anqp) {
|
||||||
|
struct l_dbus_message *reply;
|
||||||
|
|
||||||
|
l_debug("ANQP complete, resuming connect to %s", network->ssid);
|
||||||
|
|
||||||
|
if (!network_settings_load(network)) {
|
||||||
|
reply = dbus_error_not_configured(
|
||||||
|
network->connect_after_anqp);
|
||||||
|
dbus_pending_reply(&network->connect_after_anqp, reply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = network_connect_8021x(network,
|
||||||
|
network_bss_select(network, true),
|
||||||
|
network->connect_after_anqp);
|
||||||
|
|
||||||
|
if (reply)
|
||||||
|
l_dbus_send(dbus_get_bus(), reply);
|
||||||
|
|
||||||
|
l_dbus_message_unref(network->connect_after_anqp);
|
||||||
|
network->connect_after_anqp = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void setup_network_interface(struct l_dbus_interface *interface)
|
static void setup_network_interface(struct l_dbus_interface *interface)
|
||||||
{
|
{
|
||||||
l_dbus_interface_method(interface, "Connect", 0,
|
l_dbus_interface_method(interface, "Connect", 0,
|
||||||
@ -1517,6 +1570,8 @@ static int network_init(void)
|
|||||||
known_networks_watch =
|
known_networks_watch =
|
||||||
known_networks_watch_add(known_networks_changed, NULL, NULL);
|
known_networks_watch_add(known_networks_changed, NULL, NULL);
|
||||||
|
|
||||||
|
anqp_watch = station_add_anqp_watch(anqp_watch_changed, NULL, NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1525,6 +1580,9 @@ static void network_exit(void)
|
|||||||
known_networks_watch_remove(known_networks_watch);
|
known_networks_watch_remove(known_networks_watch);
|
||||||
known_networks_watch = 0;
|
known_networks_watch = 0;
|
||||||
|
|
||||||
|
station_remove_anqp_watch(anqp_watch);
|
||||||
|
anqp_watch = 0;
|
||||||
|
|
||||||
l_dbus_unregister_interface(dbus_get_bus(), IWD_NETWORK_INTERFACE);
|
l_dbus_unregister_interface(dbus_get_bus(), IWD_NETWORK_INTERFACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user