Cumulative patch from commit 39a5800f7c2a9de743c673a78929ac46a099b1a4

39a5800 wpa_supplicant: Allow disabling LDPC
7230040 Interworking: Read IMSI if not read at supplicant start
62f736d Interworking: Init scard when a credential requires SIM access
729897a Interworking: Fix incorrect compile PCSC flag
21611ea edit: Increase buffer size to 4096 bytes
0b2c59e OSU server: Add example scripts for Hotspot 2.0 PKI
0f27c20 HS 2.0R2: Add example OSU SPP server implementation
1e03c6c XML: Remove forgotten, unused definition of debug_print_func
5cfc87b Make hs20_wan_metrics parser error print more helpful
4be20bf Fix validation of anqp_3gpp_cell_net configuration parameter
23587e3 Remove duplicated vht_capab parser entry
18a8e55 Notify STA of disconnection based on ACL change
8943cc9 RADIUS server: Add support for MAC ACL
dc87541 Clean up debug print for PSK file search
bbbacbf DFS: Print CAC info in ctrl_iface STATUS command
ace0fbd P2P: Fix segfault when PBC overlap is detected
cf15b15 Add writing of network block ocsp parameter
5c9da16 nl80211: Set all BSS interfaces down when tearing down AP in MBSS mode
f1c4dbf wpa_supplicant: Remove pending sme-connect radio work
4f560cd wpa_supplicant: Override HT A-MPDU size if VHT A-MPDU was overridden
3ae8b7b hostapd: Add vendor command support
782e2f7 P2P: Do not initiate scan on P2P Device when enabled
74a1319 Fix issue with incorrect secondary_channel in HT40/HT80
96ecea5 Pass TDLS peer capability information in tdls_mgmt
78cd7e6 Sync with wireless-testing.git include/uapi/linux/nl80211.h
b36935b nl80211: Fix EAPOL frames not being delivered
6997f8b nl80211: Set interface address even if using old interface
9b4d9c8 nl80211: Print if_indices list in debug log
762c41a eloop: Add assert() on negative fd when using select() code path
978c673 Add a note on using 'iw list' to determine multi-BSS support

Change-Id: I89af7f8d92ed706c8909ed3cc9c49d6e1277a2b0
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 23aab4b..6a46210 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1701,6 +1701,7 @@
 	{ INT_RANGE(disable_ht, 0, 1) },
 	{ INT_RANGE(disable_ht40, -1, 1) },
 	{ INT_RANGE(disable_sgi, 0, 1) },
+	{ INT_RANGE(disable_ldpc, 0, 1) },
 	{ INT_RANGE(disable_max_amsdu, -1, 1) },
 	{ INT_RANGE(ampdu_factor, -1, 3) },
 	{ INT_RANGE(ampdu_density, -1, 7) },
@@ -2157,6 +2158,7 @@
 	ssid->disable_ht = DEFAULT_DISABLE_HT;
 	ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
 	ssid->disable_sgi = DEFAULT_DISABLE_SGI;
+	ssid->disable_ldpc = DEFAULT_DISABLE_LDPC;
 	ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU;
 	ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR;
 	ssid->ampdu_density = DEFAULT_AMPDU_DENSITY;
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 4f58130..7394593 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -711,6 +711,7 @@
 	INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND);
 	STR(pac_file);
 	INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE);
+	INTe(ocsp);
 #endif /* IEEE8021X_EAPOL */
 	INT(mode);
 	INT(frequency);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index d515030..71829ef 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -30,6 +30,7 @@
 #define DEFAULT_DISABLE_HT 0
 #define DEFAULT_DISABLE_HT40 0
 #define DEFAULT_DISABLE_SGI 0
+#define DEFAULT_DISABLE_LDPC 0
 #define DEFAULT_DISABLE_MAX_AMSDU -1 /* no change */
 #define DEFAULT_AMPDU_FACTOR -1 /* no change */
 #define DEFAULT_AMPDU_DENSITY -1 /* no change */
