aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Prestwood <prestwoj@gmail.com>2020-06-12 12:14:12 -0700
committerDenis Kenzior <denkenz@gmail.com>2020-06-12 15:04:31 -0500
commit248190b0ed42d99a4ddc05bd6fa5da455795cc2b (patch)
treeead0b73055776611123f1b4c62c4ca5228e9633c
parent60e2c4647c74c65bb6b037bcc9c611224ee2bfb3 (diff)
downloadiwd-248190b0ed42d99a4ddc05bd6fa5da455795cc2b.tar.gz
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.
-rw-r--r--src/network.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/network.c b/src/network.c
index 170db3e5f..65a743781 100644
--- a/src/network.c
+++ b/src/network.c
@@ -52,6 +52,7 @@
#include "src/util.h"
static uint32_t known_networks_watch;
+static uint32_t anqp_watch;
struct network {
char ssid[33];
@@ -72,7 +73,10 @@ struct network {
bool update_psk:1; /* Whether PSK should be written to storage */
bool ask_passphrase:1; /* Whether we should force-ask agent */
bool is_hs20:1;
+ bool anqp_pending:1; /* Set if there is a pending ANQP request */
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)
@@ -521,6 +525,10 @@ int network_autoconnect(struct network *network, struct scan_bss *bss)
bool is_rsn;
int ret;
+ /* already waiting for an agent request, connect in progress */
+ if (network->agent_request)
+ return -EALREADY;
+
switch (security) {
case SECURITY_NONE:
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);
return NULL;
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))
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)
{
l_dbus_interface_method(interface, "Connect", 0,
@@ -1517,6 +1570,8 @@ static int network_init(void)
known_networks_watch =
known_networks_watch_add(known_networks_changed, NULL, NULL);
+ anqp_watch = station_add_anqp_watch(anqp_watch_changed, NULL, NULL);
+
return 0;
}
@@ -1525,6 +1580,9 @@ static void network_exit(void)
known_networks_watch_remove(known_networks_watch);
known_networks_watch = 0;
+ station_remove_anqp_watch(anqp_watch);
+ anqp_watch = 0;
+
l_dbus_unregister_interface(dbus_get_bus(), IWD_NETWORK_INTERFACE);
}