Re: [PATCH] wpa_supplicant: Use nl80211_send_eapol_data for station

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 06/09/2017 02:21 AM, Wojciech Dubowik wrote:
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.

This seems like it could help my case where keys are set before the 4/4 is
transmitted.  Maybe only set the keys once we get the txstatus back?

Thanks,
Ben


Signed-off-by: Wojciech Dubowik <Wojciech.Dubowik@xxxxxxxxxxx>
---
 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);


--
Ben Greear <greearb@xxxxxxxxxxxxxxx>
Candela Technologies Inc  http://www.candelatech.com

_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap



[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux