Accumulative patch from commit dc013f1e37df3462085cf01a13f0c432f146ad7a

Author: Jouni Malinen <jouni@qca.qualcomm.com>
Date:   Tue Jan 15 12:03:29 2013 +0200
    eapol_test: Remove unnecessary header file inclusion

 - P2P: Send P2P-FIND-STOPPED event in the new continue-search states
 - P2P: Add some more details on Service Query TLV format
 - P2P: Use the same Dialog Token value for every GO Negotiation retry
 - P2P: Publish more connected clients info in Probe Response frames
 - P2P: Fix some memory leaks in p2p_add_device()
 - P2P: Use the same Dialog Token value for every PD retry
 - P2P: Document operating channel selection functions
 - P2P: Always re-select operating channel if not hard coded
 - P2P: Do not allow re-selection of GO channel if forced_freq in use
 - P2P: Set FORCE_FREQ flag as part of p2p_prepare_channel()
 - P2P: Share a single function for GO channel selection
 - P2P: Prefer operating channels where HT40 is possible
 - P2P: Be more careful with wpa_config_update_psk() call
 - P2P: Allow PSK to be used instead of passphrase for persistent GO
 - P2P: Consider age for the P2P scan results
 - Move some P2P offchannel operations to offchannel.c
 - P2P: Add more complete description of p2p_cancel
 - P2P: Allow p2p_cancel to be used to stop p2p_connect-join operation
 - Interworking changes
 - WNM changes
 - WPS changes
 - SAE changes

Change-Id: I38b847d3460066cc58aecbcf67266bfcff1d344e
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index ccc018e..93b740e 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -436,6 +436,50 @@
 #endif /* CONFIG_WPS */
 
 
+#ifdef CONFIG_WNM
+
+static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
+						const char *cmd)
+{
+	u8 addr[ETH_ALEN];
+	u8 buf[1000], *pos;
+	struct ieee80211_mgmt *mgmt;
+	int disassoc_timer;
+
+	if (hwaddr_aton(cmd, addr))
+		return -1;
+	if (cmd[17] != ' ')
+		return -1;
+	disassoc_timer = atoi(cmd + 17);
+
+	os_memset(buf, 0, sizeof(buf));
+	mgmt = (struct ieee80211_mgmt *) buf;
+	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+					   WLAN_FC_STYPE_ACTION);
+	os_memcpy(mgmt->da, addr, ETH_ALEN);
+	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
+	mgmt->u.action.category = WLAN_ACTION_WNM;
+	mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
+	mgmt->u.action.u.bss_tm_req.dialog_token = 1;
+	mgmt->u.action.u.bss_tm_req.req_mode =
+		WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
+	mgmt->u.action.u.bss_tm_req.disassoc_timer =
+		host_to_le16(disassoc_timer);
+	mgmt->u.action.u.bss_tm_req.validity_interval = 0;
+
+	pos = mgmt->u.action.u.bss_tm_req.variable;
+
+	if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+		wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
+			   "Management Request frame");
+		return -1;
+	}
+
+	return 0;
+}
+
+
 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
 					   const char *cmd)
 {
@@ -486,6 +530,8 @@
 	return 0;
 }
 
+#endif /* CONFIG_WNM */
+
 
 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
 					 char *buf, size_t buflen)
@@ -589,20 +635,9 @@
 		pos += ret;
 	}
 
