Cumulative patch from commit f51f54a007e0de1d413dee3523472d3bbeed2ecc

f51f54a nl80211: Resubscribe to nl80211 events on global nl_event socket
48ec694 Fix Linux packet socket workaround to not close the socket too easily
0d2030e Use estimated throughput to improve roaming selection
1d747e2 Add snr and est_throughput to the BSS entries
a1b790e Select AP based on estimated maximum throughput
ab647ff Add wpa_supplicant Makefile target libwpa_ctrl.a
abae2d1 trace: Initialize alloc_list even without os_program_init() call
891dfb3 Add helper function to clear and free wpa_psk list
71d77ad Update current BSS level when signal change event occurs
f1609f1 wpa_supplicant: Cancel sched_scan when stopping countermeasures
abb8d08 nl80211: Add support for configuring P2P GO CTWindow
0b8bcaa P2P: Allow configuring CTWindow when working as GO
c77ffc6 TDLS: Ignore extra padding in all packets
5ce6ac1 Inteworking: Add support to update the ANQP Capability List into the BSS
185ada4 HS 2.0: Add support to update the HS20 Capability List into the BSS
7fe7a3a wpa_gui: Debug enhancement
2b892d4 Add forgotten network profile parameters to config file writing
563ee18 IBSS: Add support for VHT80 configuration
ada157f Make hostapd_set_freq_params() common
98479dc IBSS: Update operating frequency if joining an existing IBSS
4d9e6fb IBSS: Add fixed_freq network parameter
6f5e1b0 Use priority list instead of global for PNO
97fc2dc Allow libnl-3.0 include path be specified
f92446f P2PS: Add P2PS interface info
59b416c Add optional reassoc-to-same-BSS optimization
c4da67d Fix passive_scan config parameter writing
715d5c4 hs20-osu-client: Ensure NULL checks are done before dereferencing
58d405f Fix OCSP debug messages
710dfb4 OpenSSL: Fix OCSP error path
bd7bb43 HTTP: Fix OCSP error path
946572c Android: Remove commented out non-Android build parameters
15ada7f Android: Remove libxml2 config defines
ebe8d3f Android: Silence unused function parameter warnings
dbd10da Android: Fix hs20-osu-client build on Android 5.0
a926295 HS 2.0R2: Fix permissions for SP/<fqdn> directory on Android
480994d nl80211: Allocate QCA vendor subcmds for DFS radar detected and CAC events
c165cb4 Drop all hostapd STA entries on interface disabled event
106fa1e nl80211: Indicate interface-down event only for the main netdev
eeb1cb2 VLAN: Clean up RTM_NEW/DELLINK processing
47e5fbd hostapd: Avoid sending client probe on removed client
3478273 Re-configure WPA2 group keys on hostapd interface re-enable
f33c860 Re-enable beaconing on interface disable+enable
fc99fab nl80211: Print a debug log entry on NL80211_CMD_PROBE_CLIENT failures
0d2f324 P2P: Fix send_action_in_progress clearing in corner cases
9ff8dda Add hostapd UPDATE_BEACON ctrl_iface command
e0761c5 nl80211: Allocate QCA vendor subcmd for DFS CAC Start event
1db718b nl80211: Test vendor command and event
10263dc Add control interface commands for fetching wpa_config values
f91a512 Add INTERWORKING_ADD_NETWORK command
c612ae9 AP: Do not reply to Probe Request frames with DS Params mismatch
5b74e08 P2P: Document P2P_CONNECT-auto
99650ca Add STOP_AP control interface command
6b00512 P2P: Add event messages for P2P_CONNECT-fallback-to-GO-Neg
b0e669b P2P: Fix P2P_CONNECT-auto fallback to GO Neg with group interface
bf51f4f mesh: Fix remaining BLOCKED state after SAE auth failure
79ddb20 mesh: Add a monitor event on SAE authentication getting blocked
dd2cbaf mesh: Add a monitor event for SAE authentication failure
0cb5f8d mesh: Fix inactivity timer for 32 bit system
11e2ddb mesh: Remove duplicated no_auto_peer update
1e52983 D-Bus: Fix network block type change
4fada12 Fix HT40 co-ex scanning issue on hostapd error path
23ed011 Fix Linux packat socket regression work around
663ae2f Don't write to wpa_supplicant.conf directly
d9a9bc0 IBSS: Do not enable HT with WEP or TKIP
0d7eb43 ACS: Accept channel if any (rather than all) survey results are valid
68fa00c ACS: Allow specific channels to be preferred
6f41a25 ACS: Use weighted average for 2.4 GHz adjacent channel interference

Change-Id: Ie1cabd28dcfdefafa02e81477e34badae6f7e629
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 6ad09a8..05b785e 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1654,6 +1654,13 @@
 }
 
 
