Cumulative patch from commit 8b48e3200680f71ae083b84793e6bdc2099416d2 [DO NOT MERGE]

8b48e32 wpa_cli: Add MAC address randomization in scan
fb37588 ctrl_iface: Add MAC address randomization in scan processing
56c76fa scan: Add MAC address randomization in scan handling
86056fe nl80211: Handle MAC address randomization in scan/sched_scan
ff23ed2 driver: Add definitions for MAC address randomization in scan
7db53bb wpa_cli: Implement TDLS start/cancel channel switching commands
72b2605 nl80211: Pass TDLS channel-switch start/stop params to kernel
6b90dea TDLS: Propagate enable/disable channel-switch commands to driver
d9d3b78 TDLS: Track TDLS channel switch prohibition in BSS
4daa572 TDLS: Add channel-switch capability flag
ca16586 Sync with wireless-testing.git include/uapi/linux/nl80211.h
8c42b36 WMM AC: Reconfigure tspecs on reassociation to the same BSS
677e7a9 WMM AC: Do not fail on unknown IEs in Association Response
fecc2bb WMM AC: Delete tspecs on roaming
20fe745 WMM AC: Print user-priority in wmm_ac_status
730a0d1 nl80211: Always register management frames handler
...
209702d Add possibility to set the setband parameter
ee82e33 Do not trigger the scan during initialization on Android platforms
e69ae5f Reject new SCAN commands if there is a pending request
...
59d7148 nl80211: Provide subtype and reason code for AP SME drivers
9d4ff04 Add external EAPOL transmission option for testing purposes
61fc904 P2P: Handle improper WPS termination on GO during group formation
58b40fd P2P: Clear p2p_go_group_formation_completed on GO start
c155305 Complete sme-connect radio work when clearing connection state
debb2da P2P: Report group removal reason PSK_FAILURE in timeout case
51465a0 The master branch is now used for v2.4 development

Change-Id: I9b9cfa5c5cd4d26b2f3f5595f7c226ac60de6258
diff --git a/src/common/defs.h b/src/common/defs.h
index d4091e3..e1bbd50 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -49,6 +49,7 @@
 #define WPA_KEY_MGMT_WAPI_CERT BIT(13)
 #define WPA_KEY_MGMT_CCKM BIT(14)
 #define WPA_KEY_MGMT_OSEN BIT(15)
+#define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16)
 
 static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
 {
@@ -56,7 +57,8 @@
 			 WPA_KEY_MGMT_FT_IEEE8021X |
 			 WPA_KEY_MGMT_CCKM |
 			 WPA_KEY_MGMT_OSEN |
-			 WPA_KEY_MGMT_IEEE8021X_SHA256));
+			 WPA_KEY_MGMT_IEEE8021X_SHA256 |
+			 WPA_KEY_MGMT_IEEE8021X_SUITE_B));
 }
 
 static inline int wpa_key_mgmt_wpa_psk(int akm)
@@ -85,7 +87,13 @@
 {
 	return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 |
 			 WPA_KEY_MGMT_IEEE8021X_SHA256 |
-			 WPA_KEY_MGMT_OSEN));
+			 WPA_KEY_MGMT_OSEN |
+			 WPA_KEY_MGMT_IEEE8021X_SUITE_B));
+}
+
+static inline int wpa_key_mgmt_suite_b(int akm)
+{
+	return !!(akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B);
 }
 
 static inline int wpa_key_mgmt_wpa(int akm)
@@ -300,4 +308,25 @@
 /* Maximum number of EAP methods to store for EAP server user information */
 #define EAP_MAX_METHODS 8
 
+/**
+ * enum ht_mode - channel width and offset
+ */
+enum ht_mode {
+	CHAN_UNDEFINED = 0,
+	CHAN_NO_HT,
+	CHAN_HT20,
+	CHAN_HT40PLUS,
+	CHAN_HT40MINUS,
+};
+
+enum mesh_plink_state {
+	PLINK_LISTEN = 1,
+	PLINK_OPEN_SENT,
+	PLINK_OPEN_RCVD,
+	PLINK_CNF_RCVD,
+	PLINK_ESTAB,
+	PLINK_HOLDING,
+	PLINK_BLOCKED,
+};
+
 #endif /* DEFS_H */
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 173a400..e1d45cf 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -249,6 +249,18 @@
 			elems->ht_operation = pos;
 			elems->ht_operation_len = elen;
 			break;
+		case WLAN_EID_MESH_CONFIG:
+			elems->mesh_config = pos;
+			elems->mesh_config_len = elen;
+			break;
+		case WLAN_EID_MESH_ID:
+			elems->mesh_id = pos;
+			elems->mesh_id_len = elen;
+			break;
+		case WLAN_EID_PEER_MGMT:
+			elems->peer_mgmt = pos;
+			elems->peer_mgmt_len = elen;
+			break;
 		case WLAN_EID_VHT_CAP:
 			elems->vht_capabilities = pos;
 			elems->vht_capabilities_len = elen;
@@ -290,6 +302,16 @@
 			elems->ssid_list = pos;
 			elems->ssid_list_len = elen;
 			break;
+		case WLAN_EID_AMPE:
+			elems->ampe = pos;
+			elems->ampe_len = elen;
+			break;
+		case WLAN_EID_MIC:
+			elems->mic = pos;
+			elems->mic_len = elen;
+			/* after mic everything is encrypted, so stop. */
+			left = elen;
+			break;
 		default:
 			unknown++;
 			if (!show_errors)
@@ -515,6 +537,286 @@
 }
 
 
