[wpa_supplicant] Cumulative patch from commit c54a5e96b

Bug: 154862045
Test: Confirm random dialog token usage from logs
Test: Verify Passpoint ANQP functionality and Passpoint association
Test: act.py -c ../WifiDppConfig.json -tc WifiDppTest
Test: Connect to Passpoint, Open, WPA2, WPA3 networks and run traffic

c54a5e96b Randomize GAS dialog token
a803ba4f9 Use more specific reason codes for 4-way handshake timeouts
ff0b87304 nl80211: Process unprotected Beacon frame RX events
a39e9af90 nl80211: DPP listen mode callback
e81e2091b Remove now unused Boolean/TRUE/FALSE definitions
3d58e8286 FILS: Convert Boolean to C99 bool
86ea761e9 mesh: Convert Boolean to C99 bool
71140cd5b RADIUS: Convert Boolean to C99 bool
2c55e67aa airtime_policy: Convert Boolean to C99 bool
f75a0339d state_machine: Convert Boolean to C99 bool
0365458eb HE: Replace Boolean with C99 bool
5e5eb5a31 MACsec: Convert Boolean to C99 bool
d15e109e2 EAP peer: Convert Boolean to C99 bool
c9d70dd32 RSN supp: Convert Boolean to C99 bool
da8478a1a EAPOL supp: Convert Boolean to C99 bool
37e3501bf FST: Convert Boolean to C99 bool
3dc69721e EAPOL auth: Convert Boolean to C99 bool
56024a233 WPA auth: Convert Boolean to C99 bool
4d9c313f2 WPA: Fix wpa_parse_kde_ies() handling with vendor specific elements
1025a9052 Sync with mac80211-next.git include/uapi/linux/nl80211.h

Change-Id: I4fc553d84810ba82fdc626767c2e8a5640e4ca51
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index bdd90d8..e3b13bc 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -2306,9 +2306,9 @@
 
 #ifdef CONFIG_MACSEC
 struct macsec_init_params {
-	Boolean always_include_sci;
-	Boolean use_es;
-	Boolean use_scb;
+	bool always_include_sci;
+	bool use_es;
+	bool use_scb;
 };
 #endif /* CONFIG_MACSEC */
 
@@ -4003,30 +4003,30 @@
 	/**
 	 * enable_protect_frames - Set protect frames status
 	 * @priv: Private driver interface data
-	 * @enabled: TRUE = protect frames enabled
-	 *           FALSE = protect frames disabled
+	 * @enabled: true = protect frames enabled
+	 *           false = protect frames disabled
 	 * Returns: 0 on success, -1 on failure (or if not supported)
 	 */
-	int (*enable_protect_frames)(void *priv, Boolean enabled);
+	int (*enable_protect_frames)(void *priv, bool enabled);
 
 	/**
 	 * enable_encrypt - Set encryption status
 	 * @priv: Private driver interface data
-	 * @enabled: TRUE = encrypt outgoing traffic
-	 *           FALSE = integrity-only protection on outgoing traffic
+	 * @enabled: true = encrypt outgoing traffic
+	 *           false = integrity-only protection on outgoing traffic
 	 * Returns: 0 on success, -1 on failure (or if not supported)
 	 */
-	int (*enable_encrypt)(void *priv, Boolean enabled);
+	int (*enable_encrypt)(void *priv, bool enabled);
 
 	/**
 	 * set_replay_protect - Set replay protect status and window size
 	 * @priv: Private driver interface data
-	 * @enabled: TRUE = replay protect enabled
-	 *           FALSE = replay protect disabled
+	 * @enabled: true = replay protect enabled
+	 *           false = replay protect disabled
 	 * @window: replay window size, valid only when replay protect enabled
 	 * Returns: 0 on success, -1 on failure (or if not supported)
 	 */