-	if (hapd->conf->wpa && hapd->conf->wpa_group == WPA_CIPHER_CCMP) {
-		ret = os_snprintf(pos, end - pos, "group_cipher=CCMP\n");
-		if (ret < 0 || ret >= end - pos)
-			return pos - buf;
-		pos += ret;
-	} else if (hapd->conf->wpa &&
-		   hapd->conf->wpa_group == WPA_CIPHER_GCMP) {
-		ret = os_snprintf(pos, end - pos, "group_cipher=GCMP\n");
-		if (ret < 0 || ret >= end - pos)
-			return pos - buf;
-		pos += ret;
-	} else if (hapd->conf->wpa &&
-		   hapd->conf->wpa_group == WPA_CIPHER_TKIP) {
-		ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n");
+	if (hapd->conf->wpa) {
+		ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
+				  wpa_cipher_txt(hapd->conf->wpa_group));
 		if (ret < 0 || ret >= end - pos)
 			return pos - buf;
 		pos += ret;
@@ -614,24 +649,11 @@
 			return pos - buf;
 		pos += ret;
 
-		if (hapd->conf->rsn_pairwise & WPA_CIPHER_CCMP) {
-			ret = os_snprintf(pos, end - pos, "CCMP ");
-			if (ret < 0 || ret >= end - pos)
-				return pos - buf;
-			pos += ret;
-		}
-		if (hapd->conf->rsn_pairwise & WPA_CIPHER_GCMP) {
-			ret = os_snprintf(pos, end - pos, "GCMP ");
-			if (ret < 0 || ret >= end - pos)
-				return pos - buf;
-			pos += ret;
-		}
-		if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) {
-			ret = os_snprintf(pos, end - pos, "TKIP ");
-			if (ret < 0 || ret >= end - pos)
-				return pos - buf;
-			pos += ret;
-		}
+		ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
+					" ");
+		if (ret < 0)
+			return pos - buf;
+		pos += ret;
 
 		ret = os_snprintf(pos, end - pos, "\n");
 		if (ret < 0 || ret >= end - pos)
@@ -645,24 +667,11 @@
 			return pos - buf;
 		pos += ret;
 
-		if (hapd->conf->wpa_pairwise & WPA_CIPHER_CCMP) {
-			ret = os_snprintf(pos, end - pos, "CCMP ");
-			if (ret < 0 || ret >= end - pos)
-				return pos - buf;
-			pos += ret;
-		}
-		if (hapd->conf->wpa_pairwise & WPA_CIPHER_GCMP) {
-			ret = os_snprintf(pos, end - pos, "GCMP ");
-			if (ret < 0 || ret >= end - pos)
-				return pos - buf;
-			pos += ret;
-		}
-		if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) {
-			ret = os_snprintf(pos, end - pos, "TKIP ");
-			if (ret < 0 || ret >= end - pos)
-				return pos - buf;
-			pos += ret;
-		}
+		ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
+					" ");
+		if (ret < 0)
+			return pos - buf;
+		pos += ret;
 
 		ret = os_snprintf(pos, end - pos, "\n");
 		if (ret < 0 || ret >= end - pos)
@@ -906,9 +915,14 @@
 			hapd, buf + 14, reply, reply_size);
 #endif /* CONFIG_WPS_NFC */
 #endif /* CONFIG_WPS */
+#ifdef CONFIG_WNM
+	} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
+		if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
+			reply_len = -1;
 	} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
 		if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
 			reply_len = -1;
+#endif /* CONFIG_WNM */
 	} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
 		reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
 							  reply_size);
@@ -997,12 +1011,27 @@
 	}
 
 	if (hapd->conf->ctrl_interface_gid_set &&
-	    chown(hapd->conf->ctrl_interface, 0,
+	    chown(hapd->conf->ctrl_interface, -1,
 		  hapd->conf->ctrl_interface_gid) < 0) {
 		perror("chown[ctrl_interface]");
 		return -1;
 	}
 
+#ifdef ANDROID
+	/*
+	 * Android is using umask 0077 which would leave the control interface
+	 * directory without group access. This breaks things since Wi-Fi
+	 * framework assumes that this directory can be accessed by other
+	 * applications in the wifi group. Fix this by adding group access even
+	 * if umask value would prevent this.
+	 */
+	if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
+		wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
+			   strerror(errno));
+		/* Try to continue anyway */
+	}
+#endif /* ANDROID */
+
 	if (os_strlen(hapd->conf->ctrl_interface) + 1 +
 	    os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
 		goto fail;
@@ -1055,7 +1084,7 @@
 	}
 
 	if (hapd->conf->ctrl_interface_gid_set &&
-	    chown(fname, 0, hapd->conf->ctrl_interface_gid) < 0) {
+	    chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
 		perror("chown[ctrl_interface/ifname]");
 		goto fail;
 	}