@@ -525,6 +526,14 @@
 	int disable_sgi;
 
 	/**
+	 * disable_ldpc - Disable LDPC for this network
+	 *
+	 * By default, use it if it is available, but this can be configured
+	 * to 1 to have it disabled.
+	 */
+	int disable_ldpc;
+
+	/**
 	 * disable_max_amsdu - Disable MAX A-MSDU
 	 *
 	 * A-MDSU will be 3839 bytes when disabled, or 7935
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index bbcd662..938ece6 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -532,12 +532,14 @@
 static inline int wpa_drv_send_tdls_mgmt(struct wpa_supplicant *wpa_s,
 					 const u8 *dst, u8 action_code,
 					 u8 dialog_token, u16 status_code,
-					 const u8 *buf, size_t len)
+					 u32 peer_capab, const u8 *buf,
+					 size_t len)
 {
 	if (wpa_s->driver->send_tdls_mgmt) {
 		return wpa_s->driver->send_tdls_mgmt(wpa_s->drv_priv, dst,
 						     action_code, dialog_token,
-						     status_code, buf, len);
+						     status_code, peer_capab,
+						     buf, len);
 	}
 	return -1;
 }
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index ce11e98..fc00b68 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -303,11 +303,11 @@
 #ifdef PCSC_FUNCS
 	int aka = 0, sim = 0;
 
-	if (ssid->eap.pcsc == NULL || wpa_s->scard != NULL ||
-	    wpa_s->conf->external_sim)
+	if ((ssid != NULL && ssid->eap.pcsc == NULL) ||
+	    wpa_s->scard != NULL || wpa_s->conf->external_sim)
 		return 0;
 
-	if (ssid->eap.eap_methods == NULL) {
+	if (ssid == NULL || ssid->eap.eap_methods == NULL) {
 		sim = 1;
 		aka = 1;
 	} else {
@@ -1069,8 +1069,12 @@
 		wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OVERLAP
 			"PBC session overlap");
 #ifdef CONFIG_P2P
-		if (wpas_p2p_notif_pbc_overlap(wpa_s) == 1)
+		if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT ||
+		    wpa_s->p2p_in_provisioning) {
+			eloop_register_timeout(0, 0, wpas_p2p_pbc_overlap_cb,
+					       wpa_s, NULL);
 			return -1;
+		}
 #endif /* CONFIG_P2P */
 
 #ifdef CONFIG_WPS
@@ -3278,6 +3282,12 @@
 		wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled");
 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
 			wpa_supplicant_update_mac_addr(wpa_s);
+			if (wpa_s->p2p_mgmt) {
+				wpa_supplicant_set_state(wpa_s,
+							 WPA_DISCONNECTED);
+				break;
+			}
+
 #ifdef CONFIG_AP
 			if (!wpa_s->ap_iface) {
 				wpa_supplicant_set_state(wpa_s,
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 71163c3..3450ffe 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -260,8 +260,10 @@
 		info_ids[num_info_ids++] = ANQP_IP_ADDR_TYPE_AVAILABILITY;
 	if (all || cred_with_nai_realm(wpa_s))
 		info_ids[num_info_ids++] = ANQP_NAI_REALM;
-	if (all || cred_with_3gpp(wpa_s))
+	if (all || cred_with_3gpp(wpa_s)) {
 		info_ids[num_info_ids++] = ANQP_3GPP_CELLULAR_NETWORK;
+		wpa_supplicant_scard_init(wpa_s, NULL);
+	}
 	if (all || cred_with_domain(wpa_s))
 		info_ids[num_info_ids++] = ANQP_DOMAIN_NAME;
 	wpa_hexdump(MSG_DEBUG, "Interworking: ANQP Query info",
@@ -1748,6 +1750,31 @@
 }
 
 
+#ifdef PCSC_FUNCS
+static int interworking_pcsc_read_imsi(struct wpa_supplicant *wpa_s)
+{
+	size_t len;
+
+	if (wpa_s->imsi[0] && wpa_s->mnc_len)
+		return 0;
+
+	len = sizeof(wpa_s->imsi) - 1;
+	if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
+		scard_deinit(wpa_s->scard);
+		wpa_s->scard = NULL;
+		wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
+		return -1;
+	}
+	wpa_s->imsi[len] = '\0';
+	wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
+	wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
+		   wpa_s->imsi, wpa_s->mnc_len);
+
+	return 0;
+}
+#endif /* PCSC_FUNCS */
+
+
 static struct wpa_cred * interworking_credentials_available_3gpp(
 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw,
 	int *excluded)
@@ -1786,8 +1813,9 @@
 		size_t msin_len;
 
 #ifdef PCSC_FUNCS
-		if (cred->pcsc && wpa_s->conf->pcsc_reader && wpa_s->scard &&
-		    wpa_s->imsi[0]) {
+		if (cred->pcsc && wpa_s->scard) {
+			if (interworking_pcsc_read_imsi(wpa_s) < 0)
+				continue;
 			imsi = wpa_s->imsi;
 			mnc_len = wpa_s->mnc_len;
 			goto compare;
@@ -2043,13 +2071,14 @@
 	int mnc_len = 0;
 	if (cred->imsi)
 		imsi = cred->imsi;
-#ifdef CONFIG_PCSC
-	else if (cred->pcsc && wpa_s->conf->pcsc_reader &&
-		 wpa_s->scard && wpa_s->imsi[0]) {
+#ifdef PCSC_FUNCS
+	else if (cred->pcsc && wpa_s->scard) {
+		if (interworking_pcsc_read_imsi(wpa_s) < 0)
+			return -1;
 		imsi = wpa_s->imsi;
 		mnc_len = wpa_s->mnc_len;
 	}
-#endif /* CONFIG_PCSC */
+#endif /* PCSC_FUNCS */
 #ifdef CONFIG_EAP_PROXY
 	else if (cred->pcsc && wpa_s->mnc_len > 0 && wpa_s->imsi[0]) {
 		imsi = wpa_s->imsi;
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 5e36a67..303b7fe 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -6392,6 +6392,13 @@
 }
 
 
+void wpas_p2p_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+	wpas_p2p_notif_pbc_overlap(wpa_s);
+}
+
+
 void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s)
 {
 	struct p2p_channels chan, cli_chan;
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index d3d36b1..0bf3ca9 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -158,6 +158,7 @@
 				 const struct wpabuf *req,
 				 const struct wpabuf *sel, int forced_freq);
 int wpas_p2p_nfc_tag_enabled(struct wpa_supplicant *wpa_s, int enabled);
+void wpas_p2p_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx);
 
 #ifdef CONFIG_P2P
 int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s);
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index a860afb..2538ba0 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -477,8 +477,14 @@
 	}
 
 	if (radio_work_pending(wpa_s, "sme-connect")) {
-		wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since pending work exist");
-		return;
+		/*
+		 * The previous sme-connect work might no longer be valid due to
+		 * the fact that the BSS list was updated. In addition, it makes
+		 * sense to adhere to the 'newer' decision.
+		 */
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"SME: Remove previous pending sme-connect");
+		radio_remove_works(wpa_s, "sme-connect", 0);
 	}
 
 	cwork = os_zalloc(sizeof(*cwork));
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index dce1c00..5c6f625 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2922,6 +2922,27 @@
 }
 
 
+static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
+			       struct ieee80211_ht_capabilities *htcaps,
+			       struct ieee80211_ht_capabilities *htcaps_mask,
+			       int disabled)
+{
+	/* Masking these out disables LDPC */
+	u16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
+
+	wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
+
+	if (disabled)
+		htcaps->ht_capabilities_info &= ~msk;
+	else
+		htcaps->ht_capabilities_info |= msk;
+
+	htcaps_mask->ht_capabilities_info |= msk;
+
+	return 0;
+}
+
+
 void wpa_supplicant_apply_ht_overrides(
 	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
 	struct wpa_driver_associate_params *params)