-	int (*set_replay_protect)(void *priv, Boolean enabled, u32 window);
+	int (*set_replay_protect)(void *priv, bool enabled, u32 window);
 
 	/**
 	 * set_current_cipher_suite - Set current cipher suite
@@ -4039,11 +4039,11 @@
 	/**
 	 * enable_controlled_port - Set controlled port status
 	 * @priv: Private driver interface data
-	 * @enabled: TRUE = controlled port enabled
-	 *           FALSE = controlled port disabled
+	 * @enabled: true = controlled port enabled
+	 *           false = controlled port disabled
 	 * Returns: 0 on success, -1 on failure (or if not supported)
 	 */
-	int (*enable_controlled_port)(void *priv, Boolean enabled);
+	int (*enable_controlled_port)(void *priv, bool enabled);
 
 	/**
 	 * get_receive_lowest_pn - Get receive lowest pn
@@ -4434,7 +4434,7 @@
 	 * This optional callback can be used to update RX frame filtering to
 	 * explicitly allow reception of broadcast Public Action frames.
 	 */
-	int (*dpp_listen)(void *priv, int enable);
+	int (*dpp_listen)(void *priv, bool enable);
 };
 
 /**
diff --git a/src/drivers/driver_macsec_linux.c b/src/drivers/driver_macsec_linux.c
index 5319ba2..36a0757 100644
--- a/src/drivers/driver_macsec_linux.c
+++ b/src/drivers/driver_macsec_linux.c
@@ -59,24 +59,24 @@
 	int parent_ifi;
 	int use_pae_group_addr;
 
-	Boolean created_link;
+	bool created_link;
 
-	Boolean controlled_port_enabled;
-	Boolean controlled_port_enabled_set;
+	bool controlled_port_enabled;
+	bool controlled_port_enabled_set;
 
-	Boolean protect_frames;
-	Boolean protect_frames_set;
+	bool protect_frames;
+	bool protect_frames_set;
 
-	Boolean encrypt;
-	Boolean encrypt_set;
+	bool encrypt;
+	bool encrypt_set;
 
-	Boolean replay_protect;
-	Boolean replay_protect_set;
+	bool replay_protect;
+	bool replay_protect_set;
 
 	u32 replay_window;
 
 	u8 encoding_sa;
-	Boolean encoding_sa_set;
+	bool encoding_sa_set;
 };
 
 
@@ -197,7 +197,7 @@
 
 		rtnl_link_put(change);
 
-		drv->controlled_port_enabled_set = FALSE;
+		drv->controlled_port_enabled_set = false;
 	}
 
 	if (drv->protect_frames_set) {
@@ -236,9 +236,9 @@
 	if (err < 0)
 		return err;
 
-	drv->protect_frames_set = FALSE;
-	drv->encrypt_set = FALSE;
-	drv->replay_protect_set = FALSE;
+	drv->protect_frames_set = false;
+	drv->encrypt_set = false;
+	drv->replay_protect_set = false;
 
 	return 0;
 }
@@ -390,17 +390,17 @@
 /**
  * macsec_drv_enable_protect_frames - Set protect frames status
  * @priv: Private driver interface data
- * @enabled: TRUE = protect frames enabled
- *           FALSE = protect frames disabled
+ * @enabled: true = protect frames enabled
+ *           false = protect frames disabled
  * Returns: 0 on success, -1 on failure (or if not supported)
  */