+static int bss_is_ibss(struct wpa_bss *bss)
+{
+	return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
+		IEEE80211_CAP_IBSS;
+}
+
+
 void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
 			  const struct wpa_ssid *ssid,
 			  struct hostapd_freq_params *freq)
@@ -1662,19 +1669,53 @@
 	struct hostapd_hw_modes *mode = NULL;
 	int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
 			   184, 192 };
+	int vht80[] = { 36, 52, 100, 116, 132, 149 };
 	struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
 	u8 channel;
-	int i, chan_idx, ht40 = -1, res;
+	int i, chan_idx, ht40 = -1, res, obss_scan = 1;
 	unsigned int j;
+	struct hostapd_freq_params vht_freq;
 
 	freq->freq = ssid->frequency;
 
+	for (j = 0; j < wpa_s->last_scan_res_used; j++) {
+		struct wpa_bss *bss = wpa_s->last_scan_res[j];
+
+		if (ssid->mode != WPAS_MODE_IBSS)
+			break;
+
+		/* Don't adjust control freq in case of fixed_freq */
+		if (ssid->fixed_freq)
+			break;
+
+		if (!bss_is_ibss(bss))
+			continue;
+
+		if (ssid->ssid_len == bss->ssid_len &&
+		    os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
+			wpa_printf(MSG_DEBUG,
+				   "IBSS already found in scan results, adjust control freq: %d",
+				   bss->freq);
+			freq->freq = bss->freq;
+			obss_scan = 0;
+			break;
+		}
+	}
+
 	/* For IBSS check HT_IBSS flag */
 	if (ssid->mode == WPAS_MODE_IBSS &&
 	    !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
 		return;
 
-	hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
+	if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
+	    wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
+	    wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
+		wpa_printf(MSG_DEBUG,
+			   "IBSS: WEP/TKIP detected, do not try to enable HT");
+		return;
+	}
+
+	hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
 	for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
 		if (wpa_s->hw.modes[i].mode == hw_mode) {
 			mode = &wpa_s->hw.modes[i];
@@ -1745,7 +1786,7 @@
 		break;
 	}
 
-	if (freq->sec_channel_offset) {
+	if (freq->sec_channel_offset && obss_scan) {
 		struct wpa_scan_results *scan_res;
 
 		scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
@@ -1782,6 +1823,55 @@
 	wpa_printf(MSG_DEBUG,
 		   "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
 		   freq->channel, freq->sec_channel_offset);
+
+	/* Not sure if mesh is ready for VHT */
+	if (ssid->mode != WPAS_MODE_IBSS)
+		return;
+
+	/* For IBSS check VHT_IBSS flag */
+	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
+		return;
+
+	vht_freq = *freq;
+
+	vht_freq.vht_enabled = vht_supported(mode);
+	if (!vht_freq.vht_enabled)
+		return;
+
+	/* setup center_freq1, bandwidth */
+	for (j = 0; j < ARRAY_SIZE(vht80); j++) {
+		if (freq->channel >= vht80[j] &&
+		    freq->channel < vht80[j] + 16)
+			break;
+	}
+
+	if (j == ARRAY_SIZE(vht80))
+		return;
+
+	for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
+		struct hostapd_channel_data *chan;
+
+		chan = hw_get_channel_chan(mode, i, NULL);
+		if (!chan)
+			return;
+
+		/* Back to HT configuration if channel not usable */
+		if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
+			return;
+	}
+
+	if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
+				    freq->channel, freq->ht_enabled,
+				    vht_freq.vht_enabled,
+				    freq->sec_channel_offset,
+				    VHT_CHANWIDTH_80MHZ,
+				    vht80[i] + 6, 0, 0) != 0)
+		return;
+
+	*freq = vht_freq;
+
+	wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
+		   freq->center_freq1, freq->center_freq2, freq->bandwidth);
 }
 
 
@@ -2114,6 +2204,7 @@
 		ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
 
 	if (ssid->mode == WPAS_MODE_IBSS) {
+		params.fixed_freq = ssid->fixed_freq;
 		if (ssid->beacon_int)
 			params.beacon_int = ssid->beacon_int;
 		else
@@ -3980,6 +4071,23 @@
 	wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
 						      &wpa_s->hw.num_modes,
 						      &wpa_s->hw.flags);
+	if (wpa_s->hw.modes) {
+		u16 i;
+
+		for (i = 0; i < wpa_s->hw.num_modes; i++) {
+			if (wpa_s->hw.modes[i].vht_capab) {
+				wpa_s->hw_capab = CAPAB_VHT;
+				break;
+			}
+
+			if (wpa_s->hw.modes[i].ht_capab &
+			    HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
+				wpa_s->hw_capab = CAPAB_HT40;
+			else if (wpa_s->hw.modes[i].ht_capab &&
+				 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
+				wpa_s->hw_capab = CAPAB_HT;
+		}
+	}
 
 	capa_res = wpa_drv_get_capa(wpa_s, &capa);
 	if (capa_res == 0) {