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/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 3fb9e04..8c0cbab 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -86,6 +86,9 @@
 {
 	int len, res, ret, i;
 
+	if (!sta)
+		return 0;
+
 	len = 0;
 	ret = os_snprintf(buf + len, buflen - len, MACSTR "\nflags=",
 			  MAC2STR(sta->addr));
@@ -203,7 +206,11 @@
 		if (ret < 0 || (size_t) ret >= buflen)
 			return 0;
 		return ret;
-	}		
+	}
+
+	if (!sta->next)
+		return 0;
+
 	return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
 }
 
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;
 	}
 }
diff --git a/src/ap/gas_serv.h b/src/ap/gas_serv.h
index 4213cf6..74739fe 100644
--- a/src/ap/gas_serv.h
+++ b/src/ap/gas_serv.h
@@ -50,6 +50,7 @@
 	size_t sd_resp_pos; /* Offset in sd_resp */
 	u8 sd_frag_id;
 	u16 comeback_delay;
+	int prot; /* whether Protected Dual of Public Action frame is used */
 
 	unsigned int requested;
 	unsigned int received;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 1e3693d..dee3c7a 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1588,8 +1588,8 @@
 
 #ifdef CONFIG_IEEE80211W
 	if (sta && (sta->flags & WLAN_STA_MFP) &&
-	    !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP) &&
-	      robust_action_frame(mgmt->u.action.category))) {
+	    !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP)) &&
+	    robust_action_frame(mgmt->u.action.category)) {
 		hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_DEBUG,
 			       "Dropped unprotected Robust Action frame from "
@@ -1619,6 +1619,7 @@
 		return 1;
 #endif /* CONFIG_WNM */
 	case WLAN_ACTION_PUBLIC:
+	case WLAN_ACTION_PROTECTED_DUAL:
 		if (hapd->public_action_cb) {
 			hapd->public_action_cb(hapd->public_action_cb_ctx,
 					       (u8 *) mgmt, len,
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 12dc83e..592ae54 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -271,6 +271,7 @@
 #define WLAN_ACTION_FT 6
 #define WLAN_ACTION_HT 7
 #define WLAN_ACTION_SA_QUERY 8
+#define WLAN_ACTION_PROTECTED_DUAL 9
 #define WLAN_ACTION_WNM 10
 #define WLAN_ACTION_UNPROTECTED_WNM 11
 #define WLAN_ACTION_TDLS 12
@@ -286,6 +287,19 @@
 #define WLAN_PA_GAS_COMEBACK_RESP 13
 #define WLAN_TDLS_DISCOVERY_RESPONSE 14
 
+/* Protected Dual of Public Action frames */
+#define WLAN_PROT_DSE_ENABLEMENT 1
+#define WLAN_PROT_DSE_DEENABLEMENT 2
+#define WLAN_PROT_EXT_CSA 4
+#define WLAN_PROT_MEASUREMENT_REQ 5
+#define WLAN_PROT_MEASUREMENT_REPORT 6
+#define WLAN_PROT_DSE_POWER_CONSTRAINT 8
+#define WLAN_PROT_VENDOR_SPECIFIC 9
+#define WLAN_PROT_GAS_INITIAL_REQ 10
+#define WLAN_PROT_GAS_INITIAL_RESP 11
+#define WLAN_PROT_GAS_COMEBACK_REQ 12
+#define WLAN_PROT_GAS_COMEBACK_RESP 13
+
 /* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
 #define WLAN_SA_QUERY_REQUEST 0
 #define WLAN_SA_QUERY_RESPONSE 1
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 0b8eed5..b5bf368 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -3584,7 +3584,7 @@
 
 		nla_for_each_nested(nl, tb[NL80211_ATTR_VENDOR_DATA], rem) {
 			struct nl80211_vendor_cmd_info *vinfo;
-			if (nla_len(nl) != sizeof(vinfo)) {
+			if (nla_len(nl) != sizeof(*vinfo)) {
 				wpa_printf(MSG_DEBUG, "nl80211: Unexpected vendor data info");
 				continue;
 			}
@@ -3600,7 +3600,7 @@
 
 		nla_for_each_nested(nl, tb[NL80211_ATTR_VENDOR_EVENTS], rem) {
 			struct nl80211_vendor_cmd_info *vinfo;
-			if (nla_len(nl) != sizeof(vinfo)) {
+			if (nla_len(nl) != sizeof(*vinfo)) {
 				wpa_printf(MSG_DEBUG, "nl80211: Unexpected vendor data info");
 				continue;
 			}
@@ -4216,6 +4216,18 @@
 	/* GAS Comeback Response */
 	if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
 		ret = -1;
+	/* Protected GAS Initial Request */
+	if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0a", 2) < 0)
+		ret = -1;
+	/* Protected GAS Initial Response */
+	if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0b", 2) < 0)
+		ret = -1;
+	/* Protected GAS Comeback Request */
+	if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0c", 2) < 0)
+		ret = -1;
+	/* Protected GAS Comeback Response */
+	if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0d", 2) < 0)
+		ret = -1;
 #endif /* CONFIG_P2P || CONFIG_INTERWORKING */
 #ifdef CONFIG_P2P
 	/* P2P Public Action */
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index f2aa971..8aabfc0 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -43,7 +43,7 @@
  */
 #ifndef P2P_PEER_EXPIRATION_AGE
 #define P2P_PEER_EXPIRATION_AGE 60
-#endif
+#endif /* P2P_PEER_EXPIRATION_AGE */
 
 #define P2P_PEER_EXPIRATION_INTERVAL (P2P_PEER_EXPIRATION_AGE / 2)
 
@@ -3151,13 +3151,13 @@
 
 static void p2p_timeout_wait_peer_connect(struct p2p_data *p2p)
 {
-	/*
-	 * TODO: could remain constantly in Listen state for some time if there
-	 * are no other concurrent uses for the radio. For now, go to listen
-	 * state once per second to give other uses a chance to use the radio.
-	 */
 	p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
-	p2p_set_timeout(p2p, 0, 500000);
+
+	if (p2p->cfg->is_concurrent_session_active &&
+	    p2p->cfg->is_concurrent_session_active(p2p->cfg->cb_ctx))
+		p2p_set_timeout(p2p, 0, 500000);
+	else
+		p2p_set_timeout(p2p, 0, 200000);
 }
 
 
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 25a91e7..2ce6ea6 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -789,6 +789,15 @@
 	 */
 	void (*presence_resp)(void *ctx, const u8 *src, u8 status,
 			      const u8 *noa, size_t noa_len);
+
+	/**
+	 * is_concurrent_session_active - Check whether concurrent session is
+	 * active on other virtual interfaces
+	 * @ctx: Callback context from cb_ctx
+	 * Returns: 1 if concurrent session is active on other virtual interface
+	 * or 0 if not.
+	 */
+	int (*is_concurrent_session_active)(void *ctx);
 };
 
 
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index ea4e6bb..5f69389 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -360,6 +360,8 @@
 	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)
+		return;
 	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
 			   mgmt->u.action.category,
 			   &mgmt->u.action.u.vs_public_action.action,
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index f7ee6e3..68157d2 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -54,7 +54,7 @@
 	struct wpa_ssid *ssid;
 	struct wpa_driver_scan_params params;
 
-	if (wpa_s->pno)
+	if (wpa_s->pno || wpa_s->pno_sched_pending)
 		return 0;
 
 	if ((wpa_s->wpa_state > WPA_SCANNING) &&
@@ -64,8 +64,14 @@
 	}
 
 	if (wpa_s->wpa_state == WPA_SCANNING) {
-		wpa_supplicant_cancel_sched_scan(wpa_s);
 		wpa_supplicant_cancel_scan(wpa_s);
+		if (wpa_s->sched_scanning) {
+			wpa_printf(MSG_DEBUG, "Schedule PNO on completion of "
+				   "ongoing sched scan");
+			wpa_supplicant_cancel_sched_scan(wpa_s);
+			wpa_s->pno_sched_pending = 1;
+			return 0;
+		}
 	}
 
 	os_memset(&params, 0, sizeof(params));
@@ -128,11 +134,13 @@
 {
 	int ret = 0;
 
-	if (wpa_s->pno) {
+	if (wpa_s->pno || wpa_s->sched_scanning) {
 		wpa_s->pno = 0;
 		ret = wpa_supplicant_stop_sched_scan(wpa_s);
 	}
 
+	wpa_s->pno_sched_pending = 0;
+
 	if (wpa_s->wpa_state == WPA_SCANNING)
 		wpa_supplicant_req_scan(wpa_s, 0, 0);
 
@@ -5307,6 +5315,9 @@
 	wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
 	wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
 	wpa_config_flush_blobs(wpa_s->conf);
+	wpa_s->conf->auto_interworking = 0;
+	wpa_s->conf->okc = 0;
+	wpa_s->conf->pmf = 0;
 
 	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
 	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
@@ -5477,6 +5488,9 @@
 {
 	struct wpa_radio_work *work, *tmp;
 
+	if (!wpa_s || !wpa_s->radio)
+		return;
+
 	dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
 			      struct wpa_radio_work, list) {
 		struct wpa_external_work *ework;
diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c
index 8fb217d..d44313c 100644
--- a/wpa_supplicant/ctrl_iface_unix.c
+++ b/wpa_supplicant/ctrl_iface_unix.c
@@ -800,7 +800,7 @@
 {
 	struct wpa_global *global = eloop_ctx;
 	struct ctrl_iface_global_priv *priv = sock_ctx;
-	char buf[256];
+	char buf[4096];
 	int res;
 	struct sockaddr_un from;
 	socklen_t fromlen = sizeof(from);
diff --git a/wpa_supplicant/doc/docbook/Makefile b/wpa_supplicant/doc/docbook/Makefile
index aaeee2e..82f9de3 100644
--- a/wpa_supplicant/doc/docbook/Makefile
+++ b/wpa_supplicant/doc/docbook/Makefile
@@ -7,6 +7,7 @@
 FILES += wpa_priv
 FILES += wpa_supplicant.conf
 FILES += wpa_supplicant
+FILES += eapol_test
 
 man:
 	for i in $(FILES); do docbook2man $$i.sgml; done
@@ -20,7 +21,7 @@
 
 
 clean:
-	rm -f wpa_background.8 wpa_cli.8 wpa_gui.8 wpa_passphrase.8 wpa_priv.8 wpa_supplicant.8
+	rm -f wpa_background.8 wpa_cli.8 wpa_gui.8 wpa_passphrase.8 wpa_priv.8 wpa_supplicant.8 eapol_test.8
 	rm -f wpa_supplicant.conf.5
 	rm -f manpage.links manpage.refs
 	rm -f $(FILES:%=%.pdf)
diff --git a/wpa_supplicant/doc/docbook/eapol_test.sgml b/wpa_supplicant/doc/docbook/eapol_test.sgml
new file mode 100644
index 0000000..fec174b
--- /dev/null
+++ b/wpa_supplicant/doc/docbook/eapol_test.sgml
@@ -0,0 +1,205 @@
+<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+
+<refentry>
+  <refmeta>
+    <refentrytitle>eapol_test</refentrytitle>
+    <manvolnum>8</manvolnum>
+  </refmeta>
+  <refnamediv>
+    <refname>eapol_test</refname>
+
+    <refpurpose>EAP peer and RADIUS client testing</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>eapol_test</command>
+      <arg>-nWS</arg>
+      <arg>-c<replaceable>config file</replaceable></arg>
+      <arg>-a<replaceable>server IP address</replaceable></arg>
+      <arg>-A<replaceable>client IP address</replaceable></arg>
+      <arg>-p<replaceable>UDP port</replaceable></arg>
+      <arg>-s<replaceable>shared secret</replaceable></arg>
+      <arg>-r<replaceable>re-authentications</replaceable></arg>
+      <arg>-t<replaceable>timeout</replaceable></arg>
+      <arg>-C<replaceable>Connect-Info</replaceable></arg>
+      <arg>-M<replaceable>MAC address</replaceable></arg>
+      <arg>-o<replaceable>file</replaceable></arg>
+      <arg>-N<replaceable>attr spec</replaceable></arg>
+    </cmdsynopsis>
+    <cmdsynopsis>
+      <command>eapol_test scard</command>
+    </cmdsynopsis>
+    <cmdsynopsis>
+      <command>eapol_test sim</command>
+      <arg>PIN</arg>
+      <arg>num triplets</arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Overview</title>
+
+    <para>eapol_test is a program that links together the same EAP
+    peer implementation that wpa_supplicant is using and the RADIUS
+    authentication client code from hostapd. In addition, it has
+    minimal glue code to combine these two components in similar
+    ways to IEEE 802.1X/EAPOL Authenticator state machines. In other
+    words, it integrates IEEE 802.1X Authenticator (normally, an
+    access point) and IEEE 802.1X Supplicant (normally, a wireless
+    client) together to generate a single program that can be used to
+    test EAP methods without having to setup an access point and a
+    wireless client.</para>
+
+    <para>The main uses for eapol_test are in interoperability testing
+    of EAP methods against RADIUS servers and in development testing
+    for new EAP methods. It can be easily used to automate EAP testing
+    for interoperability and regression since the program can be run
+    from shell scripts without require additional test components apart
+    from a RADIUS server. For example, the automated EAP tests described
+    in eap_testing.txt are implemented with eapol_test. Similarly,
+    eapol_test could be used to implement an automated regression
+    test suite for a RADIUS authentication server.</para>
+
+
+    <para>As an example:</para>
+
+<blockquote><programlisting>
+eapol_test -ctest.conf -a127.0.0.1 -p1812 -ssecret -r1
+</programlisting></blockquote>
+
+    <para>tries to complete EAP authentication based on the network
+    configuration from test.conf against the RADIUS server running
+    on the local host. A re-authentication is triggered to test fast
+    re-authentication. The configuration file uses the same format for
+    network blocks as wpa_supplicant.</para>
+
+  </refsect1>
+  <refsect1>
+    <title>Command Arguments</title>
+    <variablelist>
+      <varlistentry>
+	<term>-c configuration file path</term>
+
+	<listitem><para>A configuration to use.  The configuration should
+	use the same format for network blocks as wpa_supplicant.
+	</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-a AS address</term>
+
+	<listitem><para>IP address of the authentication server.  The
+	default is '127.0.0.1'.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-A client address</term>
+
+	<listitem><para>IP address of the client.  The default is to
+	select an address automatically.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-p AS port</term>
+
+	<listitem><para>UDP port of the authentication server. The
+	default is '1812'.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-s AS secret</term>
+
+	<listitem><para>Shared secret with the authentication server.
+	The default is 'radius'.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-r count</term>
+
+	<listitem><para>Number of reauthentications.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-t timeout</term>
+
+	<listitem><para>Timeout in seconds. The default is 30.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-C info</term>
+
+	<listitem><para>RADIUS Connect-Info.  The default is
+	'CONNECT 11Mbps 802.11b'.</para></listitem>
+      </varlistentry>
+
+
+      <varlistentry>
+	<term>-M mac address</term>
+
+	<listitem><para>Client MAC address (Calling-Station-Id).  The
+	default is '02:00:00:00:00:01'.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-o file</term>
+
+	<listitem><para>Location to write out server certificate.
+	</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-N attr spec</term>
+
+	<listitem><para>Send arbitrary attribute specific by
+	attr_id:syntax:value, or attr_id alone.  attr_id should be the numeric
+	ID of the attribute, and syntax should be one of 's' (string),
+	'd' (integer), or 'x' (octet string). The value is the attribute value
+	to send.  When attr_id is given alone, NULL is used as the attribute
+	value.  Multiple attributes can be specified by using the option
+	several times.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-n</term>
+
+	<listitem><para>Indicates that no MPPE keys are expected.
+	</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-W</term>
+
+	<listitem><para>Wait for a control interface monitor before starting.
+	</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-S</term>
+
+	<listitem><para>Save configuration after authentication.
+	</para></listitem>
+      </varlistentry>
+
+    </variablelist>
+  </refsect1>
+  <refsect1>
+    <title>See Also</title>
+    <para>
+      <citerefentry>
+	<refentrytitle>wpa_supplicant</refentrytitle>
+	<manvolnum>8</manvolnum>
+      </citerefentry>
+    </para>
+  </refsect1>
+  <refsect1>
+    <title>Legal</title>
+    <para>wpa_supplicant is copyright (c) 2003-2014,
+    Jouni Malinen <email>j@w1.fi</email> and
+    contributors.
+    All Rights Reserved.</para>
+
+    <para>This program is licensed under the BSD license (the one with
+    advertisement clause removed).</para>
+  </refsect1>
+</refentry>
diff --git a/wpa_supplicant/doc/docbook/wpa_background.sgml b/wpa_supplicant/doc/docbook/wpa_background.sgml
index eb3a089..860b5a0 100644
--- a/wpa_supplicant/doc/docbook/wpa_background.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_background.sgml
@@ -90,7 +90,7 @@
 
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2012,
+    <para>wpa_supplicant is copyright (c) 2003-2014,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_cli.sgml b/wpa_supplicant/doc/docbook/wpa_cli.sgml
index c080c07..142e1ab 100644
--- a/wpa_supplicant/doc/docbook/wpa_cli.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_cli.sgml
@@ -15,10 +15,12 @@
     <cmdsynopsis>
       <command>wpa_cli</command>
       <arg>-p <replaceable>path to ctrl sockets</replaceable></arg>
+      <arg>-g <replaceable>path to global ctrl_interface socket</replaceable></arg>
       <arg>-i <replaceable>ifname</replaceable></arg>
       <arg>-hvB</arg>
       <arg>-a <replaceable>action file</replaceable></arg>
       <arg>-P <replaceable>pid file</replaceable></arg>
+      <arg>-G <replaceable>ping interval</replaceable></arg>
       <arg><replaceable>command ...</replaceable></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
@@ -111,6 +113,14 @@
       </varlistentry>
 
       <varlistentry>
+	<term>-g control socket path</term>
+
+	<listitem><para>Connect to the global control socket at the
+	indicated path rather than an interface-specific control
+	socket.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
 	<term>-i ifname</term>
 
         <listitem><para>Specify the interface that is being
@@ -161,6 +171,13 @@
       </varlistentry>
 
       <varlistentry>
+	<term>-G ping interval</term>
+
+	<listitem><para>Set the interval (in seconds) at which
+	wpa_cli pings the supplicant.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
 	<term>command</term>
 
 	<listitem><para>Run a command.  The available commands are
@@ -328,7 +345,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2012,
+    <para>wpa_supplicant is copyright (c) 2003-2014,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_gui.sgml b/wpa_supplicant/doc/docbook/wpa_gui.sgml
index 0ab6419..f6ef8f1 100644
--- a/wpa_supplicant/doc/docbook/wpa_gui.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_gui.sgml
@@ -74,7 +74,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2012,
+    <para>wpa_supplicant is copyright (c) 2003-2014,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_passphrase.sgml b/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
index 336c03b..3b4360b 100644
--- a/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
@@ -62,7 +62,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2012,
+    <para>wpa_supplicant is copyright (c) 2003-2014,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_priv.sgml b/wpa_supplicant/doc/docbook/wpa_priv.sgml
index eb907a8..9c114cc 100644
--- a/wpa_supplicant/doc/docbook/wpa_priv.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_priv.sgml
@@ -137,7 +137,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2012,
+    <para>wpa_supplicant is copyright (c) 2003-2014,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
index aa20e57..182060d 100644
--- a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
@@ -12,7 +12,7 @@
   <refsynopsisdiv>
     <cmdsynopsis>
       <command>wpa_supplicant</command>
-      <arg>-BddfhKLqqtuvW</arg>
+      <arg>-BddfhKLqqsTtuvW</arg>
       <arg>-i<replaceable>ifname</replaceable></arg>
       <arg>-c<replaceable>config file</replaceable></arg>
       <arg>-D<replaceable>driver</replaceable></arg>
@@ -344,9 +344,20 @@
       </varlistentry>
 
       <varlistentry>
+	<term>-e entropy file</term>
+	<listitem>
+	  <para>File for <command>wpa_supplicant</command> to use to
+	  maintain its internal entropy store in over restarts.</para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
 	<term>-f output file</term>
 	<listitem>
-	  <para>Log output to specified file instead of stdout.</para>
+	  <para>Log output to specified file instead of stdout. (This
+	  is only available if <command>wpa_supplicant</command> was
+	  built with the <literal>CONFIG_DEBUG_FILE</literal>
+	  option.)</para>
 	</listitem>
       </varlistentry>
 
@@ -387,6 +398,22 @@
       </varlistentry>
 
       <varlistentry>
+	<term>-o override driver</term>
+	<listitem>
+	  <para>Override the driver parameter for new
+	  interfaces.</para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-O override ctrl_interface</term>
+	<listitem>
+	  <para>Override the ctrl_interface parameter for new
+	  interfaces.</para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
 	<term>-p</term>
 	<listitem>
 	  <para>Driver parameters. (Per interface)</para>
@@ -409,10 +436,40 @@
       </varlistentry>
 
       <varlistentry>
+	<term>-s</term>
+	<listitem>
+	  <para>Log output to syslog instead of stdout. (This is only
+	  available if <command>wpa_supplicant</command> was built
+	  with the <literal>CONFIG_DEBUG_SYSLOG</literal>
+	  option.)</para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-T</term>
+	<listitem>
+	  <para>Log output to Linux tracing in addition to any other
+	  destinations. (This is only available
+	  if <command>wpa_supplicant</command> was built with
+	  the <literal>CONFIG_DEBUG_LINUX_TRACING</literal>
+	  option.)</para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-t</term>
+	<listitem>
+	  <para>Include timestamp in debug messages.</para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
 	<term>-u</term>
 	<listitem>
-	  <para>Enabled DBus control interface. If enabled, interface
-	  definitions may be omitted.</para>
+	  <para>Enable DBus control interface. If enabled, interface
+	  definitions may be omitted. (This is only available
+	  if <command>wpa_supplicant</command> was built with
+	  the <literal>CONFIG_DBUS</literal> option.)</para>0
 	</listitem>
       </varlistentry>
 
@@ -679,7 +736,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2012,
+    <para>wpa_supplicant is copyright (c) 2003-2014,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index f5834d4..72d2d5b 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2739,8 +2739,10 @@
 #endif /* CONFIG_WNM */
 
 #ifdef CONFIG_GAS
-	if (mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
+	if ((mgmt->u.action.category == WLAN_ACTION_PUBLIC ||
+	     mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL) &&
 	    gas_query_rx(wpa_s->gas, mgmt->da, mgmt->sa, mgmt->bssid,
+			 mgmt->u.action.category,
 			 payload, plen, freq) == 0)
 		return;
 #endif /* CONFIG_GAS */
@@ -3240,6 +3242,7 @@
 					 data->driver_gtk_rekey.replay_ctr);
 		break;
 	case EVENT_SCHED_SCAN_STOPPED:
+		wpa_s->pno = 0;
 		wpa_s->sched_scanning = 0;
 		wpa_supplicant_notify_scanning(wpa_s, 0);
 
@@ -3247,11 +3250,20 @@
 			break;
 
 		/*
-		 * If we timed out, start a new sched scan to continue
-		 * searching for more SSIDs.
+		 * Start a new sched scan to continue searching for more SSIDs
+		 * either if timed out or PNO schedule scan is pending.
 		 */
-		if (wpa_s->sched_scan_timed_out)
-			wpa_supplicant_req_sched_scan(wpa_s);
+		if (wpa_s->sched_scan_timed_out || wpa_s->pno_sched_pending) {
+
+			if (wpa_supplicant_req_sched_scan(wpa_s) < 0 &&
+			    wpa_s->pno_sched_pending) {
+				wpa_msg(wpa_s, MSG_ERROR, "Failed to schedule PNO");
+			} else if (wpa_s->pno_sched_pending) {
+				wpa_s->pno_sched_pending = 0;
+				wpa_s->pno = 1;
+			}
+		}
+
 		break;
 	case EVENT_WPS_BUTTON_PUSHED:
 #ifdef CONFIG_WPS
diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c
index f002fd5..abcb391 100644
--- a/wpa_supplicant/gas_query.c
+++ b/wpa_supplicant/gas_query.c
@@ -1,7 +1,7 @@
 /*
  * Generic advertisement service (GAS) query
  * Copyright (c) 2009, Atheros Communications
- * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
+ * Copyright (c) 2011-2014, Qualcomm Atheros, Inc.
  * Copyright (c) 2011-2014, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
@@ -15,6 +15,7 @@
 #include "common/ieee802_11_defs.h"
 #include "common/gas.h"
 #include "common/wpa_ctrl.h"
+#include "rsn_supp/wpa.h"
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
 #include "offchannel.h"
@@ -228,13 +229,28 @@
 }
 
 
+static int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
+{
+	if (wpa_s->current_ssid == NULL ||
+	    wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
+	    os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
+		return 0;
+	return wpa_sm_pmf_enabled(wpa_s->wpa);
+}
+
+
 static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
 			struct wpabuf *req)
 {
-	int res;
+	int res, prot = pmf_in_use(gas->wpa_s, query->addr);
+
 	wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u "
-		   "freq=%d", MAC2STR(query->addr),
-		   (unsigned int) wpabuf_len(req), query->freq);
+		   "freq=%d prot=%d", MAC2STR(query->addr),
+		   (unsigned int) wpabuf_len(req), query->freq, prot);
+	if (prot) {
+		u8 *categ = wpabuf_mhead_u8(req);
+		*categ = WLAN_ACTION_PROTECTED_DUAL;
+	}
 	res = offchannel_send_action(gas->wpa_s, query->freq, query->addr,
 				     gas->wpa_s->own_addr, query->addr,
 				     wpabuf_head(req), wpabuf_len(req), 1000,
@@ -386,27 +402,41 @@
 
 
 /**
- * gas_query_rx - Indicate reception of a Public Action frame
+ * gas_query_rx - Indicate reception of a Public Action or Protected Dual frame
  * @gas: GAS query data from gas_query_init()
  * @da: Destination MAC address of the Action frame
  * @sa: Source MAC address of the Action frame
  * @bssid: BSSID of the Action frame
+ * @categ: Category of the Action frame
  * @data: Payload of the Action frame
  * @len: Length of @data
  * @freq: Frequency (in MHz) on which the frame was received
  * Returns: 0 if the Public Action frame was a GAS frame or -1 if not
  */
 int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
-		 const u8 *bssid, const u8 *data, size_t len, int freq)
+		 const u8 *bssid, u8 categ, const u8 *data, size_t len,
+		 int freq)
 {
 	struct gas_query_pending *query;
 	u8 action, dialog_token, frag_id = 0, more_frags = 0;
 	u16 comeback_delay, resp_len;
 	const u8 *pos, *adv_proto;
+	int prot, pmf;
 
 	if (gas == NULL || len < 4)
 		return -1;
 
+	prot = categ == WLAN_ACTION_PROTECTED_DUAL;
+	pmf = pmf_in_use(gas->wpa_s, bssid);
+	if (prot && !pmf) {
+		wpa_printf(MSG_DEBUG, "GAS: Drop unexpected protected GAS frame when PMF is disabled");
+		return 0;
+	}
+	if (!prot && pmf) {
+		wpa_printf(MSG_DEBUG, "GAS: Drop unexpected unprotected GAS frame when PMF is enabled");
+		return 0;
+	}
+
 	pos = data;
 	action = *pos++;
 	dialog_token = *pos++;
diff --git a/wpa_supplicant/gas_query.h b/wpa_supplicant/gas_query.h
index 5c3d161..ad13490 100644
--- a/wpa_supplicant/gas_query.h
+++ b/wpa_supplicant/gas_query.h
@@ -17,7 +17,8 @@
 struct gas_query * gas_query_init(struct wpa_supplicant *wpa_s);
 void gas_query_deinit(struct gas_query *gas);
 int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
-		 const u8 *bssid, const u8 *data, size_t len, int freq);
+		 const u8 *bssid, u8 categ, const u8 *data, size_t len,
+		 int freq);
 
 /**
  * enum gas_query_result - GAS query result
diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c
index 37f0c78..d56935d 100644
--- a/wpa_supplicant/main.c
+++ b/wpa_supplicant/main.c
@@ -22,13 +22,24 @@
 	int i;
 	printf("%s\n\n%s\n"
 	       "usage:\n"
-	       "  wpa_supplicant [-BddhKLqqstuvW] [-P<pid file>] "
+	       "  wpa_supplicant [-BddhKLqq"
+#ifdef CONFIG_DEBUG_SYSLOG
+	       "s"
+#endif /* CONFIG_DEBUG_SYSLOG */
+	       "t"
+#ifdef CONFIG_DBUS
+	       "u"
+#endif /* CONFIG_DBUS */
+	       "vW] [-P<pid file>] "
 	       "[-g<global ctrl>] \\\n"
 	       "        [-G<group>] \\\n"
 	       "        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
 	       "[-p<driver_param>] \\\n"
-	       "        [-b<br_ifname>] [-f<debug file>] [-e<entropy file>] "
-	       "\\\n"
+	       "        [-b<br_ifname>] [-e<entropy file>]"
+#ifdef CONFIG_DEBUG_FILE
+	       " [-f<debug file>]"
+#endif /* CONFIG_DEBUG_FILE */
+	       " \\\n"
 	       "        [-o<override driver>] [-O<override ctrl>] \\\n"
 	       "        [-N -i<ifname> -c<conf> [-C<ctrl>] "
 	       "[-D<driver>] \\\n"
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 91ed508..889a949 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1342,6 +1342,7 @@
 	d->pbc_in_m1 = s->pbc_in_m1;
 	d->ignore_old_scan_res = s->ignore_old_scan_res;
 	d->beacon_int = s->beacon_int;
+	d->dtim_period = s->dtim_period;
 	d->disassoc_low_ack = s->disassoc_low_ack;
 	d->disable_scan_offload = s->disable_scan_offload;
 }
@@ -3571,6 +3572,21 @@
 }
 
 