-static int macsec_drv_enable_protect_frames(void *priv, Boolean enabled)
+static int macsec_drv_enable_protect_frames(void *priv, bool enabled)
 {
 	struct macsec_drv_data *drv = priv;
 
 	wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE");
 
-	drv->protect_frames_set = TRUE;
+	drv->protect_frames_set = true;
 	drv->protect_frames = enabled;
 
 	return try_commit(drv);
@@ -410,17 +410,17 @@
 /**
  * macsec_drv_enable_encrypt - Set protect frames status
  * @priv: Private driver interface data
- * @enabled: TRUE = protect frames enabled
- *           FALSE = protect frames disabled
+ * @enabled: true = protect frames enabled
+ *           false = protect frames disabled
  * Returns: 0 on success, -1 on failure (or if not supported)
  */
-static int macsec_drv_enable_encrypt(void *priv, Boolean enabled)
+static int macsec_drv_enable_encrypt(void *priv, bool enabled)
 {
 	struct macsec_drv_data *drv = priv;
 
 	wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE");
 
-	drv->encrypt_set = TRUE;
+	drv->encrypt_set = true;
 	drv->encrypt = enabled;
 
 	return try_commit(drv);
@@ -430,12 +430,12 @@
 /**
  * macsec_drv_set_replay_protect - Set replay protect status and window size
  * @priv: Private driver interface data
- * @enabled: TRUE = replay protect enabled
- *           FALSE = replay protect disabled
+ * @enabled: true = replay protect enabled
+ *           false = replay protect disabled
  * @window: replay window size, valid only when replay protect enabled
  * Returns: 0 on success, -1 on failure (or if not supported)
  */
-static int macsec_drv_set_replay_protect(void *priv, Boolean enabled,
+static int macsec_drv_set_replay_protect(void *priv, bool enabled,
 					 u32 window)
 {
 	struct macsec_drv_data *drv = priv;
@@ -443,7 +443,7 @@
 	wpa_printf(MSG_DEBUG, "%s -> %s, %u", __func__,
 		   enabled ? "TRUE" : "FALSE", window);
 
-	drv->replay_protect_set = TRUE;
+	drv->replay_protect_set = true;
 	drv->replay_protect = enabled;
 	if (enabled)
 		drv->replay_window = window;
@@ -468,18 +468,18 @@
 /**
  * macsec_drv_enable_controlled_port - Set controlled port status
  * @priv: Private driver interface data
- * @enabled: TRUE = controlled port enabled
- *           FALSE = controlled port disabled
+ * @enabled: true = controlled port enabled
+ *           false = controlled port disabled
  * Returns: 0 on success, -1 on failure (or if not supported)
  */
-static int macsec_drv_enable_controlled_port(void *priv, Boolean enabled)
+static int macsec_drv_enable_controlled_port(void *priv, bool enabled)
 {
 	struct macsec_drv_data *drv = priv;
 
 	wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE");
 
 	drv->controlled_port_enabled = enabled;
-	drv->controlled_port_enabled_set = TRUE;
+	drv->controlled_port_enabled_set = true;
 
 	return try_commit(drv);
 }
@@ -986,7 +986,7 @@
 
 
 static int set_active_rx_sa(const struct macsec_genl_ctx *ctx, int ifindex,
-			    u64 sci, unsigned char an, Boolean state)
+			    u64 sci, unsigned char an, bool state)
 {
 	struct nl_msg *msg;
 	struct nlattr *nest;
@@ -1036,7 +1036,7 @@
 		   SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
 
 	return set_active_rx_sa(ctx, drv->ifi, mka_sci_u64(&sa->sc->sci),
-				sa->an, TRUE);
+				sa->an, true);
 }
 
 
@@ -1056,7 +1056,7 @@
 		   SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
 
 	return set_active_rx_sa(ctx, drv->ifi, mka_sci_u64(&sa->sc->sci),
-				sa->an, FALSE);
+				sa->an, false);
 }
 
 
@@ -1117,13 +1117,13 @@
 	sci = mka_sci_u64(&sc->sci);
 	rtnl_link_macsec_set_sci(link, sci);
 