+static const char *us_op_class_cc[] = {
+	"US", "CA", NULL
+};
+
+static const char *eu_op_class_cc[] = {
+	"AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE",
+	"DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT",
+	"LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT",
+	"RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL
+};
+
+static const char *jp_op_class_cc[] = {
+	"JP", NULL
+};
+
+static const char *cn_op_class_cc[] = {
+	"CN", "CA", NULL
+};
+
+
+static int country_match(const char *cc[], const char *country)
+{
+	int i;
+
+	if (country == NULL)
+		return 0;
+	for (i = 0; cc[i]; i++) {
+		if (cc[i][0] == country[0] && cc[i][1] == country[1])
+			return 1;
+	}
+
+	return 0;
+}
+
+
+static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
+{
+	switch (op_class) {
+	case 12: /* channels 1..11 */
+	case 32: /* channels 1..7; 40 MHz */
+	case 33: /* channels 5..11; 40 MHz */
+		if (chan < 1 || chan > 11)
+			return -1;
+		return 2407 + 5 * chan;
+	case 1: /* channels 36,40,44,48 */
+	case 2: /* channels 52,56,60,64; dfs */
+	case 22: /* channels 36,44; 40 MHz */
+	case 23: /* channels 52,60; 40 MHz */
+	case 27: /* channels 40,48; 40 MHz */
+	case 28: /* channels 56,64; 40 MHz */
+		if (chan < 36 || chan > 64)
+			return -1;
+		return 5000 + 5 * chan;
+	case 4: /* channels 100-144 */
+	case 24: /* channels 100-140; 40 MHz */
+		if (chan < 100 || chan > 144)
+			return -1;
+		return 5000 + 5 * chan;
+	case 3: /* channels 149,153,157,161 */
+	case 25: /* channels 149,157; 40 MHz */
+	case 26: /* channels 149,157; 40 MHz */
+	case 30: /* channels 153,161; 40 MHz */
+	case 31: /* channels 153,161; 40 MHz */
+		if (chan < 149 || chan > 161)
+			return -1;
+		return 5000 + 5 * chan;
+	case 34: /* 60 GHz band, channels 1..3 */
+		if (chan < 1 || chan > 3)
+			return -1;
+		return 56160 + 2160 * chan;
+	}
+	return -1;
+}
+
+
+static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
+{
+	switch (op_class) {
+	case 4: /* channels 1..13 */
+	case 11: /* channels 1..9; 40 MHz */
+	case 12: /* channels 5..13; 40 MHz */
+		if (chan < 1 || chan > 13)
+			return -1;
+		return 2407 + 5 * chan;
+	case 1: /* channels 36,40,44,48 */
+	case 2: /* channels 52,56,60,64; dfs */
+	case 5: /* channels 36,44; 40 MHz */
+	case 6: /* channels 52,60; 40 MHz */
+	case 8: /* channels 40,48; 40 MHz */
+	case 9: /* channels 56,64; 40 MHz */
+		if (chan < 36 || chan > 64)
+			return -1;
+		return 5000 + 5 * chan;
+	case 3: /* channels 100-140 */
+	case 7: /* channels 100-132; 40 MHz */
+	case 10: /* channels 104-136; 40 MHz */
+	case 16: /* channels 100-140 */
+		if (chan < 100 || chan > 140)
+			return -1;
+		return 5000 + 5 * chan;
+	case 17: /* channels 149,153,157,161,165,169 */
+		if (chan < 149 || chan > 169)
+			return -1;
+		return 5000 + 5 * chan;
+	case 18: /* 60 GHz band, channels 1..4 */
+		if (chan < 1 || chan > 4)
+			return -1;
+		return 56160 + 2160 * chan;
+	}
+	return -1;
+}
+
+
+static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
+{
+	switch (op_class) {
+	case 30: /* channels 1..13 */
+	case 56: /* channels 1..9; 40 MHz */
+	case 57: /* channels 5..13; 40 MHz */
+		if (chan < 1 || chan > 13)
+			return -1;
+		return 2407 + 5 * chan;
+	case 31: /* channel 14 */
+		if (chan != 14)
+			return -1;
+		return 2414 + 5 * chan;
+	case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */
+	case 32: /* channels 52,56,60,64 */
+	case 33: /* channels 52,56,60,64 */
+	case 36: /* channels 36,44; 40 MHz */
+	case 37: /* channels 52,60; 40 MHz */
+	case 38: /* channels 52,60; 40 MHz */
+	case 41: /* channels 40,48; 40 MHz */
+	case 42: /* channels 56,64; 40 MHz */
+	case 43: /* channels 56,64; 40 MHz */
+		if (chan < 34 || chan > 64)
+			return -1;
+		return 5000 + 5 * chan;
+	case 34: /* channels 100-140 */
+	case 35: /* channels 100-140 */
+	case 39: /* channels 100-132; 40 MHz */
+	case 40: /* channels 100-132; 40 MHz */
+	case 44: /* channels 104-136; 40 MHz */
+	case 45: /* channels 104-136; 40 MHz */
+	case 58: /* channels 100-140 */
+		if (chan < 100 || chan > 140)
+			return -1;
+		return 5000 + 5 * chan;
+	case 59: /* 60 GHz band, channels 1..4 */
+		if (chan < 1 || chan > 3)
+			return -1;
+		return 56160 + 2160 * chan;
+	}
+	return -1;
+}
+
+
+static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
+{
+	switch (op_class) {
+	case 7: /* channels 1..13 */
+	case 8: /* channels 1..9; 40 MHz */
+	case 9: /* channels 5..13; 40 MHz */
+		if (chan < 1 || chan > 13)
+			return -1;
+		return 2407 + 5 * chan;
+	case 1: /* channels 36,40,44,48 */
+	case 2: /* channels 52,56,60,64; dfs */
+	case 4: /* channels 36,44; 40 MHz */
+	case 5: /* channels 52,60; 40 MHz */
+		if (chan < 36 || chan > 64)
+			return -1;
+		return 5000 + 5 * chan;
+	case 3: /* channels 149,153,157,161,165 */
+	case 6: /* channels 149,157; 40 MHz */
+		if (chan < 149 || chan > 165)
+			return -1;
+		return 5000 + 5 * chan;
+	}
+	return -1;
+}
+
+
+static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
+{
+	/* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
+	switch (op_class) {
+	case 81:
+		/* channels 1..13 */
+		if (chan < 1 || chan > 13)
+			return -1;
+		return 2407 + 5 * chan;
+	case 82:
+		/* channel 14 */
+		if (chan != 14)
+			return -1;
+		return 2414 + 5 * chan;
+	case 83: /* channels 1..9; 40 MHz */
+	case 84: /* channels 5..13; 40 MHz */
+		if (chan < 1 || chan > 13)
+			return -1;
+		return 2407 + 5 * chan;
+	case 115: /* channels 36,40,44,48; indoor only */
+	case 116: /* channels 36,44; 40 MHz; indoor only */
+	case 117: /* channels 40,48; 40 MHz; indoor only */
+	case 118: /* channels 52,56,60,64; dfs */
+	case 119: /* channels 52,60; 40 MHz; dfs */
+	case 120: /* channels 56,64; 40 MHz; dfs */
+		if (chan < 36 || chan > 64)
+			return -1;
+		return 5000 + 5 * chan;
+	case 121: /* channels 100-140 */
+	case 122: /* channels 100-142; 40 MHz */
+	case 123: /* channels 104-136; 40 MHz */
+		if (chan < 100 || chan > 140)
+			return -1;
+		return 5000 + 5 * chan;
+	case 124: /* channels 149,153,157,161 */
+	case 125: /* channels 149,153,157,161,165,169 */
+	case 126: /* channels 149,157; 40 MHz */
+	case 127: /* channels 153,161; 40 MHz */
+		if (chan < 149 || chan > 161)
+			return -1;
+		return 5000 + 5 * chan;
+	case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
+	case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
+		if (chan < 36 || chan > 161)
+			return -1;
+		return 5000 + 5 * chan;
+	case 129: /* center freqs 50, 114; 160 MHz */
+		if (chan < 50 || chan > 114)
+			return -1;
+		return 5000 + 5 * chan;
+	case 180: /* 60 GHz band, channels 1..4 */
+		if (chan < 1 || chan > 4)
+			return -1;
+		return 56160 + 2160 * chan;
+	}
+	return -1;
+}
+
+/**
+ * ieee80211_chan_to_freq - Convert channel info to frequency
+ * @country: Country code, if known; otherwise, global operating class is used
+ * @op_class: Operating class
+ * @chan: Channel number
+ * Returns: Frequency in MHz or -1 if the specified channel is unknown
+ */
+int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
+{
+	int freq;
+
+	if (country_match(us_op_class_cc, country)) {
+		freq = ieee80211_chan_to_freq_us(op_class, chan);
+		if (freq > 0)
+			return freq;
+	}
+
+	if (country_match(eu_op_class_cc, country)) {
+		freq = ieee80211_chan_to_freq_eu(op_class, chan);
+		if (freq > 0)
+			return freq;
+	}
+
+	if (country_match(jp_op_class_cc, country)) {
+		freq = ieee80211_chan_to_freq_jp(op_class, chan);
+		if (freq > 0)
+			return freq;
+	}
+
+	if (country_match(cn_op_class_cc, country)) {
+		freq = ieee80211_chan_to_freq_cn(op_class, chan);
+		if (freq > 0)
+			return freq;
+	}
+
+	return ieee80211_chan_to_freq_global(op_class, chan);
+}
+
+
 static int is_11b(u8 rate)
 {
 	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index cf83057..2357afc 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -28,6 +28,9 @@
 	const u8 *timeout_int;
 	const u8 *ht_capabilities;
 	const u8 *ht_operation;
+	const u8 *mesh_config;
+	const u8 *mesh_id;
+	const u8 *peer_mgmt;
 	const u8 *vht_capabilities;
 	const u8 *vht_operation;
 	const u8 *vht_opmode_notif;
@@ -42,6 +45,8 @@
 	const u8 *bss_max_idle_period;
 	const u8 *ssid_list;
 	const u8 *osen;
+	const u8 *ampe;
+	const u8 *mic;
 
 	u8 ssid_len;
 	u8 supp_rates_len;
@@ -60,6 +65,9 @@
 	u8 timeout_int_len;
 	u8 ht_capabilities_len;
 	u8 ht_operation_len;
+	u8 mesh_config_len;
+	u8 mesh_id_len;
+	u8 peer_mgmt_len;
 	u8 vht_capabilities_len;
 	u8 vht_operation_len;
 	u8 vendor_ht_cap_len;
@@ -71,6 +79,8 @@
 	u8 ext_capab_len;
 	u8 ssid_list_len;
 	u8 osen_len;
+	u8 ampe_len;
+	u8 mic_len;
 };
 
 typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
