Cumulative patch from commit commit add7add09d72c3294c63a113635d69b766acf504
add7add IBSS RSN: Add a timeout for Authentication frame exchange
c1c0b35 P2P: Postpone concurrent scans when waiting for first client as GO
6fb7b58 IBSS RSN: Work around Data RX vs. Authentication RX race condition
Bug: 10513949
Change-Id: Ic4d77c94a5b6e4729cd798f7b033e3ea5b2481cc
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index b694bde..3e5d412 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -10,6 +10,7 @@
#include "common.h"
#include "common/wpa_ctrl.h"
+#include "utils/eloop.h"
#include "l2_packet/l2_packet.h"
#include "rsn_supp/wpa.h"
#include "rsn_supp/wpa_ie.h"
@@ -20,6 +21,9 @@
#include "ibss_rsn.h"
+static void ibss_rsn_auth_timeout(void *eloop_ctx, void *timeout_ctx);
+
+
static struct ibss_rsn_peer * ibss_rsn_get_peer(struct ibss_rsn *ibss_rsn,
const u8 *addr)
{
@@ -34,6 +38,7 @@
static void ibss_rsn_free(struct ibss_rsn_peer *peer)
{
+ eloop_cancel_timeout(ibss_rsn_auth_timeout, peer, NULL);
wpa_auth_sta_deinit(peer->auth);
wpa_sm_deinit(peer->supp);
os_free(peer);
@@ -543,6 +548,23 @@
}
+static void ibss_rsn_auth_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct ibss_rsn_peer *peer = eloop_ctx;
+
+ /*
+ * Assume peer does not support Authentication exchange or the frame was
+ * lost somewhere - start EAPOL Authenticator.
+ */
+ wpa_printf(MSG_DEBUG,
+ "RSN: Timeout on waiting Authentication frame response from "
+ MACSTR " - start authenticator", MAC2STR(peer->addr));
+
+ peer->authentication_status |= IBSS_RSN_AUTH_BY_US;
+ ibss_rsn_auth_init(peer->ibss_rsn, peer);
+}
+
+
int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr)
{
struct ibss_rsn_peer *peer;
@@ -566,6 +588,9 @@
*/
peer->authentication_status |= IBSS_RSN_AUTH_BY_US;
return ibss_rsn_auth_init(ibss_rsn, peer);
+ } else {
+ os_get_time(&peer->own_auth_tx);
+ eloop_register_timeout(1, 0, ibss_rsn_auth_timeout, peer, NULL);
}
return 0;
@@ -807,6 +832,16 @@
if (peer &&
peer->authentication_status & IBSS_RSN_AUTH_EAPOL_BY_PEER) {
+ if (peer->own_auth_tx.sec) {
+ struct os_time now, diff;
+ os_get_time(&now);
+ os_time_sub(&now, &peer->own_auth_tx, &diff);
+ if (diff.sec == 0 && diff.usec < 500000) {
+ wpa_printf(MSG_DEBUG, "RSN: Skip IBSS reinit since only %u usec from own Auth frame TX",
+ (int) diff.usec);
+ goto skip_reinit;
+ }
+ }
/*
* A peer sent us an Authentication frame even though it already
* started an EAPOL session. We should reinit state machines
@@ -829,6 +864,7 @@
MAC2STR(addr));
}
+skip_reinit:
/* reply with an Authentication frame now, before sending an EAPOL */
ibss_rsn_send_auth(ibss_rsn, addr, 2);
/* no need to start another AUTH challenge in the other way.. */
@@ -869,7 +905,8 @@
}
/* authentication has been completed */
- wpa_printf(MSG_DEBUG, "RSN: IBSS Auth completed with "MACSTR,
+ eloop_cancel_timeout(ibss_rsn_auth_timeout, peer, NULL);
+ wpa_printf(MSG_DEBUG, "RSN: IBSS Auth completed with " MACSTR,
MAC2STR(header->sa));
ibss_rsn_peer_authenticated(ibss_rsn, peer,
IBSS_RSN_AUTH_BY_US);
diff --git a/wpa_supplicant/ibss_rsn.h b/wpa_supplicant/ibss_rsn.h
index 6b89f7a..3089283 100644
--- a/wpa_supplicant/ibss_rsn.h
+++ b/wpa_supplicant/ibss_rsn.h
@@ -39,6 +39,8 @@
struct wpa_state_machine *auth;
int authentication_status;
+
+ struct os_time own_auth_tx;
};
struct ibss_rsn {
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 0827f35..239e608 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -61,6 +61,16 @@
#define P2P_MAX_INITIAL_CONN_WAIT 10
#endif /* P2P_MAX_INITIAL_CONN_WAIT */
+#ifndef P2P_MAX_INITIAL_CONN_WAIT_GO
+/*
+ * How many seconds to wait for initial 4-way handshake to get completed after
+ * WPS provisioning step on the GO. This controls the extra time the P2P
+ * operation is considered to be in progress (e.g., to delay other scans) after
+ * WPS provisioning has been completed on the GO during group formation.
+ */
+#define P2P_MAX_INITIAL_CONN_WAIT_GO 10
+#endif /* P2P_MAX_INITIAL_CONN_WAIT_GO */
+
#ifndef P2P_CONCURRENT_SEARCH_DELAY
#define P2P_CONCURRENT_SEARCH_DELAY 500
#endif /* P2P_CONCURRENT_SEARCH_DELAY */
@@ -792,8 +802,10 @@
ssid, go_dev_addr);
if (network_id < 0 && ssid)
network_id = ssid->id;
- if (!client)
+ if (!client) {
wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0);
+ os_get_time(&wpa_s->global->p2p_go_wait_client);
+ }
}
@@ -5823,6 +5835,19 @@
}
}
+ if (!ret && wpa_s->global->p2p_go_wait_client.sec) {
+ struct os_time now;
+ os_get_time(&now);
+ if (now.sec > wpa_s->global->p2p_go_wait_client.sec +
+ P2P_MAX_INITIAL_CONN_WAIT_GO) {
+ /* Wait for the first client has expired */
+ wpa_s->global->p2p_go_wait_client.sec = 0;
+ } else {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Waiting for initial client connection during group formation");
+ ret = 1;
+ }
+ }
+
return ret;
}
@@ -5882,6 +5907,7 @@
void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
const u8 *addr)
{
+ wpa_s->global->p2p_go_wait_client.sec = 0;
if (addr == NULL)
return;
wpas_p2p_add_persistent_group_client(wpa_s, addr);
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 0858bbc..604997e 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -252,6 +252,7 @@
struct wpa_supplicant *p2p_group_formation;
struct wpa_supplicant *p2p_invite_group;
u8 p2p_dev_addr[ETH_ALEN];
+ struct os_time p2p_go_wait_client;
struct dl_list p2p_srv_bonjour; /* struct p2p_srv_bonjour */
struct dl_list p2p_srv_upnp; /* struct p2p_srv_upnp */
int p2p_disabled;