-	drv->created_link = TRUE;
+	drv->created_link = true;
 
 	err = rtnl_link_add(drv->sk, link, NLM_F_CREATE);
 	if (err == -NLE_BUSY) {
 		wpa_printf(MSG_INFO,
 			   DRV_PREFIX "link already exists, using it");
-		drv->created_link = FALSE;
+		drv->created_link = false;
 	} else if (err < 0) {
 		rtnl_link_put(link);
 		wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't create link: err %d",
@@ -1296,7 +1296,7 @@
 
 
 static int set_active_tx_sa(const struct macsec_genl_ctx *ctx, int ifindex,
-			    unsigned char an, Boolean state)
+			    unsigned char an, bool state)
 {
 	struct nl_msg *msg;
 	struct nlattr *nest;
@@ -1344,13 +1344,13 @@
 		   SCISTR, drv->ifname, sa->an,
 		   SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
 
-	ret = set_active_tx_sa(ctx, drv->ifi, sa->an, TRUE);
+	ret = set_active_tx_sa(ctx, drv->ifi, sa->an, true);
 	if (ret < 0) {
 		wpa_printf(MSG_ERROR, DRV_PREFIX "failed to enable txsa");
 		return ret;
 	}
 
-	drv->encoding_sa_set = TRUE;
+	drv->encoding_sa_set = true;
 	drv->encoding_sa = sa->an;
 
 	return try_commit(drv);
@@ -1372,7 +1372,7 @@
 		   SCISTR, drv->ifname, sa->an,
 		   SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
 
-	return set_active_tx_sa(ctx, drv->ifi, sa->an, FALSE);
+	return set_active_tx_sa(ctx, drv->ifi, sa->an, false);
 }
 
 
diff --git a/src/drivers/driver_macsec_qca.c b/src/drivers/driver_macsec_qca.c
index f4e55d5..928f024 100644
--- a/src/drivers/driver_macsec_qca.c
+++ b/src/drivers/driver_macsec_qca.c
@@ -70,11 +70,11 @@
 	u32 secy_id;
 
 	/* shadow */
-	Boolean always_include_sci;
-	Boolean use_es;
-	Boolean use_scb;
-	Boolean protect_frames;
-	Boolean replay_protect;
+	bool always_include_sci;
+	bool use_es;
+	bool use_scb;
+	bool protect_frames;
+	bool replay_protect;
 	u32 replay_window;
 
 	struct channel_map receive_channel_map[MAXSC];
@@ -91,7 +91,7 @@
 	wpa_printf(MSG_INFO, "%s: secy_id=%d", __func__, drv->secy_id);
 
 	/* Enable Secy and Let EAPoL bypass */
-	ret = nss_macsec_secy_en_set(drv->secy_id, TRUE);
+	ret = nss_macsec_secy_en_set(drv->secy_id, true);
 	if (ret)
 		wpa_printf(MSG_ERROR, "nss_macsec_secy_en_set: FAIL");
 
@@ -123,7 +123,7 @@
 
 static void __macsec_drv_deinit(struct macsec_qca_data *drv)
 {
-	nss_macsec_secy_en_set(drv->secy_id, FALSE);
+	nss_macsec_secy_en_set(drv->secy_id, false);
 	nss_macsec_secy_rx_sc_del_all(drv->secy_id);
 	nss_macsec_secy_tx_sc_del_all(drv->secy_id);
 }
@@ -422,7 +422,7 @@
 }
 
 
-static int macsec_qca_enable_protect_frames(void *priv, Boolean enabled)
+static int macsec_qca_enable_protect_frames(void *priv, bool enabled)
 {
 	struct macsec_qca_data *drv = priv;
 	int ret = 0;
@@ -435,7 +435,7 @@
 }
 
 
-static int macsec_qca_set_replay_protect(void *priv, Boolean enabled,
+static int macsec_qca_set_replay_protect(void *priv, bool enabled,
 					 unsigned int window)
 {
 	struct macsec_qca_data *drv = priv;
@@ -480,7 +480,7 @@
 }
 
 
-static int macsec_qca_enable_controlled_port(void *priv, Boolean enabled)
+static int macsec_qca_enable_controlled_port(void *priv, bool enabled)
 {
 	struct macsec_qca_data *drv = priv;
 	int ret = 0;
@@ -560,7 +560,7 @@
 	struct macsec_qca_data *drv = priv;
 	int ret = 0;
 	u32 next_pn = 0;
-	bool enabled = FALSE;
+	bool enabled = false;
 	u32 win;
 	u32 channel;
 
@@ -629,7 +629,7 @@
 	struct macsec_qca_data *drv = priv;
 	int ret = 0;
 	u32 sc_ch = 0;
-	bool in_use = FALSE;
+	bool in_use = false;
 
 	for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) {
 		ret = nss_macsec_secy_rx_sc_in_used_get(drv->secy_id, sc_ch,
@@ -794,7 +794,7 @@
 		   sa->an);
 
 	ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
-					    TRUE);
+					    true);
 
 	return ret;
 }