@@ -95,6 +105,7 @@
 int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
 			  const char *name, const char *val);
 enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel);
+int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan);
 
 int supp_rates_11b_only(struct ieee802_11_elems *elems);
 
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 6de71e9..dfe0faf 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -25,6 +25,8 @@
 #define WLAN_FC_GET_TYPE(fc)	(((fc) & 0x000c) >> 2)
 #define WLAN_FC_GET_STYPE(fc)	(((fc) & 0x00f0) >> 4)
 
+#define WLAN_INVALID_MGMT_SEQ   0xFFFF
+
 #define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0)))
 #define WLAN_GET_SEQ_SEQ(seq) \
 	(((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4)
@@ -194,6 +196,16 @@
 #define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26
 /* IEEE 802.11e */
 #define WLAN_REASON_DISASSOC_LOW_ACK 34
+/* IEEE 802.11s */
+#define WLAN_REASON_MESH_PEERING_CANCELLED 52
+#define WLAN_REASON_MESH_MAX_PEERS 53
+#define WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION 54
+#define WLAN_REASON_MESH_CLOSE_RCVD 55
+#define WLAN_REASON_MESH_MAX_RETRIES 56
+#define WLAN_REASON_MESH_CONFIRM_TIMEOUT 57
+#define WLAN_REASON_MESH_INVALID_GTK 58
+#define WLAN_REASON_MESH_INCONSISTENT_PARAMS 59
+#define WLAN_REASON_MESH_INVALID_SECURITY_CAP 60
 
 
 /* Information Element IDs */
@@ -234,6 +246,7 @@
 #define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
 #define WLAN_EID_WAPI 68
 #define WLAN_EID_TIME_ADVERTISEMENT 69
+#define WLAN_EID_RRM_ENABLED_CAPABILITIES 70
 #define WLAN_EID_20_40_BSS_COEXISTENCE 72
 #define WLAN_EID_20_40_BSS_INTOLERANT 73
 #define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
@@ -249,7 +262,12 @@
 #define WLAN_EID_ADV_PROTO 108
 #define WLAN_EID_QOS_MAP_SET 110
 #define WLAN_EID_ROAMING_CONSORTIUM 111
+#define WLAN_EID_MESH_CONFIG 113
+#define WLAN_EID_MESH_ID 114
+#define WLAN_EID_PEER_MGMT 117
 #define WLAN_EID_EXT_CAPAB 127
+#define WLAN_EID_AMPE 139
+#define WLAN_EID_MIC 140
 #define WLAN_EID_CCKM 156
 #define WLAN_EID_VHT_CAP 191
 #define WLAN_EID_VHT_OPERATION 192
@@ -277,6 +295,7 @@
 #define WLAN_ACTION_WNM 10
 #define WLAN_ACTION_UNPROTECTED_WNM 11
 #define WLAN_ACTION_TDLS 12
+#define WLAN_ACTION_SELF_PROTECTED 15
 #define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
 #define WLAN_ACTION_VENDOR_SPECIFIC 127
 
@@ -321,6 +340,19 @@
 #define WLAN_TDLS_PEER_TRAFFIC_RESPONSE 9
 #define WLAN_TDLS_DISCOVERY_REQUEST 10
 
+/* Radio Measurement Action codes */
+#define WLAN_RRM_RADIO_MEASUREMENT_REQUEST 0
+#define WLAN_RRM_RADIO_MEASUREMENT_REPORT 1
+#define WLAN_RRM_LINK_MEASUREMENT_REQUEST 2
+#define WLAN_RRM_LINK_MEASUREMENT_REPORT 3
+#define WLAN_RRM_NEIGHBOR_REPORT_REQUEST 4
+#define WLAN_RRM_NEIGHBOR_REPORT_RESPONSE 5
+
+/* Radio Measurement capabilities (from RRM Capabilities IE) */
+/* byte 1 (out of 5) */
+#define WLAN_RRM_CAPS_LINK_MEASUREMENT BIT(0)
+#define WLAN_RRM_CAPS_NEIGHBOR_REPORT BIT(1)
+
 /* Timeout Interval Type */
 #define WLAN_TIMEOUT_REASSOC_DEADLINE 1
 #define WLAN_TIMEOUT_KEY_LIFETIME 2
@@ -577,6 +609,10 @@
 					 * Entries (optional) */
 					u8 variable[0];
 				} STRUCT_PACKED bss_tm_query;
+				struct {
+					u8 action; /* 15 */
+					u8 variable[0];
+				} STRUCT_PACKED slf_prot_action;
 			} u;
 		} STRUCT_PACKED action;
 	} u;