@@ -2945,6 +2966,7 @@
 	wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
 	wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
 	wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
+	wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
 }
 
 #endif /* CONFIG_HT_OVERRIDES */
@@ -2957,6 +2979,10 @@
 {
 	struct ieee80211_vht_capabilities *vhtcaps;
 	struct ieee80211_vht_capabilities *vhtcaps_mask;
+#ifdef CONFIG_HT_OVERRIDES
+	int max_ampdu;
+	const u32 max_ampdu_mask = VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
+#endif /* CONFIG_HT_OVERRIDES */
 
 	if (!ssid)
 		return;
@@ -2972,6 +2998,20 @@
 	vhtcaps->vht_capabilities_info = ssid->vht_capa;
 	vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
 
+#ifdef CONFIG_HT_OVERRIDES
+	/* if max ampdu is <= 3, we have to make the HT cap the same */
+	if (ssid->vht_capa_mask & max_ampdu_mask) {
+		max_ampdu = (ssid->vht_capa & max_ampdu_mask) >>
+			find_first_bit(max_ampdu_mask);
+
+		max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
+		wpa_set_ampdu_factor(wpa_s,
+				     (void *) params->htcaps,
+				     (void *) params->htcaps_mask,
+				     max_ampdu);
+	}
+#endif /* CONFIG_HT_OVERRIDES */
+
 #define OVERRIDE_MCS(i)							\
 	if (ssid->vht_tx_mcs_nss_ ##i >= 0) {				\
 		vhtcaps_mask->vht_supported_mcs_set.tx_map |=		\
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 03c6f5f..3358250 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -947,6 +947,10 @@
 # 0 = SGI enabled (if AP supports it)
 # 1 = SGI disabled
 #
+# disable_ldpc: Whether LDPC should be disabled.
+# 0 = LDPC enabled (if AP supports it)
+# 1 = LDPC disabled
+#
 # ht_mcs:  Configure allowed MCS rates.
 #  Parsed as an array of bytes, in base-16 (ascii-hex)
 # ht_mcs=""                                   // Use all available (default)
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index e8a4b35..b2a330c 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -558,12 +558,12 @@
 
 static int wpa_supplicant_send_tdls_mgmt(void *ctx, const u8 *dst,
 					 u8 action_code, u8 dialog_token,
-					 u16 status_code, const u8 *buf,
-					 size_t len)
+					 u16 status_code, u32 peer_capab,
+					 const u8 *buf, size_t len)
 {
 	struct wpa_supplicant *wpa_s = ctx;
 	return wpa_drv_send_tdls_mgmt(wpa_s, dst, action_code, dialog_token,
-				      status_code, buf, len);
+				      status_code, peer_capab, buf, len);
 }
 
 
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index b086c47..dfcc069 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -510,15 +510,6 @@
 }
 
 
-#ifdef CONFIG_P2P
-static void wpas_wps_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx)
-{
-	struct wpa_supplicant *wpa_s = eloop_ctx;
-	wpas_p2p_notif_pbc_overlap(wpa_s);
-}
-#endif /* CONFIG_P2P */
-
-
 static void wpa_supplicant_wps_event_m2d(struct wpa_supplicant *wpa_s,
 					 struct wps_event_m2d *m2d)
 {
@@ -537,7 +528,7 @@
 		 * Notify P2P from eloop timeout to avoid issues with the
 		 * interface getting removed while processing a message.
 		 */
-		eloop_register_timeout(0, 0, wpas_wps_pbc_overlap_cb, wpa_s,
+		eloop_register_timeout(0, 0, wpas_p2p_pbc_overlap_cb, wpa_s,
 				       NULL);
 	}
 #endif /* CONFIG_P2P */