@@ -814,7 +814,7 @@
 		   sa->an);
 
 	ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
-					    FALSE);
+					    false);
 
 	return ret;
 }
@@ -824,7 +824,7 @@
 {
 	struct macsec_qca_data *drv = priv;
 	u32 sc_ch = 0;
-	bool in_use = FALSE;
+	bool in_use = false;
 
 	for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) {
 		if (nss_macsec_secy_tx_sc_in_used_get(drv->secy_id, sc_ch,
@@ -988,7 +988,7 @@
 		   sa->an);
 
 	ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
-					    TRUE);
+					    true);
 
 	return ret;
 }
@@ -1008,7 +1008,7 @@
 		   sa->an);
 
 	ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
-					    FALSE);
+					    false);
 
 	return ret;
 }
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 75792f3..d48f8cb 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -2165,7 +2165,8 @@
 
 static int nl80211_register_frame(struct i802_bss *bss,
 				  struct nl_sock *nl_handle,
-				  u16 type, const u8 *match, size_t match_len)
+				  u16 type, const u8 *match, size_t match_len,
+				  bool multicast)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
@@ -2174,10 +2175,12 @@
 
 	buf[0] = '\0';
 	wpa_snprintf_hex(buf, sizeof(buf), match, match_len);
-	wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x (%s) nl_handle=%p match=%s",
-		   type, fc2str(type), nl_handle, buf);
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: Register frame type=0x%x (%s) nl_handle=%p match=%s multicast=%d",
+		   type, fc2str(type), nl_handle, buf, multicast);
 
 	if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_REGISTER_FRAME)) ||
+	    (multicast && nla_put_flag(msg, NL80211_ATTR_RECEIVE_MULTICAST)) ||
 	    nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, type) ||
 	    nla_put(msg, NL80211_ATTR_FRAME_MATCH, match_len, match)) {
 		nlmsg_free(msg);
@@ -2225,7 +2228,7 @@
 {
 	u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);
 	return nl80211_register_frame(bss, bss->nl_mgmt,
-				      type, match, match_len);
+				      type, match, match_len, false);
 }
 
 
@@ -2242,12 +2245,12 @@
 
 	if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
 		/* register for any AUTH message */
-		nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0);
+		nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0, false);
 	} else if ((drv->capa.flags & WPA_DRIVER_FLAGS_SAE) &&
 		   !(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
 		/* register for SAE Authentication frames */
 		nl80211_register_frame(bss, bss->nl_mgmt, type,
-				       (u8 *) "\x03\x00", 2);
+				       (u8 *) "\x03\x00", 2, false);
 	}
 
 #ifdef CONFIG_INTERWORKING
@@ -2389,7 +2392,7 @@
 	if (nl80211_register_frame(bss, bss->nl_mgmt,
 				   (WLAN_FC_TYPE_MGMT << 2) |
 				   (WLAN_FC_STYPE_AUTH << 4),
-				   NULL, 0) < 0)
+				   NULL, 0, false) < 0)
 		ret = -1;
 
 	/* Mesh peering open */
@@ -2495,7 +2498,7 @@
 		if (nl80211_register_frame(bss, bss->nl_mgmt,
 					   (WLAN_FC_TYPE_MGMT << 2) |
 					   (stypes[i] << 4),
-					   NULL, 0) < 0) {
+					   NULL, 0, false) < 0) {
 			goto out_err;
 		}
 	}
@@ -2529,8 +2532,8 @@
 		u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4);
 
 		/* Register for all Authentication frames */