@@ -638,6 +674,15 @@
 	le16 vht_basic_mcs_set;
 } STRUCT_PACKED;
 
+struct ieee80211_ampe_ie {
+	u8 selected_pairwise_suite[4];
+	u8 local_nonce[32];
+	u8 peer_nonce[32];
+	u8 mgtk[16];
+	u8 key_rsc[8];
+	u8 key_expiration[4];
+} STRUCT_PACKED;
+
 #ifdef _MSC_VER
 #pragma pack(pop)
 #endif /* _MSC_VER */
@@ -754,6 +799,7 @@
 #define VHT_CAP_MAX_MPDU_LENGTH_7991                ((u32) BIT(0))
 #define VHT_CAP_MAX_MPDU_LENGTH_11454               ((u32) BIT(1))
 #define VHT_CAP_MAX_MPDU_LENGTH_MASK                ((u32) BIT(0) | BIT(1))
+#define VHT_CAP_MAX_MPDU_LENGTH_MASK_SHIFT          0
 #define VHT_CAP_SUPP_CHAN_WIDTH_160MHZ              ((u32) BIT(2))
 #define VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ     ((u32) BIT(3))
 #define VHT_CAP_SUPP_CHAN_WIDTH_MASK                ((u32) BIT(2) | BIT(3))
@@ -767,13 +813,16 @@
 #define VHT_CAP_RXSTBC_4                            ((u32) BIT(10))
 #define VHT_CAP_RXSTBC_MASK                         ((u32) BIT(8) | BIT(9) | \
 							   BIT(10))
+#define VHT_CAP_RXSTBC_MASK_SHIFT                   8
 #define VHT_CAP_SU_BEAMFORMER_CAPABLE               ((u32) BIT(11))
 #define VHT_CAP_SU_BEAMFORMEE_CAPABLE               ((u32) BIT(12))
 #define VHT_CAP_BEAMFORMEE_STS_MAX                  ((u32) BIT(13) | \
 							   BIT(14) | BIT(15))
+#define VHT_CAP_BEAMFORMEE_STS_MAX_SHIFT            13
 #define VHT_CAP_BEAMFORMEE_STS_OFFSET               13
 #define VHT_CAP_SOUNDING_DIMENSION_MAX              ((u32) BIT(16) | \
 							   BIT(17) | BIT(18))
+#define VHT_CAP_SOUNDING_DIMENSION_MAX_SHIFT        16
 #define VHT_CAP_SOUNDING_DIMENSION_OFFSET           16
 #define VHT_CAP_MU_BEAMFORMER_CAPABLE               ((u32) BIT(19))
 #define VHT_CAP_MU_BEAMFORMEE_CAPABLE               ((u32) BIT(20))
@@ -788,6 +837,7 @@
 #define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_6        ((u32) BIT(24) | BIT(25))
 #define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX      ((u32) BIT(23) | \
 							   BIT(24) | BIT(25))
+#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT 23
 #define VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB   ((u32) BIT(27))
 #define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB     ((u32) BIT(26) | BIT(27))
 #define VHT_CAP_RX_ANTENNA_PATTERN                  ((u32) BIT(28))
@@ -855,6 +905,8 @@
 
 } STRUCT_PACKED;
 
+#define WMM_QOSINFO_AP_UAPSD 0x80
+
 #define WMM_QOSINFO_STA_AC_MASK 0x0f
 #define WMM_QOSINFO_STA_SP_MASK 0x03
 #define WMM_QOSINFO_STA_SP_SHIFT 5
@@ -922,11 +974,12 @@
 
 
 /* Access Categories / ACI to AC coding */
-enum {
+enum wmm_ac {
 	WMM_AC_BE = 0 /* Best Effort */,
 	WMM_AC_BK = 1 /* Background */,
 	WMM_AC_VI = 2 /* Video */,
-	WMM_AC_VO = 3 /* Voice */
+	WMM_AC_VO = 3 /* Voice */,
+	WMM_AC_NUM = 4
 };
 
 
@@ -1087,6 +1140,19 @@
 	WFD_SUBELEM_SESSION_INFO = 9
 };
 
+/* 802.11s */
+#define MESH_SYNC_METHOD_NEIGHBOR_OFFSET 1
+#define MESH_SYNC_METHOD_VENDOR		255
+#define MESH_PATH_PROTOCOL_HWMP		1
+#define MESH_PATH_PROTOCOL_VENDOR	255
+#define MESH_PATH_METRIC_AIRTIME	1
+#define MESH_PATH_METRIC_VENDOR		255
+
+enum plink_action_field {
+	PLINK_OPEN = 1,
+	PLINK_CONFIRM,
+	PLINK_CLOSE
+};
 
 #define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
 
@@ -1122,6 +1188,7 @@
 #define WLAN_AKM_SUITE_FT_PSK		0x000FAC04
 #define WLAN_AKM_SUITE_8021X_SHA256	0x000FAC05
 #define WLAN_AKM_SUITE_PSK_SHA256	0x000FAC06
+#define WLAN_AKM_SUITE_8021X_SUITE_B	0x000FAC11
 #define WLAN_AKM_SUITE_CCKM		0x00409600
 #define WLAN_AKM_SUITE_OSEN		0x506f9a01
 
@@ -1247,4 +1314,30 @@
 #define CHAN_SWITCH_MODE_ALLOW_TX	0
 #define CHAN_SWITCH_MODE_BLOCK_TX	1
 
