[PATCH] wpa_supplicant: Use nl80211_send_eapol_data for station
Wojciech Dubowik
Wojciech.Dubowik at neratec.com
Fri Jun 9 02:21:30 PDT 2017
Supplicant is using generic L2 send function for EAPOL
messages which doesn't give back status whether frame has been
acked or not. It can lead to wrong wpa states when EAPOL 4/4
is lost i.e. client is in connected state but keys aren't
established on AP side.
Fix that by using nl80211_send_eapol_data as for AP side
and check in conneced state that 4/4 EAPOL has been acked.
Signed-off-by: Wojciech Dubowik <Wojciech.Dubowik at neratec.com>
---
src/drivers/driver.h | 12 ++++++++++++
src/drivers/driver_nl80211.c | 11 +++++++++++
wpa_supplicant/driver_i.h | 10 ++++++++++
wpa_supplicant/events.c | 17 ++++++++++++++++-
wpa_supplicant/wpas_glue.c | 6 ++++++
5 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 9587d06..b73679d 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -2665,6 +2665,18 @@ struct wpa_driver_ops {
const u8 *own_addr, u32 flags);
/**
+ * send_eapol - Send an EAPOL packet (STA only)
+ * @priv: private driver interface data
+ * @addr: Destination MAC address
+ * @data: EAPOL packet starting with IEEE 802.1X header
+ * @data_len: Length of the EAPOL packet in octets
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+ int (*send_eapol)(void *priv, const u8 *addr, const u8 *data,
+ size_t data_len);
+
+ /**
* sta_deauth - Deauthenticate a station (AP only)
* @priv: Private driver interface data
* @own_addr: Source address and BSSID for the Deauthentication frame
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 1b7be39..60185dd 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -4844,6 +4844,16 @@ static int wpa_driver_nl80211_hapd_send_eapol(
return res;
}
+static int wpa_driver_nl80211_send_eapol(
+ void *priv, const u8 *addr, const u8 *data,
+ size_t data_len)
+{
+ struct i802_bss *bss = priv;
+
+ return nl80211_send_eapol_data(bss, addr, data, data_len);
+}
+
+
static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
unsigned int total_flags,
@@ -10186,6 +10196,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.sta_add = wpa_driver_nl80211_sta_add,
.sta_remove = driver_nl80211_sta_remove,
.hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol,
+ .send_eapol = wpa_driver_nl80211_send_eapol,
.sta_set_flags = wpa_driver_nl80211_sta_set_flags,
.hapd_init = i802_init,
.hapd_deinit = i802_deinit,
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index fa2296b..e0a177c 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -349,6 +349,16 @@ static inline int wpa_drv_hapd_send_eapol(struct wpa_supplicant *wpa_s,
return -1;
}
+static inline int wpa_drv_send_eapol(struct wpa_supplicant *wpa_s,
+ const u8 *addr, const u8 *data,
+ size_t data_len)
+{
+ if (wpa_s->driver->hapd_send_eapol)
+ return wpa_s->driver->send_eapol(wpa_s->drv_priv, addr,
+ data, data_len);
+ return -1;
+}
+
static inline int wpa_drv_sta_set_flags(struct wpa_supplicant *wpa_s,
const u8 *addr, int total_flags,
int flags_or, int flags_and)
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 3a2ec64..af9bf2a 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -3966,13 +3966,28 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
}
#endif /* CONFIG_AP */
break;
-#ifdef CONFIG_AP
case EVENT_EAPOL_TX_STATUS:
+#ifdef CONFIG_AP
ap_eapol_tx_status(wpa_s, data->eapol_tx_status.dst,
data->eapol_tx_status.data,
data->eapol_tx_status.data_len,
data->eapol_tx_status.ack);
+#else
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "EAPOL_TX_STATUS: ACK(%d)",
+ data->eapol_tx_status.ack);
+ if (!data->eapol_tx_status.ack &&
+ wpa_s->wpa_state == WPA_COMPLETED) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "EAPOL 4/4 Not acked, disconnecting");
+ wpa_s->own_disconnect_req = 1;
+ wpa_supplicant_deauthenticate(
+ wpa_s, WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
+
+ }
+#endif
break;
+#ifdef CONFIG_AP
case EVENT_DRIVER_CLIENT_POLL_OK:
ap_client_poll_ok(wpa_s, data->client_poll.addr);
break;
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index ae246f9..da81ac0 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -97,6 +97,7 @@ static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type,
static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
u16 proto, const u8 *buf, size_t len)
{
+ int ret;
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_s->ext_eapol_frame_io && proto == ETH_P_EAPOL) {
size_t hex_len = 2 * len + 1;
@@ -111,6 +112,11 @@ static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
return 0;
}
#endif /* CONFIG_TESTING_OPTIONS */
+ ret = wpa_drv_send_eapol(wpa_s, dest, buf, len);
+ if (ret < 0)
+ wpa_printf(MSG_DEBUG, " (%d)", ret);
+ else
+ return ret;
if (wpa_s->l2) {
return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
--
2.7.4
More information about the Hostap
mailing list