Accumulative patch from commit d5b559b6418c2bd09663e0d09e93a6592357fdce

d5b559b WNM: Add disassociation timeout processing for ESS_DISASSOC
f65f539 GAS: Reduce query timeout to two seconds
7a56af5 GAS: Assign new dialog token even if previous one is free
9e1ecab GAS: Ignore replays if previous frag_id without dropping GAS session
fa7ae95 Add test code for fetching the last configured GTK
576bce9 P2P: Direct global ctrl_iface commands automatically for P2P
c4bf83a P2P: No duplicate AP-STA-CONNECTED/DISCONNECTED as global event
7793c95 Clean up AP-STA-CONNECTED/DISCONNECTED prints
92c4465 P2P: Mark P2P events global (not specific to interface)
ed496f1 P2P: Clean up debug prints
710ae9a P2P: Move p2p_find stopped event message into p2p_supplicant.c
47bfe49 Add wpa_msg_global() for global events
214e428 Allow global ctrl_iface monitors
89c7ac5 wpa_cli: Set buffer length the same as in wpa_supplicant_ctrl_iface_process()
faf9a85 Add band option (2.4 vs. 5) for filtering scans
b83b1b2 Android: Clarify keystore include directories
6f1127c Android: Add a top level Android.mk
d2a9e2c Abstract and Android sockets for global ctrl_iface
6fd5cea wpa_cli: Allow global interface to be used in interactive mode
2925756 wpa_supplicant: Add -G argument to specify global ctrl group
cf3bebf Allow global ctrl_iface to be used for per-interface commands
058c863 FT RRB: Fix a memory leak on error path

Change-Id: I32a4afb43894167a30c4b0df18fd4846a2945c7c
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 2153329..7fc520c 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -537,14 +537,24 @@
 					   const char *cmd)
 {
 	u8 addr[ETH_ALEN];
-	const char *url;
+	const char *url, *timerstr;
 	u8 buf[1000], *pos;
 	struct ieee80211_mgmt *mgmt;
 	size_t url_len;
+	int disassoc_timer;
 
 	if (hwaddr_aton(cmd, addr))
 		return -1;
-	url = cmd + 17;
+
+	timerstr = cmd + 17;
+	if (*timerstr != ' ')
+		return -1;
+	timerstr++;
+	disassoc_timer = atoi(timerstr);
+	if (disassoc_timer < 0 || disassoc_timer > 65535)
+		return -1;
+
+	url = os_strchr(timerstr, ' ');
 	if (*url != ' ')
 		return -1;
 	url++;
@@ -564,8 +574,9 @@
 	mgmt->u.action.u.bss_tm_req.dialog_token = 1;
 	mgmt->u.action.u.bss_tm_req.req_mode =
 		WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
-	mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0);
-	mgmt->u.action.u.bss_tm_req.validity_interval = 0;
+	mgmt->u.action.u.bss_tm_req.disassoc_timer =
+		host_to_le16(disassoc_timer);
+	mgmt->u.action.u.bss_tm_req.validity_interval = 0x01;
 
 	pos = mgmt->u.action.u.bss_tm_req.variable;
 
@@ -580,6 +591,25 @@
 		return -1;
 	}
 
+	/* send disassociation frame after time-out */
+	if (disassoc_timer) {
+		struct sta_info *sta;
+
+		sta = ap_get_sta(hapd, addr);
+		if (sta == NULL) {
+			wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
+				   "for ESS disassociation imminent message",
+				   MAC2STR(addr));
+			return -1;
+		}
+
+		sta->timeout_next = STA_DISASSOC_FROM_CLI;
+		eloop_cancel_timeout(ap_handle_timer, hapd, sta);
+		eloop_register_timeout(disassoc_timer / 1000,
+				       disassoc_timer % 1000 * 1000,
+				       ap_handle_timer, hapd, sta);
+	}
+
 	return 0;
 }
 
@@ -1035,7 +1065,7 @@
 }
 
 
-static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
+static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global,
 				      const char *txt, size_t len)
 {
 	struct hostapd_data *hapd = ctx;
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 1537275..7071594 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -593,14 +593,14 @@
 	char buf[300];
 	int res;
 
-	if (argc < 2) {
-		printf("Invalid 'ess_disassoc' command - two arguments (STA "
-		       "addr and URL) are needed\n");
+	if (argc < 3) {
+		printf("Invalid 'ess_disassoc' command - three arguments (STA "
+		       "addr, disassoc timer, and URL) are needed\n");
 		return -1;
 	}
 
-	res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s",
-			  argv[0], argv[1]);
+	res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
+			  argv[0], argv[1], argv[2]);
 	if (res < 0 || res >= (int) sizeof(buf))
 		return -1;
 	return wpa_ctrl_command(ctrl, buf);