+struct tpc_report {
+	u8 eid;
+	u8 len;
+	u8 tx_power;
+	u8 link_margin;
+} STRUCT_PACKED;
+
+/* IEEE Std 802.11-2012, 8.5.7.4 - Link Measurement Request frame format */
+struct rrm_link_measurement_request {
+	u8 dialog_token;
+	s8 tx_power;
+	s8 max_tp;
+	u8 variable[0];
+} STRUCT_PACKED;
+
+/* IEEE Std 802.11-2012, 8.5.7.5 - Link Measurement Report frame format */
+struct rrm_link_measurement_report {
+	u8 dialog_token;
+	struct tpc_report tpc;
+	u8 rx_ant_id;
+	u8 tx_ant_id;
+	u8 rcpi;
+	u8 rsni;
+	u8 variable[0];
+} STRUCT_PACKED;
+
 #endif /* IEEE802_11_DEFS_H */
diff --git a/src/common/privsep_commands.h b/src/common/privsep_commands.h
index 858b51d..4dc34c4 100644
--- a/src/common/privsep_commands.h
+++ b/src/common/privsep_commands.h
@@ -31,7 +31,9 @@
 	u8 bssid[ETH_ALEN];
 	u8 ssid[32];
 	size_t ssid_len;
+	int hwmode;
 	int freq;
+	int channel;
 	int pairwise_suite;
 	int group_suite;
 	int key_mgmt_suite;
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index ad3bdfd..ec1be86 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -50,6 +50,25 @@
  * @QCA_NL80211_VENDOR_SUBCMD_NAN: NAN command/event which is used to pass
  *	NAN Request/Response and NAN Indication messages. These messages are
  *	interpreted between the framework and the firmware component.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY: Set key operation that can be
+ *	used to configure PMK to the driver even when not connected. This can
+ *	be used to request offloading of key management operations. Only used
+ *	if device supports QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH: An extended version of
+ *	NL80211_CMD_ROAM event with optional attributes including information
+ *	from offloaded key management operation. Uses
+ *	enum qca_wlan_vendor_attr_roam_auth attributes. Only used
+ *	if device supports QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DO_ACS: ACS command/event which is used to
+ *	invoke the ACS function in device and pass selected channels to
+ *	hostapd.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES: Command to get the features
+ *	supported by the driver. enum qca_wlan_vendor_features defines
+ *	the possible features.
  */
 enum qca_nl80211_vendor_subcmds {
 	QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -60,7 +79,42 @@
 	QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY =  11,
 	QCA_NL80211_VENDOR_SUBCMD_NAN =  12,
 	QCA_NL80211_VENDOR_SUBMCD_STATS_EXT = 13,
-	/* 14..49 - reserved for QCA */
+	QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET = 14,
+	QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET = 15,
+	QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR = 16,
+	QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS = 17,
+	QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS = 18,
+	QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS = 19,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_START = 20,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_STOP = 21,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS = 22,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES = 23,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS = 24,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE = 25,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT = 26,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT = 27,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND = 28,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST = 29,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_BSSID_HOTLIST = 30,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE = 31,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE = 32,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_SIGNIFICANT_CHANGE = 33,
+	QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE = 34,
+	QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE = 35,
+	QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS = 36,
+	QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE = 37,
+	QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES = 38,
+	QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI = 39,
+	QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG = 40,
+	QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_LOST = 41,
+	QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX = 42,
+	/* 43..49 - reserved for QCA */
+	QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY = 50,
+	QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH = 51,
+	QCA_NL80211_VENDOR_SUBCMD_APFIND = 52,
+	/* 53 - reserved for QCA */
+	QCA_NL80211_VENDOR_SUBCMD_DO_ACS = 54,
+	QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES = 55,
 };
 
 
@@ -78,6 +132,8 @@
 	 * by enum qca_roaming_policy. */
 	QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY = 5,
 	QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6,
+	/* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */
+	QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS = 7,
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_MAX	= QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
@@ -89,4 +145,53 @@
 	QCA_ROAMING_ALLOWED_WITHIN_ESS,
 };
 
+enum qca_wlan_vendor_attr_roam_auth {
+	QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
+	QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
+	QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
+	QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
+	QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
+	QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
+	QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX =
+	QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST - 1
+};
+
+enum qca_wlan_vendor_attr_acs_offload {
+	QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
+	QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
+	QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
+	QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED,
+	QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED,
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_ACS_MAX =
+	QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST - 1
+};
+
+enum qca_wlan_vendor_acs_hw_mode {
+	QCA_ACS_MODE_IEEE80211B,
+	QCA_ACS_MODE_IEEE80211G,
+	QCA_ACS_MODE_IEEE80211A,
+	QCA_ACS_MODE_IEEE80211AD,
+};
+
+/**
+ * enum qca_wlan_vendor_features - Vendor device/driver feature flags
+ *
+ * @QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD: Device supports key
+ *	management offload, a mechanism where the station's firmware
+ *	does the exchange with the AP to establish the temporal keys
+ *	after roaming, rather than having the user space wpa_supplicant do it.
+ * @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
+ */
+enum qca_wlan_vendor_features {
+	QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD	= 0,
+	NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
+};
+
 #endif /* QCA_VENDOR_H */
diff --git a/src/common/sae.c b/src/common/sae.c
index b67623f..5888958 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -87,7 +87,8 @@
 	crypto_ec_point_deinit(tmp->pwe_ecc, 1);
 	crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0);
 	crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0);
-	os_free(sae->tmp);
+	wpabuf_free(tmp->anti_clogging_token);
+	bin_clear_free(tmp, sizeof(*tmp));
 	sae->tmp = NULL;
 }
 
@@ -623,8 +624,10 @@
 	wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
 	sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK",
 		   val, sae->tmp->prime_len, keys, sizeof(keys));
+	os_memset(keyseed, 0, sizeof(keyseed));
 	os_memcpy(sae->tmp->kck, keys, SAE_KCK_LEN);
 	os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN);
+	os_memset(keys, 0, sizeof(keys));
 	wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, SAE_KCK_LEN);
 	wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN);
 
@@ -656,8 +659,11 @@
 		return;
 
 	wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
-	if (token)
+	if (token) {
 		wpabuf_put_buf(buf, token);
+		wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token",
+			    wpabuf_head(token), wpabuf_len(token));
+	}
 	pos = wpabuf_put(buf, sae->tmp->prime_len);
 	crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
 			     sae->tmp->prime_len, sae->tmp->prime_len);
@@ -682,8 +688,7 @@
 }
 
 
