Cumulative patch from commit 8615bdfac90174c3730ae5e6607b85f8bbec847e

8615bdf Increase global ctrl_iface buffer to same size as per-interface
c5a64e2 GAS client: Use Protected Dual of Public Action frames with PMF
5ce00d0 GAS server: Add support for Protected Dual of Public Action frames
e24fe94 Add definitions for Protected Dual of Public Action frames
7b2c42f hostapd: Fix PMF robust Action frame processing rules
ea6e040 Clear more configuration parameters to default on FLUSH
cf70d29 wpa_supplicant: Schedule PNO on completion of ongoing sched_scan
080cc44 nl80211: Fix sizeof check in vendor command/event handling
a487b35 hostapd: Fix segmentation fault when calling hostapd_cli all_sta
a6cff8b wpa_supplicant: Fix seg fault in wpas_ctrl_radio_work_flush() in error case
f62a3c2 P2P: Clone dtim_period to a new interface
88a0bca Update copyright years in the manpages
32185f5 Sync manpages and command-line options
b948e78 Add manpage for eapol_test
36bd29e wpa_supplicant: Fix usage text based on build options
dcdd383 P2P: Reduce peer expiration age to 60 sec and allow customization
dd27185 Skip normal scan when PNO is already in progress
a2d6365 P2P: Extend the listen time based on the active concurrent session

Change-Id: Iad81dc478319e59d8cfb673e2988d8bd3099b313
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c
index 8349c4d..b5fb7df 100644
--- a/src/ap/gas_serv.c
+++ b/src/ap/gas_serv.c
@@ -1,6 +1,6 @@
 /*
  * Generic advertisement service (GAS) server
- * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
+ * Copyright (c) 2011-2014, Qualcomm Atheros, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -19,6 +19,13 @@
 #include "gas_serv.h"
 
 
+static void convert_to_protected_dual(struct wpabuf *msg)
+{
+	u8 *categ = wpabuf_mhead_u8(msg);
+	*categ = WLAN_ACTION_PROTECTED_DUAL;
+}
+
+
 static struct gas_dialog_info *
 gas_dialog_create(struct hostapd_data *hapd, const u8 *addr, u8 dialog_token)
 {
@@ -774,7 +781,7 @@
 
 static void gas_serv_req_local_processing(struct hostapd_data *hapd,
 					  const u8 *sa, u8 dialog_token,
-					  struct anqp_query_info *qi)
+					  struct anqp_query_info *qi, int prot)
 {
 	struct wpabuf *buf, *tx_buf;
 
@@ -806,6 +813,7 @@
 			wpabuf_free(buf);
 			return;
 		}
+		di->prot = prot;
 		di->sd_resp = buf;
 		di->sd_resp_pos = 0;
 		tx_buf = gas_anqp_build_initial_resp_buf(
@@ -819,7 +827,8 @@
 	}
 	if (!tx_buf)
 		return;
-
+	if (prot)
+		convert_to_protected_dual(tx_buf);
 	hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
 				wpabuf_head(tx_buf), wpabuf_len(tx_buf));
 	wpabuf_free(tx_buf);
@@ -828,7 +837,7 @@
 
 static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd,
 					const u8 *sa,
-					const u8 *data, size_t len)
+					const u8 *data, size_t len, int prot)
 {
 	const u8 *pos = data;
 	const u8 *end = data + len;
@@ -878,6 +887,8 @@
 			return;
 		wpabuf_put_data(buf, adv_proto, 2 + slen);
 		wpabuf_put_le16(buf, 0); /* Query Response Length */
+		if (prot)
+			convert_to_protected_dual(buf);
 		hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
 					wpabuf_head(buf), wpabuf_len(buf));
 		wpabuf_free(buf);
@@ -929,7 +940,7 @@
 		pos += elen;
 	}
 
-	gas_serv_req_local_processing(hapd, sa, dialog_token, &qi);
+	gas_serv_req_local_processing(hapd, sa, dialog_token, &qi, prot);
 }
 
 
@@ -975,6 +986,8 @@
 		if (tx_buf) {
 			wpa_msg(hapd->msg_ctx, MSG_DEBUG,
 				"GAS: Tx GAS Initial Resp (comeback = 10TU)");
+			if (dialog->prot)
+				convert_to_protected_dual(tx_buf);
 			hostapd_drv_send_action(hapd, hapd->iface->freq, 0,
 						dst,
 						wpabuf_head(tx_buf),
@@ -1012,6 +1025,8 @@
 		dialog->sd_frag_id, (int) frag_len);
 	dialog->sd_frag_id++;
 
+	if (dialog->prot)
+		convert_to_protected_dual(tx_buf);
 	hostapd_drv_send_action(hapd, hapd->iface->freq, 0, dst,
 				wpabuf_head(tx_buf), wpabuf_len(tx_buf));
 	wpabuf_free(tx_buf);
@@ -1022,7 +1037,7 @@
 
 static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd,
 					 const u8 *sa,
-					 const u8 *data, size_t len)
+					 const u8 *data, size_t len, int prot)
 {
 	struct gas_dialog_info *dialog;
 	struct wpabuf *buf, *tx_buf;
@@ -1120,6 +1135,8 @@
 	}
 
 send_resp:
+	if (prot)
+		convert_to_protected_dual(tx_buf);
 	hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
 				wpabuf_head(tx_buf), wpabuf_len(tx_buf));
 	wpabuf_free(tx_buf);
@@ -1137,22 +1154,30 @@
 	const struct ieee80211_mgmt *mgmt;
 	size_t hdr_len;
 	const u8 *sa, *data;
+	int prot;
 
 	mgmt = (const struct ieee80211_mgmt *) buf;
 	hdr_len = (const u8 *) &mgmt->u.action.u.vs_public_action.action - buf;
 	if (hdr_len > len)
 		return;
-	if (mgmt->u.action.category != WLAN_ACTION_PUBLIC)
+	if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
+	    mgmt->u.action.category != WLAN_ACTION_PROTECTED_DUAL)
 		return;
+	/*
+	 * Note: Public Action and Protected Dual of Public Action frames share
+	 * the same payload structure, so it is fine to use definitions of
+	 * Public Action frames to process both.
+	 */
+	prot = mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL;
 	sa = mgmt->sa;
 	len -= hdr_len;
 	data = &mgmt->u.action.u.public_action.action;
 	switch (data[0]) {
 	case WLAN_PA_GAS_INITIAL_REQ:
-		gas_serv_rx_gas_initial_req(hapd, sa, data + 1, len - 1);
+		gas_serv_rx_gas_initial_req(hapd, sa, data + 1, len - 1, prot);
 		break;
 	case WLAN_PA_GAS_COMEBACK_REQ:
-		gas_serv_rx_gas_comeback_req(hapd, sa, data + 1, len - 1);
+		gas_serv_rx_gas_comeback_req(hapd, sa, data + 1, len - 1, prot);
 		break;
 	}
 }