-		if (nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0)
-		    < 0)
+		if (nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0,
+					   false) < 0)
 			wpa_printf(MSG_DEBUG,
 				   "nl80211: Failed to subscribe to handle Authentication frames - SAE offload may not work");
 	}
@@ -7931,7 +7934,7 @@
 	if (nl80211_register_frame(bss, bss->nl_preq,
 				   (WLAN_FC_TYPE_MGMT << 2) |
 				   (WLAN_FC_STYPE_PROBE_REQ << 4),
-				   NULL, 0) < 0)
+				   NULL, 0, false) < 0)
 		goto out_err;
 
 	nl80211_register_eloop_read(&bss->nl_preq,
@@ -11433,6 +11436,28 @@
 }
 
 
+#ifdef CONFIG_DPP
+static int nl80211_dpp_listen(void *priv, bool enable)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);
+	struct nl_sock *handle;
+
+	if (!drv->multicast_registrations || !bss->nl_mgmt)
+		return 0; /* cannot do more than hope broadcast RX works */
+
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: Update DPP Public Action frame registration (%s multicast RX)",
+		   enable ? "enable" : "disable");
+	handle = (void *) (((intptr_t) bss->nl_mgmt) ^ ELOOP_SOCKET_INVALID);
+	return nl80211_register_frame(bss, handle, type,
+				      (u8 *) "\x04\x09\x50\x6f\x9a\x1a", 6,
+				      enable);
+}
+#endif /* CONFIG_DPP */
+
+
 const struct wpa_driver_ops wpa_driver_nl80211_ops = {
 	.name = "nl80211",
 	.desc = "Linux nl80211/cfg80211",
@@ -11568,4 +11593,7 @@
 	.update_connect_params = nl80211_update_connection_params,
 	.send_external_auth_status = nl80211_send_external_auth_status,
 	.set_4addr_mode = nl80211_set_4addr_mode,
+#ifdef CONFIG_DPP
+	.dpp_listen = nl80211_dpp_listen,
+#endif /* CONFIG_DPP */
 };
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 19ac44a..dc80a17 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -172,6 +172,7 @@
 	unsigned int get_supported_akm_suites_avail:1;
 	unsigned int add_sta_node_vendor_cmd_avail:1;
 	unsigned int control_port_ap:1;
+	unsigned int multicast_registrations:1;
 
 	u64 vendor_scan_cookie;
 	u64 remain_on_chan_cookie;
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index f033591..f997577 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -460,6 +460,10 @@
 	if (ext_feature_isset(ext_features, len,
 			      NL80211_EXT_FEATURE_EXT_KEY_ID))
 		capa->flags |= WPA_DRIVER_FLAGS_EXTENDED_KEY_ID;
+
+	if (ext_feature_isset(ext_features, len,
+			      NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS))
+		info->drv->multicast_registrations = 1;
 }
 
 
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 17a06d8..1152312 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -137,6 +137,7 @@
 	C2S(NL80211_CMD_STA_OPMODE_CHANGED)
 	C2S(NL80211_CMD_CONTROL_PORT_FRAME)
 	C2S(NL80211_CMD_UPDATE_OWE_INFO)
+	C2S(NL80211_CMD_UNPROT_BEACON)
 	default:
 		return "NL80211_CMD_UNKNOWN";
 	}
@@ -893,6 +894,23 @@
 }
 
 
+static void mlme_event_unprot_beacon(struct wpa_driver_nl80211_data *drv,
+				     const u8 *frame, size_t len)
+{
+	const struct ieee80211_mgmt *mgmt;
+	union wpa_event_data event;
+
+	if (len < 24)
+		return;
+
+	mgmt = (const struct ieee80211_mgmt *) frame;
+
+	os_memset(&event, 0, sizeof(event));
+	event.unprot_beacon.sa = mgmt->sa;
+	wpa_supplicant_event(drv->ctx, EVENT_UNPROT_BEACON, &event);
+}
+
+
 static void mlme_event(struct i802_bss *bss,
 		       enum nl80211_commands cmd, struct nlattr *frame,
 		       struct nlattr *addr, struct nlattr *timed_out,
@@ -974,6 +992,9 @@
 		mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC,
 					     nla_data(frame), nla_len(frame));
 		break;