+static int wpas_is_concurrent_session_active(void *ctx)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+	struct wpa_supplicant *ifs;
+
+	for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
+		if (ifs == wpa_s)
+			continue;
+		if (ifs->wpa_state > WPA_ASSOCIATED)
+			return 1;
+	}
+	return 0;
+}
+
+
 static void wpas_p2p_debug_print(void *ctx, int level, const char *msg)
 {
 	struct wpa_supplicant *wpa_s = ctx;
@@ -3685,6 +3701,7 @@
 	p2p.get_noa = wpas_get_noa;
 	p2p.go_connected = wpas_go_connected;
 	p2p.presence_resp = wpas_presence_resp;
+	p2p.is_concurrent_session_active = wpas_is_concurrent_session_active;
 
 	os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
 	os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index da827bd..30da097 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -521,6 +521,11 @@
 	size_t max_ssids;
 	enum wpa_states prev_state;
 
+	if (wpa_s->pno || wpa_s->pno_sched_pending) {
+		wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - PNO is in progress");
+		return;
+	}
+
 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled");
 		return;
@@ -1112,6 +1117,9 @@
 		params.extra_ies_len = wpabuf_len(extra_ie);
 	}
 
+	if (wpa_s->conf->filter_rssi)
+		params.filter_rssi = wpa_s->conf->filter_rssi;
+
 	scan_params = &params;
 
 scan:
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 3a28534..078856e 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -768,6 +768,7 @@
 	} hw;
 
 	int pno;
+	int pno_sched_pending;
 
 	/* WLAN_REASON_* reason codes. Negative if locally generated. */
 	int disconnect_reason;