-static u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups,
-			     u16 group)
+u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group)
 {
 	if (allowed_groups) {
 		int i;
diff --git a/src/common/sae.h b/src/common/sae.h
index d82a98e..89d74ab 100644
--- a/src/common/sae.h
+++ b/src/common/sae.h
@@ -35,6 +35,7 @@
 	const struct crypto_bignum *order;
 	struct crypto_bignum *prime_buf;
 	struct crypto_bignum *order_buf;
+	struct wpabuf *anti_clogging_token;
 };
 
 struct sae_data {
@@ -60,5 +61,6 @@
 		     const u8 **token, size_t *token_len, int *allowed_groups);
 void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf);
 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len);
+u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group);
 
 #endif /* SAE_H */
diff --git a/src/common/version.h b/src/common/version.h
index 726289d..c662270 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -5,6 +5,6 @@
 #define VERSION_STR_POSTFIX ""
 #endif /* VERSION_STR_POSTFIX */
 
-#define VERSION_STR "2.3" VERSION_STR_POSTFIX
+#define VERSION_STR "2.4-devel" VERSION_STR_POSTFIX
 
 #endif /* VERSION_H */
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index 998a51a..a573e11 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -14,7 +14,6 @@
 #include "crypto/sha256.h"
 #include "crypto/aes_wrap.h"
 #include "crypto/crypto.h"
-#include "drivers/driver.h"
 #include "ieee802_11_defs.h"
 #include "defs.h"
 #include "wpa_common.h"
@@ -23,6 +22,7 @@
 /**
  * wpa_eapol_key_mic - Calculate EAPOL-Key MIC
  * @key: EAPOL-Key Key Confirmation Key (KCK)
+ * @akmp: WPA_KEY_MGMT_* used in key derivation
  * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
  * @buf: Pointer to the beginning of the EAPOL header (version field)
  * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame)
@@ -38,10 +38,10 @@
  * happened during final editing of the standard and the correct behavior is
  * defined in the last draft (IEEE 802.11i/D10).
  */
-int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
-		      u8 *mic)
+int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf,
+		      size_t len, u8 *mic)
 {
-	u8 hash[SHA1_MAC_LEN];
+	u8 hash[SHA256_MAC_LEN];
 
 	switch (ver) {
 #ifndef CONFIG_FIPS
@@ -57,11 +57,23 @@
 	case WPA_KEY_INFO_TYPE_AES_128_CMAC:
 		return omac1_aes_128(key, buf, len, mic);
 #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
-#ifdef CONFIG_HS20
 	case WPA_KEY_INFO_TYPE_AKM_DEFINED:
-		/* FIX: This should be based on negotiated AKM */
-		return omac1_aes_128(key, buf, len, mic);
+		switch (akmp) {
+#ifdef CONFIG_HS20
+		case WPA_KEY_MGMT_OSEN:
+			return omac1_aes_128(key, buf, len, mic);
 #endif /* CONFIG_HS20 */
+#ifdef CONFIG_SUITEB
+		case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
+			if (hmac_sha256(key, 16, buf, len, hash))
+				return -1;
+			os_memcpy(mic, hash, MD5_MAC_LEN);
+			break;
+#endif /* CONFIG_SUITEB */
+		default:
+			return -1;
+		}
+		break;
 	default:
 		return -1;
 	}
@@ -399,6 +411,8 @@
 	if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE)
 		return WPA_KEY_MGMT_FT_SAE;
 #endif /* CONFIG_SAE */
+	if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B)
+		return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
 	return 0;
 }
 
@@ -496,7 +510,7 @@
 		count = WPA_GET_LE16(pos);
 		pos += 2;
 		left -= 2;
-		if (count == 0 || left < count * RSN_SELECTOR_LEN) {
+		if (count == 0 || count > left / RSN_SELECTOR_LEN) {
 			wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
 				   "count %u left %u", __func__, count, left);
 			return -4;
@@ -524,7 +538,7 @@
 		count = WPA_GET_LE16(pos);
 		pos += 2;
 		left -= 2;
-		if (count == 0 || left < count * RSN_SELECTOR_LEN) {
+		if (count == 0 || count > left / RSN_SELECTOR_LEN) {
 			wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
 				   "count %u left %u", __func__, count, left);
 			return -6;
@@ -547,17 +561,17 @@
 	}
 
 	if (left >= 2) {
-		data->num_pmkid = WPA_GET_LE16(pos);
+		u16 num_pmkid = WPA_GET_LE16(pos);
 		pos += 2;
 		left -= 2;
-		if (left < (int) data->num_pmkid * PMKID_LEN) {
+		if (num_pmkid > (unsigned int) left / PMKID_LEN) {
 			wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
-				   "(num_pmkid=%lu left=%d)",
-				   __func__, (unsigned long) data->num_pmkid,
-				   left);
+				   "(num_pmkid=%u left=%d)",
+				   __func__, num_pmkid, left);
 			data->num_pmkid = 0;
 			return -9;
 		} else {
+			data->num_pmkid = num_pmkid;
 			data->pmkid = pos;
 			pos += data->num_pmkid * PMKID_LEN;
 			left -= data->num_pmkid * PMKID_LEN;
@@ -674,7 +688,7 @@
 		count = WPA_GET_LE16(pos);
 		pos += 2;
 		left -= 2;
-		if (count == 0 || left < count * WPA_SELECTOR_LEN) {
+		if (count == 0 || count > left / WPA_SELECTOR_LEN) {
 			wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
 				   "count %u left %u", __func__, count, left);
 			return -4;
@@ -695,7 +709,7 @@
 		count = WPA_GET_LE16(pos);
 		pos += 2;
 		left -= 2;
-		if (count == 0 || left < count * WPA_SELECTOR_LEN) {
+		if (count == 0 || count > left / WPA_SELECTOR_LEN) {
 			wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
 				   "count %u left %u", __func__, count, left);
 			return -6;
@@ -928,6 +942,39 @@
 }
 
 
+#ifdef CONFIG_SUITEB
+/**
+ * rsn_pmkid_suite_b - Calculate PMK identifier for Suite B AKM
+ * @kck: Key confirmation key
+ * @kck_len: Length of kck in bytes
+ * @aa: Authenticator address
+ * @spa: Supplicant address
+ * @pmkid: Buffer for PMKID
+ * Returns: 0 on success, -1 on failure
+ *
+ * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
+ * PMKID = Truncate(HMAC-SHA-256(KCK, "PMK Name" || AA || SPA))
+ */
+int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
+		      const u8 *spa, u8 *pmkid)
+{
+	char *title = "PMK Name";
+	const u8 *addr[3];
+	const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
+	unsigned char hash[SHA256_MAC_LEN];
+
+	addr[0] = (u8 *) title;
+	addr[1] = aa;
+	addr[2] = spa;
+
+	if (hmac_sha256_vector(kck, kck_len, 3, addr, len, hash) < 0)
+		return -1;
+	os_memcpy(pmkid, hash, PMKID_LEN);
+	return 0;
+}
+#endif /* CONFIG_SUITEB */
+
+
 /**
  * wpa_cipher_txt - Convert cipher suite to a text string
  * @cipher: Cipher suite (WPA_CIPHER_* enum)
@@ -997,6 +1044,16 @@
 	case WPA_KEY_MGMT_PSK_SHA256:
 		return "WPA2-PSK-SHA256";
 #endif /* CONFIG_IEEE80211W */
+	case WPA_KEY_MGMT_WPS:
+		return "WPS";
+	case WPA_KEY_MGMT_SAE:
+		return "SAE";
+	case WPA_KEY_MGMT_FT_SAE:
+		return "FT-SAE";
+	case WPA_KEY_MGMT_OSEN:
+		return "OSEN";
+	case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
+		return "WPA2-EAP-SUITE-B";
 	default:
 		return "UNKNOWN";
 	}
@@ -1023,6 +1080,8 @@
 		return WLAN_AKM_SUITE_CCKM;
 	if (akm & WPA_KEY_MGMT_OSEN)
 		return WLAN_AKM_SUITE_OSEN;
+	if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
+		return WLAN_AKM_SUITE_8021X_SUITE_B;
 	return 0;
 }
 