+	case NL80211_CMD_UNPROT_BEACON:
+		mlme_event_unprot_beacon(drv, nla_data(frame), nla_len(frame));
+		break;
 	default:
 		break;
 	}
@@ -2541,6 +2562,7 @@
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int external_scan_event = 0;
+	struct nlattr *frame = tb[NL80211_ATTR_FRAME];
 
 	wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s",
 		   cmd, nl80211_command_to_string(cmd), bss->ifname);
@@ -2751,6 +2773,11 @@
 	case NL80211_CMD_UPDATE_OWE_INFO:
 		mlme_event_dh_event(drv, bss, tb);
 		break;
+	case NL80211_CMD_UNPROT_BEACON:
+		if (frame)
+			mlme_event_unprot_beacon(drv, nla_data(frame),
+						 nla_len(frame));
+		break;
 	default:
 		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
 			"(cmd=%d)", cmd);
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index 38835b5..5e500d7 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -687,6 +687,10 @@
  *	four bytes for vendor frames including the OUI. The registration
  *	cannot be dropped, but is removed automatically when the netlink
  *	socket is closed. Multiple registrations can be made.
+ *	The %NL80211_ATTR_RECEIVE_MULTICAST flag attribute can be given if
+ *	%NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS is available, in which
+ *	case the registration can also be modified to include/exclude the
+ *	flag, rather than requiring unregistration to change it.
  * @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for
  *	backward compatibility
  * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This
@@ -1151,6 +1155,11 @@
  * @NL80211_CMD_SET_TID_CONFIG: Data frame TID specific configuration
  *	is passed using %NL80211_ATTR_TID_CONFIG attribute.
  *
+ * @NL80211_CMD_UNPROT_BEACON: Unprotected or incorrectly protected Beacon
+ *	frame. This event is used to indicate that a received Beacon frame was
+ *	dropped because it did not include a valid MME MIC while beacon
+ *	protection was enabled (BIGTK configured in station mode).
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1377,6 +1386,8 @@
 
 	NL80211_CMD_SET_TID_CONFIG,
 
+	NL80211_CMD_UNPROT_BEACON,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -2470,6 +2481,9 @@
  *	no roaming occurs between the reauth threshold and PMK expiration,
  *	disassociation is still forced.
  *
+ * @NL80211_ATTR_RECEIVE_MULTICAST: multicast flag for the
+ *	%NL80211_CMD_REGISTER_FRAME command, see the description there.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2945,6 +2959,8 @@
 	NL80211_ATTR_PMK_LIFETIME,
 	NL80211_ATTR_PMK_REAUTH_THRESHOLD,
 
+	NL80211_ATTR_RECEIVE_MULTICAST,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -5674,6 +5690,8 @@
  *
  * @NL80211_EXT_FEATURE_BEACON_PROTECTION: The driver supports Beacon protection
  *	and can receive key configuration for BIGTK using key indexes 6 and 7.
+ * @NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT: The driver supports Beacon
+ *	protection as a client only and cannot transmit protected beacons.
  *
  * @NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH: The driver can disable the
  *	forwarding of preauth frames over the control port. They are then
@@ -5684,6 +5702,9 @@
  * @NL80211_EXT_FEATURE_DEL_IBSS_STA: The driver supports removing stations
  *      in IBSS mode, essentially by dropping their state.
  *
+ * @NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS: management frame registrations
+ *	are possible for multicast frames and those will be reported properly.
+ *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
  */
@@ -5735,6 +5756,8 @@
 	NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH,
 	NL80211_EXT_FEATURE_PROTECTED_TWT,
 	NL80211_EXT_FEATURE_DEL_IBSS_STA,
+	NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS,
+	NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT,
 
 	/* add new features before the definition below */
 	NUM_NL80211_EXT_FEATURES,