Cumulative patch from commit f2d6c17aa0f9107a0e8092238b849461447cdd21

f2d6c17 nl80211: Support network hierarchy of a master interface under bridge
f85399f Reserve QCA vendor specific nl80211 commands 116..118
3bd5886 hostapd: Handle running out of DFS channels
cc1af6f FST: Fix session setup failure with peer without MB IE
dfe0745 P2P: Add optional op_class argument to P2P_SET listen_channel
e4a1469 P2P: Adjust service discovery maximum fragment size for 60 GHz
c7fb678 D-Bus: Add association response status code property for failure cases
2940bf6 hostapd: Use ifname of the current context in debug messages
6448e06 hostapd: Allow use of driver-generated interface addresses
f2accfe AP: Save EAPOL received before Association Response ACK
1307301 wpaspy: Add support for TERMINATE command
a2c88a8 wpaspy: Add support for UDP connection
3e67171 hostapd: Add global TERMINATE command
618f5d0 hostapd: Add INTERFACES ctrl_iface command
180e5b9 hostapd: Update ctrl_interface for UDP to include the selected port
56e2fc2 wpa_supplicant: Add ctrl parameter to INTERFACES command
b9066c6 hostapd: Allow UDP ctrl_iface configuration to set the UDP port
56885ee hostapd: Add UDP support for ctrl_iface
acf57fa ctrl_iface_common: Use sockaddr_storage instead of sockaddr_un
89b781b hostapd: Use common functions for ctrl_iface
1a2124c wpa_supplicant: Use common functions for ctrl_iface
ca974ae Add common ctrl_iface files
d60886c wpa_supplicant: Add monitor support for global UDP ctrl_iface
f0e5d3b wpa_supplicant: Share attach/detach/send UDP ctrl_iface functions
db7fb43 wpa_supplicant: Allow UDP ctrl_iface configuration to set the UDP port
3598695 P2P: Update peer WFD IE from PD Response and GO Negotiation Response
c69ef1d P2P: Respect p2p_ignore_shared_freq on p2p_group_add
4115b05 P2P: Fix shared freq print in wpas_p2p_init_go_params()

Change-Id: Id939064b95210ee1a195f7a9f7c069da520d77ca
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index c774d5c..42b0299 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -861,6 +861,29 @@
 }
 
 
+static void ieee802_1x_save_eapol(struct sta_info *sta, const u8 *buf,
+				  size_t len)
+{
+	if (sta->pending_eapol_rx) {
+		wpabuf_free(sta->pending_eapol_rx->buf);
+	} else {
+		sta->pending_eapol_rx =
+			os_malloc(sizeof(*sta->pending_eapol_rx));
+		if (!sta->pending_eapol_rx)
+			return;
+	}
+
+	sta->pending_eapol_rx->buf = wpabuf_alloc_copy(buf, len);
+	if (!sta->pending_eapol_rx->buf) {
+		os_free(sta->pending_eapol_rx);
+		sta->pending_eapol_rx = NULL;
+		return;
+	}
+
+	os_get_reltime(&sta->pending_eapol_rx->rx_time);
+}
+
+
 /**
  * ieee802_1x_receive - Process the EAPOL frames from the Supplicant
  * @hapd: hostapd BSS data
@@ -891,6 +914,13 @@
 		     !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) {
 		wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not "
 			   "associated/Pre-authenticating STA");
+
+		if (sta && (sta->flags & WLAN_STA_AUTH)) {
+			wpa_printf(MSG_DEBUG, "Saving EAPOL frame from " MACSTR
+				   " for later use", MAC2STR(sta->addr));
+			ieee802_1x_save_eapol(sta, buf, len);
+		}
+
 		return;
 	}
 
@@ -1183,6 +1213,12 @@
 	eloop_cancel_timeout(ieee802_1x_wnm_notif_send, hapd, sta);
 #endif /* CONFIG_HS20 */
 
+	if (sta->pending_eapol_rx) {
+		wpabuf_free(sta->pending_eapol_rx->buf);
+		os_free(sta->pending_eapol_rx);
+		sta->pending_eapol_rx = NULL;
+	}
+
 	if (sm == NULL)
 		return;