@@ -1417,56 +1476,56 @@
 	if (ciphers & WPA_CIPHER_CCMP_256) {
 		ret = os_snprintf(pos, end - pos, "%sCCMP-256",
 				  pos == start ? "" : delim);
-		if (ret < 0 || ret >= end - pos)
+		if (os_snprintf_error(end - pos, ret))
 			return -1;
 		pos += ret;
 	}
 	if (ciphers & WPA_CIPHER_GCMP_256) {
 		ret = os_snprintf(pos, end - pos, "%sGCMP-256",
 				  pos == start ? "" : delim);
-		if (ret < 0 || ret >= end - pos)
+		if (os_snprintf_error(end - pos, ret))
 			return -1;
 		pos += ret;
 	}
 	if (ciphers & WPA_CIPHER_CCMP) {
 		ret = os_snprintf(pos, end - pos, "%sCCMP",
 				  pos == start ? "" : delim);
-		if (ret < 0 || ret >= end - pos)
+		if (os_snprintf_error(end - pos, ret))
 			return -1;
 		pos += ret;
 	}
 	if (ciphers & WPA_CIPHER_GCMP) {
 		ret = os_snprintf(pos, end - pos, "%sGCMP",
 				  pos == start ? "" : delim);
-		if (ret < 0 || ret >= end - pos)
+		if (os_snprintf_error(end - pos, ret))
 			return -1;
 		pos += ret;
 	}
 	if (ciphers & WPA_CIPHER_TKIP) {
 		ret = os_snprintf(pos, end - pos, "%sTKIP",
 				  pos == start ? "" : delim);
-		if (ret < 0 || ret >= end - pos)
+		if (os_snprintf_error(end - pos, ret))
 			return -1;
 		pos += ret;
 	}
 	if (ciphers & WPA_CIPHER_WEP104) {
 		ret = os_snprintf(pos, end - pos, "%sWEP104",
 				  pos == start ? "" : delim);
-		if (ret < 0 || ret >= end - pos)
+		if (os_snprintf_error(end - pos, ret))
 			return -1;
 		pos += ret;
 	}
 	if (ciphers & WPA_CIPHER_WEP40) {
 		ret = os_snprintf(pos, end - pos, "%sWEP40",
 				  pos == start ? "" : delim);
-		if (ret < 0 || ret >= end - pos)
+		if (os_snprintf_error(end - pos, ret))
 			return -1;
 		pos += ret;
 	}
 	if (ciphers & WPA_CIPHER_NONE) {
 		ret = os_snprintf(pos, end - pos, "%sNONE",
 				  pos == start ? "" : delim);
-		if (ret < 0 || ret >= end - pos)
+		if (os_snprintf_error(end - pos, ret))
 			return -1;
 		pos += ret;
 	}
@@ -1497,78 +1556,3 @@
 		return WPA_CIPHER_CCMP_256;
 	return WPA_CIPHER_CCMP;
 }
-
-
-static int wpa_check_wowlan_trigger(const char *start, const char *trigger,
-				    int capa_trigger, u8 *param_trigger)
-{
-	if (os_strcmp(start, trigger) != 0)
-		return 0;
-	if (!capa_trigger)
-		return 0;
-
-	*param_trigger = 1;
-	return 1;
-}
-
-
-struct wowlan_triggers *wpa_get_wowlan_triggers(const char *wowlan_triggers,
-						struct wpa_driver_capa *capa)
-{
-	struct wowlan_triggers *triggers;
-	char *start, *end, *buf;
-	int last;
-
-	if (!wowlan_triggers)
-		return NULL;
-
-	buf = os_strdup(wowlan_triggers);
-	if (buf == NULL)
-		return NULL;
-
-	triggers = os_zalloc(sizeof(*triggers));
-	if (triggers == NULL)
-		goto out;
-
-#define CHECK_TRIGGER(trigger) \
-	wpa_check_wowlan_trigger(start, #trigger,			\
-				  capa->wowlan_triggers.trigger,	\
-				  &triggers->trigger)
-
-	start = buf;
-	while (*start != '\0') {
-		while (isblank(*start))
-			start++;
-		if (*start == '\0')
-			break;
-		end = start;
-		while (!isblank(*end) && *end != '\0')
-			end++;
-		last = *end == '\0';
-		*end = '\0';
-
-		if (!CHECK_TRIGGER(any) &&
-		    !CHECK_TRIGGER(disconnect) &&
-		    !CHECK_TRIGGER(magic_pkt) &&
-		    !CHECK_TRIGGER(gtk_rekey_failure) &&
-		    !CHECK_TRIGGER(eap_identity_req) &&
-		    !CHECK_TRIGGER(four_way_handshake) &&
-		    !CHECK_TRIGGER(rfkill_release)) {
-			wpa_printf(MSG_DEBUG,
-				   "Unknown/unsupported wowlan trigger '%s'",
-				   start);
-			os_free(triggers);
-			triggers = NULL;
-			goto out;
-		}
-
-		if (last)
-			break;
-		start = end + 1;
-	}
-#undef CHECK_TRIGGER
-
-out:
-	os_free(buf);
-	return triggers;
-}
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index 0ef5a9d..17bed34 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -327,8 +327,8 @@
 #endif /* _MSC_VER */
 
 
-int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
-		      u8 *mic);
+int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf,
+		      size_t len, u8 *mic);
 void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
 		    const u8 *addr1, const u8 *addr2,
 		    const u8 *nonce1, const u8 *nonce2,
@@ -374,6 +374,16 @@
 
 void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
 	       u8 *pmkid, int use_sha256);
+#ifdef CONFIG_SUITEB
+int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
+		       const u8 *spa, u8 *pmkid);
+#else /* CONFIG_SUITEB */
+static inline int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
+				    const u8 *spa, u8 *pmkid)
+{
+	return -1;
+}
+#endif /* CONFIG_SUITEB */
 
 const char * wpa_cipher_txt(int cipher);
 const char * wpa_key_mgmt_txt(int key_mgmt, int proto);
diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c
index 5820a13..ccaaf1b 100644
--- a/src/common/wpa_ctrl.c
+++ b/src/common/wpa_ctrl.c
@@ -94,10 +94,9 @@
 	if (ctrl_path == NULL)
 		return NULL;
 
-	ctrl = os_malloc(sizeof(*ctrl));
+	ctrl = os_zalloc(sizeof(*ctrl));
 	if (ctrl == NULL)
 		return NULL;
-	os_memset(ctrl, 0, sizeof(*ctrl));
 
 	ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
 	if (ctrl->s < 0) {
@@ -112,7 +111,7 @@
 			  CONFIG_CTRL_IFACE_CLIENT_DIR "/"
 			  CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d",
 			  (int) getpid(), counter);
-	if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
+	if (os_snprintf_error(sizeof(ctrl->local.sun_path), ret)) {
 		close(ctrl->s);
 		os_free(ctrl);
 		return NULL;
@@ -283,10 +282,9 @@
 	struct hostent *h;
 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
 
-	ctrl = os_malloc(sizeof(*ctrl));
+	ctrl = os_zalloc(sizeof(*ctrl));
 	if (ctrl == NULL)
 		return NULL;
-	os_memset(ctrl, 0, sizeof(*ctrl));
 
 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
 	ctrl->s = socket(PF_INET6, SOCK_DGRAM, 0);
@@ -643,7 +641,7 @@
 		ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
 				  ctrl_path);
 #endif /* UNICODE */
-	if (ret < 0 || ret >= 256) {
+	if (os_snprintf_error(256, ret)) {
 		os_free(ctrl);
 		return NULL;
 	}
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 4812f8d..1f747eb 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -58,6 +58,8 @@
 #define WPA_EVENT_SCAN_STARTED "CTRL-EVENT-SCAN-STARTED "
 /** New scan results available */
 #define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS "
+/** Scan command failed */
+#define WPA_EVENT_SCAN_FAILED "CTRL-EVENT-SCAN-FAILED "
 /** wpa_supplicant state change */
 #define WPA_EVENT_STATE_CHANGE "CTRL-EVENT-STATE-CHANGE "
 /** A new BSS entry was added (followed by BSS entry id and BSSID) */
@@ -118,6 +120,17 @@
 #define WPS_EVENT_ER_AP_SETTINGS "WPS-ER-AP-SETTINGS "
 #define WPS_EVENT_ER_SET_SEL_REG "WPS-ER-AP-SET-SEL-REG "
 
+/* MESH events */
+#define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
+#define MESH_GROUP_REMOVED "MESH-GROUP-REMOVED "
+#define MESH_PEER_CONNECTED "MESH-PEER-CONNECTED "
+#define MESH_PEER_DISCONNECTED "MESH-PEER-DISCONNECTED "
+
+/* WMM AC events */
+#define WMM_AC_EVENT_TSPEC_ADDED "TSPEC-ADDED "
+#define WMM_AC_EVENT_TSPEC_REMOVED "TSPEC-REMOVED "
+#define WMM_AC_EVENT_TSPEC_REQ_FAILED "TSPEC-REQ-FAILED "
+
 /** P2P device found */
 #define P2P_EVENT_DEVICE_FOUND "P2P-DEVICE-FOUND "
 
@@ -187,6 +200,9 @@
 #define EXT_RADIO_WORK_START "EXT-RADIO-WORK-START "
 #define EXT_RADIO_WORK_TIMEOUT "EXT-RADIO-WORK-TIMEOUT "
 
+#define RRM_EVENT_NEIGHBOR_REP_RXED "RRM-NEIGHBOR-REP-RECEIVED "
+#define RRM_EVENT_NEIGHBOR_REP_FAILED "RRM-NEIGHBOR-REP-REQUEST-FAILED "
+
 /* hostapd control interface - fixed message prefixes */
 #define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED "
 #define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS "
@@ -204,6 +220,9 @@
 #define AP_EVENT_ENABLED "AP-ENABLED "
 #define AP_EVENT_DISABLED "AP-DISABLED "
 
+#define INTERFACE_ENABLED "INTERFACE-ENABLED "
+#define INTERFACE_DISABLED "INTERFACE-DISABLED "
+
 #define ACS_EVENT_STARTED "ACS-STARTED "
 #define ACS_EVENT_COMPLETED "ACS-COMPLETED "
 #define ACS_EVENT_FAILED "ACS-FAILED "
@@ -216,6 +235,9 @@
 
 #define AP_CSA_FINISHED "AP-CSA-FINISHED "
 
+/* BSS Transition Management Response frame received */
+#define BSS_TM_RESP "BSS-TM-RESP "
+
 /* BSS command information masks */
 
 #define WPA_BSS_MASK_ALL		0xFFFDFFFF
@@ -237,6 +259,7 @@
 #define WPA_BSS_MASK_INTERNETW		BIT(15)
 #define WPA_BSS_MASK_WIFI_DISPLAY	BIT(16)
 #define WPA_BSS_MASK_DELIM		BIT(17)
+#define WPA_BSS_MASK_MESH_SCAN		BIT(18)
 
 
 /* VENDOR_ELEM_* frame id values */
@@ -383,8 +406,6 @@
  */
 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
 
-char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl);
-
 #ifdef ANDROID
 /**
  * wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
@@ -402,6 +423,8 @@
 #define WPA_CTRL_IFACE_PORT_LIMIT 50 /* decremented from start */
 #define WPA_GLOBAL_CTRL_IFACE_PORT 9878
 #define WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT 20 /* incremented from start */
+
+char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl);
 #endif /* CONFIG_CTRL_IFACE_UDP */