Home | History | Annotate | Download | only in drivers
      1 /*
      2  * Driver interaction with Linux nl80211/cfg80211 - Event processing
      3  * Copyright (c) 2002-2017, Jouni Malinen <j (at) w1.fi>
      4  * Copyright (c) 2007, Johannes Berg <johannes (at) sipsolutions.net>
      5  * Copyright (c) 2009-2010, Atheros Communications
      6  *
      7  * This software may be distributed under the terms of the BSD license.
      8  * See README for more details.
      9  */
     10 
     11 #include "includes.h"
     12 #include <netlink/genl/genl.h>
     13 
     14 #include "utils/common.h"
     15 #include "utils/eloop.h"
     16 #include "common/qca-vendor.h"
     17 #include "common/qca-vendor-attr.h"
     18 #include "common/ieee802_11_defs.h"
     19 #include "common/ieee802_11_common.h"
     20 #include "driver_nl80211.h"
     21 
     22 
     23 static const char * nl80211_command_to_string(enum nl80211_commands cmd)
     24 {
     25 #define C2S(x) case x: return #x;
     26 	switch (cmd) {
     27 	C2S(NL80211_CMD_UNSPEC)
     28 	C2S(NL80211_CMD_GET_WIPHY)
     29 	C2S(NL80211_CMD_SET_WIPHY)
     30 	C2S(NL80211_CMD_NEW_WIPHY)
     31 	C2S(NL80211_CMD_DEL_WIPHY)
     32 	C2S(NL80211_CMD_GET_INTERFACE)
     33 	C2S(NL80211_CMD_SET_INTERFACE)
     34 	C2S(NL80211_CMD_NEW_INTERFACE)
     35 	C2S(NL80211_CMD_DEL_INTERFACE)
     36 	C2S(NL80211_CMD_GET_KEY)
     37 	C2S(NL80211_CMD_SET_KEY)
     38 	C2S(NL80211_CMD_NEW_KEY)
     39 	C2S(NL80211_CMD_DEL_KEY)
     40 	C2S(NL80211_CMD_GET_BEACON)
     41 	C2S(NL80211_CMD_SET_BEACON)
     42 	C2S(NL80211_CMD_START_AP)
     43 	C2S(NL80211_CMD_STOP_AP)
     44 	C2S(NL80211_CMD_GET_STATION)
     45 	C2S(NL80211_CMD_SET_STATION)
     46 	C2S(NL80211_CMD_NEW_STATION)
     47 	C2S(NL80211_CMD_DEL_STATION)
     48 	C2S(NL80211_CMD_GET_MPATH)
     49 	C2S(NL80211_CMD_SET_MPATH)
     50 	C2S(NL80211_CMD_NEW_MPATH)
     51 	C2S(NL80211_CMD_DEL_MPATH)
     52 	C2S(NL80211_CMD_SET_BSS)
     53 	C2S(NL80211_CMD_SET_REG)
     54 	C2S(NL80211_CMD_REQ_SET_REG)
     55 	C2S(NL80211_CMD_GET_MESH_CONFIG)
     56 	C2S(NL80211_CMD_SET_MESH_CONFIG)
     57 	C2S(NL80211_CMD_SET_MGMT_EXTRA_IE)
     58 	C2S(NL80211_CMD_GET_REG)
     59 	C2S(NL80211_CMD_GET_SCAN)
     60 	C2S(NL80211_CMD_TRIGGER_SCAN)
     61 	C2S(NL80211_CMD_NEW_SCAN_RESULTS)
     62 	C2S(NL80211_CMD_SCAN_ABORTED)
     63 	C2S(NL80211_CMD_REG_CHANGE)
     64 	C2S(NL80211_CMD_AUTHENTICATE)
     65 	C2S(NL80211_CMD_ASSOCIATE)
     66 	C2S(NL80211_CMD_DEAUTHENTICATE)
     67 	C2S(NL80211_CMD_DISASSOCIATE)
     68 	C2S(NL80211_CMD_MICHAEL_MIC_FAILURE)
     69 	C2S(NL80211_CMD_REG_BEACON_HINT)
     70 	C2S(NL80211_CMD_JOIN_IBSS)
     71 	C2S(NL80211_CMD_LEAVE_IBSS)
     72 	C2S(NL80211_CMD_TESTMODE)
     73 	C2S(NL80211_CMD_CONNECT)
     74 	C2S(NL80211_CMD_ROAM)
     75 	C2S(NL80211_CMD_DISCONNECT)
     76 	C2S(NL80211_CMD_SET_WIPHY_NETNS)
     77 	C2S(NL80211_CMD_GET_SURVEY)
     78 	C2S(NL80211_CMD_NEW_SURVEY_RESULTS)
     79 	C2S(NL80211_CMD_SET_PMKSA)
     80 	C2S(NL80211_CMD_DEL_PMKSA)
     81 	C2S(NL80211_CMD_FLUSH_PMKSA)
     82 	C2S(NL80211_CMD_REMAIN_ON_CHANNEL)
     83 	C2S(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL)
     84 	C2S(NL80211_CMD_SET_TX_BITRATE_MASK)
     85 	C2S(NL80211_CMD_REGISTER_FRAME)
     86 	C2S(NL80211_CMD_FRAME)
     87 	C2S(NL80211_CMD_FRAME_TX_STATUS)
     88 	C2S(NL80211_CMD_SET_POWER_SAVE)
     89 	C2S(NL80211_CMD_GET_POWER_SAVE)
     90 	C2S(NL80211_CMD_SET_CQM)
     91 	C2S(NL80211_CMD_NOTIFY_CQM)
     92 	C2S(NL80211_CMD_SET_CHANNEL)
     93 	C2S(NL80211_CMD_SET_WDS_PEER)
     94 	C2S(NL80211_CMD_FRAME_WAIT_CANCEL)
     95 	C2S(NL80211_CMD_JOIN_MESH)
     96 	C2S(NL80211_CMD_LEAVE_MESH)
     97 	C2S(NL80211_CMD_UNPROT_DEAUTHENTICATE)
     98 	C2S(NL80211_CMD_UNPROT_DISASSOCIATE)
     99 	C2S(NL80211_CMD_NEW_PEER_CANDIDATE)
    100 	C2S(NL80211_CMD_GET_WOWLAN)
    101 	C2S(NL80211_CMD_SET_WOWLAN)
    102 	C2S(NL80211_CMD_START_SCHED_SCAN)
    103 	C2S(NL80211_CMD_STOP_SCHED_SCAN)
    104 	C2S(NL80211_CMD_SCHED_SCAN_RESULTS)
    105 	C2S(NL80211_CMD_SCHED_SCAN_STOPPED)
    106 	C2S(NL80211_CMD_SET_REKEY_OFFLOAD)
    107 	C2S(NL80211_CMD_PMKSA_CANDIDATE)
    108 	C2S(NL80211_CMD_TDLS_OPER)
    109 	C2S(NL80211_CMD_TDLS_MGMT)
    110 	C2S(NL80211_CMD_UNEXPECTED_FRAME)
    111 	C2S(NL80211_CMD_PROBE_CLIENT)
    112 	C2S(NL80211_CMD_REGISTER_BEACONS)
    113 	C2S(NL80211_CMD_UNEXPECTED_4ADDR_FRAME)
    114 	C2S(NL80211_CMD_SET_NOACK_MAP)
    115 	C2S(NL80211_CMD_CH_SWITCH_NOTIFY)
    116 	C2S(NL80211_CMD_START_P2P_DEVICE)
    117 	C2S(NL80211_CMD_STOP_P2P_DEVICE)
    118 	C2S(NL80211_CMD_CONN_FAILED)
    119 	C2S(NL80211_CMD_SET_MCAST_RATE)
    120 	C2S(NL80211_CMD_SET_MAC_ACL)
    121 	C2S(NL80211_CMD_RADAR_DETECT)
    122 	C2S(NL80211_CMD_GET_PROTOCOL_FEATURES)
    123 	C2S(NL80211_CMD_UPDATE_FT_IES)
    124 	C2S(NL80211_CMD_FT_EVENT)
    125 	C2S(NL80211_CMD_CRIT_PROTOCOL_START)
    126 	C2S(NL80211_CMD_CRIT_PROTOCOL_STOP)
    127 	C2S(NL80211_CMD_GET_COALESCE)
    128 	C2S(NL80211_CMD_SET_COALESCE)
    129 	C2S(NL80211_CMD_CHANNEL_SWITCH)
    130 	C2S(NL80211_CMD_VENDOR)
    131 	C2S(NL80211_CMD_SET_QOS_MAP)
    132 	C2S(NL80211_CMD_ADD_TX_TS)
    133 	C2S(NL80211_CMD_DEL_TX_TS)
    134 	default:
    135 		return "NL80211_CMD_UNKNOWN";
    136 	}
    137 #undef C2S
    138 }
    139 
    140 
    141 static void mlme_event_auth(struct wpa_driver_nl80211_data *drv,
    142 			    const u8 *frame, size_t len)
    143 {
    144 	const struct ieee80211_mgmt *mgmt;
    145 	union wpa_event_data event;
    146 
    147 	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
    148 	    drv->force_connect_cmd) {
    149 		/*
    150 		 * Avoid reporting two association events that would confuse
    151 		 * the core code.
    152 		 */
    153 		wpa_printf(MSG_DEBUG,
    154 			   "nl80211: Ignore auth event when using driver SME");
    155 		return;
    156 	}
    157 
    158 	wpa_printf(MSG_DEBUG, "nl80211: Authenticate event");
    159 	mgmt = (const struct ieee80211_mgmt *) frame;
    160 	if (len < 24 + sizeof(mgmt->u.auth)) {
    161 		wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
    162 			   "frame");
    163 		return;
    164 	}
    165 
    166 	os_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN);
    167 	os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
    168 	os_memset(&event, 0, sizeof(event));
    169 	os_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN);
    170 	event.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg);
    171 	event.auth.auth_transaction =
    172 		le_to_host16(mgmt->u.auth.auth_transaction);
    173 	event.auth.status_code = le_to_host16(mgmt->u.auth.status_code);
    174 	if (len > 24 + sizeof(mgmt->u.auth)) {
    175 		event.auth.ies = mgmt->u.auth.variable;
    176 		event.auth.ies_len = len - 24 - sizeof(mgmt->u.auth);
    177 	}
    178 
    179 	wpa_supplicant_event(drv->ctx, EVENT_AUTH, &event);
    180 }
    181 
    182 
    183 static void nl80211_parse_wmm_params(struct nlattr *wmm_attr,
    184 				     struct wmm_params *wmm_params)
    185 {
    186 	struct nlattr *wmm_info[NL80211_STA_WME_MAX + 1];
    187 	static struct nla_policy wme_policy[NL80211_STA_WME_MAX + 1] = {
    188 		[NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
    189 	};
    190 
    191 	if (!wmm_attr ||
    192 	    nla_parse_nested(wmm_info, NL80211_STA_WME_MAX, wmm_attr,
    193 			     wme_policy) ||
    194 	    !wmm_info[NL80211_STA_WME_UAPSD_QUEUES])
    195 		return;
    196 
    197 	wmm_params->uapsd_queues =
    198 		nla_get_u8(wmm_info[NL80211_STA_WME_UAPSD_QUEUES]);
    199 	wmm_params->info_bitmap |= WMM_PARAMS_UAPSD_QUEUES_INFO;
    200 }
    201 
    202 
    203 static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
    204 			    const u8 *frame, size_t len, struct nlattr *wmm)
    205 {
    206 	const struct ieee80211_mgmt *mgmt;
    207 	union wpa_event_data event;
    208 	u16 status;
    209 	int ssid_len;
    210 
    211 	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
    212 	    drv->force_connect_cmd) {
    213 		/*
    214 		 * Avoid reporting two association events that would confuse
    215 		 * the core code.
    216 		 */
    217 		wpa_printf(MSG_DEBUG,
    218 			   "nl80211: Ignore assoc event when using driver SME");
    219 		return;
    220 	}
    221 
    222 	wpa_printf(MSG_DEBUG, "nl80211: Associate event");
    223 	mgmt = (const struct ieee80211_mgmt *) frame;
    224 	if (len < 24 + sizeof(mgmt->u.assoc_resp)) {
    225 		wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
    226 			   "frame");
    227 		return;
    228 	}
    229 
    230 	status = le_to_host16(mgmt->u.assoc_resp.status_code);
    231 	if (status != WLAN_STATUS_SUCCESS) {
    232 		os_memset(&event, 0, sizeof(event));
    233 		event.assoc_reject.bssid = mgmt->bssid;
    234 		if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
    235 			event.assoc_reject.resp_ies =
    236 				(u8 *) mgmt->u.assoc_resp.variable;
    237 			event.assoc_reject.resp_ies_len =
    238 				len - 24 - sizeof(mgmt->u.assoc_resp);
    239 		}
    240 		event.assoc_reject.status_code = status;
    241 
    242 		wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
    243 		return;
    244 	}
    245 
    246 	drv->associated = 1;
    247 	os_memcpy(drv->bssid, mgmt->sa, ETH_ALEN);
    248 	os_memcpy(drv->prev_bssid, mgmt->sa, ETH_ALEN);
    249 
    250 	os_memset(&event, 0, sizeof(event));
    251 	event.assoc_info.resp_frame = frame;
    252 	event.assoc_info.resp_frame_len = len;
    253 	if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
    254 		event.assoc_info.resp_ies = (u8 *) mgmt->u.assoc_resp.variable;
    255 		event.assoc_info.resp_ies_len =
    256 			len - 24 - sizeof(mgmt->u.assoc_resp);
    257 	}
    258 
    259 	event.assoc_info.freq = drv->assoc_freq;
    260 
    261 	/* When this association was initiated outside of wpa_supplicant,
    262 	 * drv->ssid needs to be set here to satisfy later checking. */
    263 	ssid_len = nl80211_get_assoc_ssid(drv, drv->ssid);
    264 	if (ssid_len > 0) {
    265 		drv->ssid_len = ssid_len;
    266 		wpa_printf(MSG_DEBUG,
    267 			   "nl80211: Set drv->ssid based on scan res info to '%s'",
    268 			   wpa_ssid_txt(drv->ssid, drv->ssid_len));
    269 	}
    270 
    271 	nl80211_parse_wmm_params(wmm, &event.assoc_info.wmm_params);
    272 
    273 	wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
    274 }
    275 
    276 
    277 static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
    278 			       enum nl80211_commands cmd, struct nlattr *status,
    279 			       struct nlattr *addr, struct nlattr *req_ie,
    280 			       struct nlattr *resp_ie,
    281 			       struct nlattr *timed_out,
    282 			       struct nlattr *timeout_reason,
    283 			       struct nlattr *authorized,
    284 			       struct nlattr *key_replay_ctr,
    285 			       struct nlattr *ptk_kck,
    286 			       struct nlattr *ptk_kek,
    287 			       struct nlattr *subnet_status,
    288 			       struct nlattr *fils_erp_next_seq_num,
    289 			       struct nlattr *fils_pmk,
    290 			       struct nlattr *fils_pmkid)
    291 {
    292 	union wpa_event_data event;
    293 	const u8 *ssid = NULL;
    294 	u16 status_code;
    295 	int ssid_len;
    296 
    297 	if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
    298 		/*
    299 		 * Avoid reporting two association events that would confuse
    300 		 * the core code.
    301 		 */
    302 		wpa_printf(MSG_DEBUG, "nl80211: Ignore connect event (cmd=%d) "
    303 			   "when using userspace SME", cmd);
    304 		return;
    305 	}
    306 
    307 	drv->connect_reassoc = 0;
    308 
    309 	status_code = status ? nla_get_u16(status) : WLAN_STATUS_SUCCESS;
    310 
    311 	if (cmd == NL80211_CMD_CONNECT) {
    312 		wpa_printf(MSG_DEBUG,
    313 			   "nl80211: Connect event (status=%u ignore_next_local_disconnect=%d)",
    314 			   status_code, drv->ignore_next_local_disconnect);
    315 	} else if (cmd == NL80211_CMD_ROAM) {
    316 		wpa_printf(MSG_DEBUG, "nl80211: Roam event");
    317 	}
    318 
    319 	os_memset(&event, 0, sizeof(event));
    320 	if (cmd == NL80211_CMD_CONNECT && status_code != WLAN_STATUS_SUCCESS) {
    321 		if (addr)
    322 			event.assoc_reject.bssid = nla_data(addr);
    323 		if (drv->ignore_next_local_disconnect) {
    324 			drv->ignore_next_local_disconnect = 0;
    325 			if (!event.assoc_reject.bssid ||
    326 			    (os_memcmp(event.assoc_reject.bssid,
    327 				       drv->auth_attempt_bssid,
    328 				       ETH_ALEN) != 0)) {
    329 				/*
    330 				 * Ignore the event that came without a BSSID or
    331 				 * for the old connection since this is likely
    332 				 * not relevant to the new Connect command.
    333 				 */
    334 				wpa_printf(MSG_DEBUG,
    335 					   "nl80211: Ignore connection failure event triggered during reassociation");
    336 				return;
    337 			}
    338 		}
    339 		if (resp_ie) {
    340 			event.assoc_reject.resp_ies = nla_data(resp_ie);
    341 			event.assoc_reject.resp_ies_len = nla_len(resp_ie);
    342 		}
    343 		event.assoc_reject.status_code = status_code;
    344 		event.assoc_reject.timed_out = timed_out != NULL;
    345 		if (timed_out && timeout_reason) {
    346 			enum nl80211_timeout_reason reason;
    347 
    348 			reason = nla_get_u32(timeout_reason);
    349 			switch (reason) {
    350 			case NL80211_TIMEOUT_SCAN:
    351 				event.assoc_reject.timeout_reason = "scan";
    352 				break;
    353 			case NL80211_TIMEOUT_AUTH:
    354 				event.assoc_reject.timeout_reason = "auth";
    355 				break;
    356 			case NL80211_TIMEOUT_ASSOC:
    357 				event.assoc_reject.timeout_reason = "assoc";
    358 				break;
    359 			default:
    360 				break;
    361 			}
    362 		}
    363 		if (fils_erp_next_seq_num)
    364 			event.assoc_reject.fils_erp_next_seq_num =
    365 				nla_get_u16(fils_erp_next_seq_num);
    366 		wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
    367 		return;
    368 	}
    369 
    370 	drv->associated = 1;
    371 	if (addr) {
    372 		os_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);
    373 		os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
    374 	}
    375 
    376 	if (req_ie) {
    377 		event.assoc_info.req_ies = nla_data(req_ie);
    378 		event.assoc_info.req_ies_len = nla_len(req_ie);
    379 
    380 		if (cmd == NL80211_CMD_ROAM) {
    381 			ssid = get_ie(event.assoc_info.req_ies,
    382 				      event.assoc_info.req_ies_len,
    383 				      WLAN_EID_SSID);
    384 			if (ssid && ssid[1] > 0 && ssid[1] <= 32) {
    385 				drv->ssid_len = ssid[1];
    386 				os_memcpy(drv->ssid, ssid + 2, ssid[1]);
    387 				wpa_printf(MSG_DEBUG,
    388 					   "nl80211: Set drv->ssid based on req_ie to '%s'",
    389 					   wpa_ssid_txt(drv->ssid,
    390 							drv->ssid_len));
    391 			}
    392 		}
    393 	}
    394 	if (resp_ie) {
    395 		event.assoc_info.resp_ies = nla_data(resp_ie);
    396 		event.assoc_info.resp_ies_len = nla_len(resp_ie);
    397 	}
    398 
    399 	event.assoc_info.freq = nl80211_get_assoc_freq(drv);
    400 
    401 	if ((!ssid || ssid[1] == 0 || ssid[1] > 32) &&
    402 	    (ssid_len = nl80211_get_assoc_ssid(drv, drv->ssid)) > 0) {
    403 		/* When this connection was initiated outside of wpa_supplicant,
    404 		 * drv->ssid needs to be set here to satisfy later checking. */
    405 		drv->ssid_len = ssid_len;
    406 		wpa_printf(MSG_DEBUG,
    407 			   "nl80211: Set drv->ssid based on scan res info to '%s'",
    408 			   wpa_ssid_txt(drv->ssid, drv->ssid_len));
    409 	}
    410 
    411 	if (authorized && nla_get_u8(authorized)) {
    412 		event.assoc_info.authorized = 1;
    413 		wpa_printf(MSG_DEBUG, "nl80211: connection authorized");
    414 	}
    415 	if (key_replay_ctr) {
    416 		event.assoc_info.key_replay_ctr = nla_data(key_replay_ctr);
    417 		event.assoc_info.key_replay_ctr_len = nla_len(key_replay_ctr);
    418 	}
    419 	if (ptk_kck) {
    420 		event.assoc_info.ptk_kck = nla_data(ptk_kck);
    421 		event.assoc_info.ptk_kck_len = nla_len(ptk_kck);
    422 	}
    423 	if (ptk_kek) {
    424 		event.assoc_info.ptk_kek = nla_data(ptk_kek);
    425 		event.assoc_info.ptk_kek_len = nla_len(ptk_kek);
    426 	}
    427 
    428 	if (subnet_status) {
    429 		/*
    430 		 * At least for now, this is only available from
    431 		 * QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS and that
    432 		 * attribute has the same values 0, 1, 2 as are used in the
    433 		 * variable here, so no mapping between different values are
    434 		 * needed.
    435 		 */
    436 		event.assoc_info.subnet_status = nla_get_u8(subnet_status);
    437 	}
    438 
    439 	if (fils_erp_next_seq_num)
    440 		event.assoc_info.fils_erp_next_seq_num =
    441 			nla_get_u16(fils_erp_next_seq_num);
    442 
    443 	if (fils_pmk) {
    444 		event.assoc_info.fils_pmk = nla_data(fils_pmk);
    445 		event.assoc_info.fils_pmk_len = nla_len(fils_pmk);
    446 	}
    447 
    448 	if (fils_pmkid)
    449 		event.assoc_info.fils_pmkid = nla_data(fils_pmkid);
    450 
    451 	wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
    452 }
    453 
    454 
    455 static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv,
    456 				  struct nlattr *reason, struct nlattr *addr,
    457 				  struct nlattr *by_ap)
    458 {
    459 	union wpa_event_data data;
    460 	unsigned int locally_generated = by_ap == NULL;
    461 
    462 	if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
    463 		/*
    464 		 * Avoid reporting two disassociation events that could
    465 		 * confuse the core code.
    466 		 */
    467 		wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
    468 			   "event when using userspace SME");
    469 		return;
    470 	}
    471 
    472 	if (drv->ignore_next_local_disconnect) {
    473 		drv->ignore_next_local_disconnect = 0;
    474 		if (locally_generated) {
    475 			wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
    476 				   "event triggered during reassociation");
    477 			return;
    478 		}
    479 		wpa_printf(MSG_WARNING, "nl80211: Was expecting local "
    480 			   "disconnect but got another disconnect "
    481 			   "event first");
    482 	}
    483 
    484 	wpa_printf(MSG_DEBUG, "nl80211: Disconnect event");
    485 	nl80211_mark_disconnected(drv);
    486 	os_memset(&data, 0, sizeof(data));
    487 	if (reason)
    488 		data.deauth_info.reason_code = nla_get_u16(reason);
    489 	data.deauth_info.locally_generated = by_ap == NULL;
    490 	wpa_supplicant_event(drv->ctx, EVENT_DEAUTH, &data);
    491 }
    492 
    493 
    494 static int calculate_chan_offset(int width, int freq, int cf1, int cf2)
    495 {
    496 	int freq1 = 0;
    497 
    498 	switch (convert2width(width)) {
    499 	case CHAN_WIDTH_20_NOHT:
    500 	case CHAN_WIDTH_20:
    501 		return 0;
    502 	case CHAN_WIDTH_40:
    503 		freq1 = cf1 - 10;
    504 		break;
    505 	case CHAN_WIDTH_80:
    506 		freq1 = cf1 - 30;
    507 		break;
    508 	case CHAN_WIDTH_160:
    509 		freq1 = cf1 - 70;
    510 		break;
    511 	case CHAN_WIDTH_UNKNOWN:
    512 	case CHAN_WIDTH_80P80:
    513 		/* FIXME: implement this */
    514 		return 0;
    515 	}
    516 
    517 	return (abs(freq - freq1) / 20) % 2 == 0 ? 1 : -1;
    518 }
    519 
    520 
    521 static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
    522 				 struct nlattr *ifindex, struct nlattr *freq,
    523 				 struct nlattr *type, struct nlattr *bw,
    524 				 struct nlattr *cf1, struct nlattr *cf2)
    525 {
    526 	struct i802_bss *bss;
    527 	union wpa_event_data data;
    528 	int ht_enabled = 1;
    529 	int chan_offset = 0;
    530 	int ifidx;
    531 
    532 	wpa_printf(MSG_DEBUG, "nl80211: Channel switch event");
    533 
    534 	if (!freq)
    535 		return;
    536 
    537 	ifidx = nla_get_u32(ifindex);
    538 	bss = get_bss_ifindex(drv, ifidx);
    539 	if (bss == NULL) {
    540 		wpa_printf(MSG_WARNING, "nl80211: Unknown ifindex (%d) for channel switch, ignoring",
    541 			   ifidx);
    542 		return;
    543 	}
    544 
    545 	if (type) {
    546 		enum nl80211_channel_type ch_type = nla_get_u32(type);
    547 
    548 		wpa_printf(MSG_DEBUG, "nl80211: Channel type: %d", ch_type);
    549 		switch (ch_type) {
    550 		case NL80211_CHAN_NO_HT:
    551 			ht_enabled = 0;
    552 			break;
    553 		case NL80211_CHAN_HT20:
    554 			break;
    555 		case NL80211_CHAN_HT40PLUS:
    556 			chan_offset = 1;
    557 			break;
    558 		case NL80211_CHAN_HT40MINUS:
    559 			chan_offset = -1;
    560 			break;
    561 		}
    562 	} else if (bw && cf1) {
    563 		/* This can happen for example with VHT80 ch switch */
    564 		chan_offset = calculate_chan_offset(nla_get_u32(bw),
    565 						    nla_get_u32(freq),
    566 						    nla_get_u32(cf1),
    567 						    cf2 ? nla_get_u32(cf2) : 0);
    568 	} else {
    569 		wpa_printf(MSG_WARNING, "nl80211: Unknown secondary channel information - following channel definition calculations may fail");
    570 	}
    571 
    572 	os_memset(&data, 0, sizeof(data));
    573 	data.ch_switch.freq = nla_get_u32(freq);
    574 	data.ch_switch.ht_enabled = ht_enabled;
    575 	data.ch_switch.ch_offset = chan_offset;
    576 	if (bw)
    577 		data.ch_switch.ch_width = convert2width(nla_get_u32(bw));
    578 	if (cf1)
    579 		data.ch_switch.cf1 = nla_get_u32(cf1);
    580 	if (cf2)
    581 		data.ch_switch.cf2 = nla_get_u32(cf2);
    582 
    583 	bss->freq = data.ch_switch.freq;
    584 	drv->assoc_freq = data.ch_switch.freq;
    585 
    586 	wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH, &data);
    587 }
    588 
    589 
    590 static void mlme_timeout_event(struct wpa_driver_nl80211_data *drv,
    591 			       enum nl80211_commands cmd, struct nlattr *addr)
    592 {
    593 	union wpa_event_data event;
    594 	enum wpa_event_type ev;
    595 
    596 	if (nla_len(addr) != ETH_ALEN)
    597 		return;
    598 
    599 	wpa_printf(MSG_DEBUG, "nl80211: MLME event %d; timeout with " MACSTR,
    600 		   cmd, MAC2STR((u8 *) nla_data(addr)));
    601 
    602 	if (cmd == NL80211_CMD_AUTHENTICATE)
    603 		ev = EVENT_AUTH_TIMED_OUT;
    604 	else if (cmd == NL80211_CMD_ASSOCIATE)
    605 		ev = EVENT_ASSOC_TIMED_OUT;
    606 	else
    607 		return;
    608 
    609 	os_memset(&event, 0, sizeof(event));
    610 	os_memcpy(event.timeout_event.addr, nla_data(addr), ETH_ALEN);
    611 	wpa_supplicant_event(drv->ctx, ev, &event);
    612 }
    613 
    614 
    615 static void mlme_event_mgmt(struct i802_bss *bss,
    616 			    struct nlattr *freq, struct nlattr *sig,
    617 			    const u8 *frame, size_t len)
    618 {
    619 	struct wpa_driver_nl80211_data *drv = bss->drv;
    620 	const struct ieee80211_mgmt *mgmt;
    621 	union wpa_event_data event;
    622 	u16 fc, stype;
    623 	int ssi_signal = 0;
    624 	int rx_freq = 0;
    625 
    626 	wpa_printf(MSG_MSGDUMP, "nl80211: Frame event");
    627 	mgmt = (const struct ieee80211_mgmt *) frame;
    628 	if (len < 24) {
    629 		wpa_printf(MSG_DEBUG, "nl80211: Too short management frame");
    630 		return;
    631 	}
    632 
    633 	fc = le_to_host16(mgmt->frame_control);
    634 	stype = WLAN_FC_GET_STYPE(fc);
    635 
    636 	if (sig)
    637 		ssi_signal = (s32) nla_get_u32(sig);
    638 
    639 	os_memset(&event, 0, sizeof(event));
    640 	if (freq) {
    641 		event.rx_mgmt.freq = nla_get_u32(freq);
    642 		rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
    643 	}
    644 	wpa_printf(MSG_DEBUG,
    645 		   "nl80211: RX frame da=" MACSTR " sa=" MACSTR " bssid=" MACSTR
    646 		   " freq=%d ssi_signal=%d fc=0x%x seq_ctrl=0x%x stype=%u (%s) len=%u",
    647 		   MAC2STR(mgmt->da), MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid),
    648 		   rx_freq, ssi_signal, fc,
    649 		   le_to_host16(mgmt->seq_ctrl), stype, fc2str(fc),
    650 		   (unsigned int) len);
    651 	event.rx_mgmt.frame = frame;
    652 	event.rx_mgmt.frame_len = len;
    653 	event.rx_mgmt.ssi_signal = ssi_signal;
    654 	event.rx_mgmt.drv_priv = bss;
    655 	wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
    656 }
    657 
    658 
    659 static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv,
    660 				      struct nlattr *cookie, const u8 *frame,
    661 				      size_t len, struct nlattr *ack)
    662 {
    663 	union wpa_event_data event;
    664 	const struct ieee80211_hdr *hdr;
    665 	u16 fc;
    666 
    667 	wpa_printf(MSG_DEBUG, "nl80211: Frame TX status event");
    668 	if (!is_ap_interface(drv->nlmode)) {
    669 		u64 cookie_val;
    670 
    671 		if (!cookie)
    672 			return;
    673 
    674 		cookie_val = nla_get_u64(cookie);
    675 		wpa_printf(MSG_DEBUG, "nl80211: Action TX status:"
    676 			   " cookie=0%llx%s (ack=%d)",
    677 			   (long long unsigned int) cookie_val,
    678 			   cookie_val == drv->send_action_cookie ?
    679 			   " (match)" : " (unknown)", ack != NULL);
    680 		if (cookie_val != drv->send_action_cookie)
    681 			return;
    682 	}
    683 
    684 	hdr = (const struct ieee80211_hdr *) frame;
    685 	fc = le_to_host16(hdr->frame_control);
    686 
    687 	os_memset(&event, 0, sizeof(event));
    688 	event.tx_status.type = WLAN_FC_GET_TYPE(fc);
    689 	event.tx_status.stype = WLAN_FC_GET_STYPE(fc);
    690 	event.tx_status.dst = hdr->addr1;
    691 	event.tx_status.data = frame;
    692 	event.tx_status.data_len = len;
    693 	event.tx_status.ack = ack != NULL;
    694 	wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);
    695 }
    696 
    697 
    698 static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
    699 				       enum wpa_event_type type,
    700 				       const u8 *frame, size_t len)
    701 {
    702 	const struct ieee80211_mgmt *mgmt;
    703 	union wpa_event_data event;
    704 	const u8 *bssid = NULL;
    705 	u16 reason_code = 0;
    706 
    707 	if (type == EVENT_DEAUTH)
    708 		wpa_printf(MSG_DEBUG, "nl80211: Deauthenticate event");
    709 	else
    710 		wpa_printf(MSG_DEBUG, "nl80211: Disassociate event");
    711 
    712 	mgmt = (const struct ieee80211_mgmt *) frame;
    713 	if (len >= 24) {
    714 		bssid = mgmt->bssid;
    715 
    716 		if ((drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
    717 		    !drv->associated &&
    718 		    os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0 &&
    719 		    os_memcmp(bssid, drv->auth_attempt_bssid, ETH_ALEN) != 0 &&
    720 		    os_memcmp(bssid, drv->prev_bssid, ETH_ALEN) == 0) {
    721 			/*
    722 			 * Avoid issues with some roaming cases where
    723 			 * disconnection event for the old AP may show up after
    724 			 * we have started connection with the new AP.
    725 			 * In case of locally generated event clear
    726 			 * ignore_next_local_deauth as well, to avoid next local
    727 			 * deauth event be wrongly ignored.
    728 			 */
    729 			if (!os_memcmp(mgmt->sa, drv->first_bss->addr,
    730 				       ETH_ALEN)) {
    731 				wpa_printf(MSG_DEBUG,
    732 					   "nl80211: Received a locally generated deauth event. Clear ignore_next_local_deauth flag");
    733 				drv->ignore_next_local_deauth = 0;
    734 			} else {
    735 				wpa_printf(MSG_DEBUG,
    736 					   "nl80211: Ignore deauth/disassoc event from old AP " MACSTR " when already authenticating with " MACSTR,
    737 					   MAC2STR(bssid),
    738 					   MAC2STR(drv->auth_attempt_bssid));
    739 			}
    740 			return;
    741 		}
    742 
    743 		if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
    744 		    drv->connect_reassoc && drv->associated &&
    745 		    os_memcmp(bssid, drv->prev_bssid, ETH_ALEN) == 0 &&
    746 		    os_memcmp(bssid, drv->auth_attempt_bssid, ETH_ALEN) != 0) {
    747 			/*
    748 			 * Avoid issues with some roaming cases where
    749 			 * disconnection event for the old AP may show up after
    750 			 * we have started connection with the new AP.
    751 			 */
    752 			 wpa_printf(MSG_DEBUG,
    753 				    "nl80211: Ignore deauth/disassoc event from old AP "
    754 				    MACSTR
    755 				    " when already connecting with " MACSTR,
    756 				    MAC2STR(bssid),
    757 				    MAC2STR(drv->auth_attempt_bssid));
    758 			return;
    759 		}
    760 
    761 		if (drv->associated != 0 &&
    762 		    os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&
    763 		    os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {
    764 			/*
    765 			 * We have presumably received this deauth as a
    766 			 * response to a clear_state_mismatch() outgoing
    767 			 * deauth.  Don't let it take us offline!
    768 			 */
    769 			wpa_printf(MSG_DEBUG, "nl80211: Deauth received "
    770 				   "from Unknown BSSID " MACSTR " -- ignoring",
    771 				   MAC2STR(bssid));
    772 			return;
    773 		}
    774 	}
    775 
    776 	nl80211_mark_disconnected(drv);
    777 	os_memset(&event, 0, sizeof(event));
    778 
    779 	/* Note: Same offset for Reason Code in both frame subtypes */
    780 	if (len >= 24 + sizeof(mgmt->u.deauth))
    781 		reason_code = le_to_host16(mgmt->u.deauth.reason_code);
    782 
    783 	if (type == EVENT_DISASSOC) {
    784 		event.disassoc_info.locally_generated =
    785 			!os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
    786 		event.disassoc_info.addr = bssid;
    787 		event.disassoc_info.reason_code = reason_code;
    788 		if (frame + len > mgmt->u.disassoc.variable) {
    789 			event.disassoc_info.ie = mgmt->u.disassoc.variable;
    790 			event.disassoc_info.ie_len = frame + len -
    791 				mgmt->u.disassoc.variable;
    792 		}
    793 	} else {
    794 		event.deauth_info.locally_generated =
    795 			!os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
    796 		if (drv->ignore_deauth_event) {
    797 			wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth event due to previous forced deauth-during-auth");
    798 			drv->ignore_deauth_event = 0;
    799 			if (event.deauth_info.locally_generated)
    800 				drv->ignore_next_local_deauth = 0;
    801 			return;
    802 		}
    803 		if (drv->ignore_next_local_deauth) {
    804 			drv->ignore_next_local_deauth = 0;
    805 			if (event.deauth_info.locally_generated) {
    806 				wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth event triggered due to own deauth request");
    807 				return;
    808 			}
    809 			wpa_printf(MSG_WARNING, "nl80211: Was expecting local deauth but got another disconnect event first");
    810 		}
    811 		event.deauth_info.addr = bssid;
    812 		event.deauth_info.reason_code = reason_code;
    813 		if (frame + len > mgmt->u.deauth.variable) {
    814 			event.deauth_info.ie = mgmt->u.deauth.variable;
    815 			event.deauth_info.ie_len = frame + len -
    816 				mgmt->u.deauth.variable;
    817 		}
    818 	}
    819 
    820 	wpa_supplicant_event(drv->ctx, type, &event);
    821 }
    822 
    823 
    824 static void mlme_event_unprot_disconnect(struct wpa_driver_nl80211_data *drv,
    825 					 enum wpa_event_type type,
    826 					 const u8 *frame, size_t len)
    827 {
    828 	const struct ieee80211_mgmt *mgmt;
    829 	union wpa_event_data event;
    830 	u16 reason_code = 0;
    831 
    832 	if (type == EVENT_UNPROT_DEAUTH)
    833 		wpa_printf(MSG_DEBUG, "nl80211: Unprot Deauthenticate event");
    834 	else
    835 		wpa_printf(MSG_DEBUG, "nl80211: Unprot Disassociate event");
    836 
    837 	if (len < 24)
    838 		return;
    839 
    840 	mgmt = (const struct ieee80211_mgmt *) frame;
    841 
    842 	os_memset(&event, 0, sizeof(event));
    843 	/* Note: Same offset for Reason Code in both frame subtypes */
    844 	if (len >= 24 + sizeof(mgmt->u.deauth))
    845 		reason_code = le_to_host16(mgmt->u.deauth.reason_code);
    846 
    847 	if (type == EVENT_UNPROT_DISASSOC) {
    848 		event.unprot_disassoc.sa = mgmt->sa;
    849 		event.unprot_disassoc.da = mgmt->da;
    850 		event.unprot_disassoc.reason_code = reason_code;
    851 	} else {
    852 		event.unprot_deauth.sa = mgmt->sa;
    853 		event.unprot_deauth.da = mgmt->da;
    854 		event.unprot_deauth.reason_code = reason_code;
    855 	}
    856 
    857 	wpa_supplicant_event(drv->ctx, type, &event);
    858 }
    859 
    860 
    861 static void mlme_event(struct i802_bss *bss,
    862 		       enum nl80211_commands cmd, struct nlattr *frame,
    863 		       struct nlattr *addr, struct nlattr *timed_out,
    864 		       struct nlattr *freq, struct nlattr *ack,
    865 		       struct nlattr *cookie, struct nlattr *sig,
    866 		       struct nlattr *wmm)
    867 {
    868 	struct wpa_driver_nl80211_data *drv = bss->drv;
    869 	const u8 *data;
    870 	size_t len;
    871 
    872 	if (timed_out && addr) {
    873 		mlme_timeout_event(drv, cmd, addr);
    874 		return;
    875 	}
    876 
    877 	if (frame == NULL) {
    878 		wpa_printf(MSG_DEBUG,
    879 			   "nl80211: MLME event %d (%s) without frame data",
    880 			   cmd, nl80211_command_to_string(cmd));
    881 		return;
    882 	}
    883 
    884 	data = nla_data(frame);
    885 	len = nla_len(frame);
    886 	if (len < 4 + 2 * ETH_ALEN) {
    887 		wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d (%s) on %s("
    888 			   MACSTR ") - too short",
    889 			   cmd, nl80211_command_to_string(cmd), bss->ifname,
    890 			   MAC2STR(bss->addr));
    891 		return;
    892 	}
    893 	wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d (%s) on %s(" MACSTR
    894 		   ") A1=" MACSTR " A2=" MACSTR, cmd,
    895 		   nl80211_command_to_string(cmd), bss->ifname,
    896 		   MAC2STR(bss->addr), MAC2STR(data + 4),
    897 		   MAC2STR(data + 4 + ETH_ALEN));
    898 	if (cmd != NL80211_CMD_FRAME_TX_STATUS && !(data[4] & 0x01) &&
    899 	    os_memcmp(bss->addr, data + 4, ETH_ALEN) != 0 &&
    900 	    (is_zero_ether_addr(bss->rand_addr) ||
    901 	     os_memcmp(bss->rand_addr, data + 4, ETH_ALEN) != 0) &&
    902 	    os_memcmp(bss->addr, data + 4 + ETH_ALEN, ETH_ALEN) != 0) {
    903 		wpa_printf(MSG_MSGDUMP, "nl80211: %s: Ignore MLME frame event "
    904 			   "for foreign address", bss->ifname);
    905 		return;
    906 	}
    907 	wpa_hexdump(MSG_MSGDUMP, "nl80211: MLME event frame",
    908 		    nla_data(frame), nla_len(frame));
    909 
    910 	switch (cmd) {
    911 	case NL80211_CMD_AUTHENTICATE:
    912 		mlme_event_auth(drv, nla_data(frame), nla_len(frame));
    913 		break;
    914 	case NL80211_CMD_ASSOCIATE:
    915 		mlme_event_assoc(drv, nla_data(frame), nla_len(frame), wmm);
    916 		break;
    917 	case NL80211_CMD_DEAUTHENTICATE:
    918 		mlme_event_deauth_disassoc(drv, EVENT_DEAUTH,
    919 					   nla_data(frame), nla_len(frame));
    920 		break;
    921 	case NL80211_CMD_DISASSOCIATE:
    922 		mlme_event_deauth_disassoc(drv, EVENT_DISASSOC,
    923 					   nla_data(frame), nla_len(frame));
    924 		break;
    925 	case NL80211_CMD_FRAME:
    926 		mlme_event_mgmt(bss, freq, sig, nla_data(frame),
    927 				nla_len(frame));
    928 		break;
    929 	case NL80211_CMD_FRAME_TX_STATUS:
    930 		mlme_event_mgmt_tx_status(drv, cookie, nla_data(frame),
    931 					  nla_len(frame), ack);
    932 		break;
    933 	case NL80211_CMD_UNPROT_DEAUTHENTICATE:
    934 		mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DEAUTH,
    935 					     nla_data(frame), nla_len(frame));
    936 		break;
    937 	case NL80211_CMD_UNPROT_DISASSOCIATE:
    938 		mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC,
    939 					     nla_data(frame), nla_len(frame));
    940 		break;
    941 	default:
    942 		break;
    943 	}
    944 }
    945 
    946 
    947 static void mlme_event_michael_mic_failure(struct i802_bss *bss,
    948 					   struct nlattr *tb[])
    949 {
    950 	union wpa_event_data data;
    951 
    952 	wpa_printf(MSG_DEBUG, "nl80211: MLME event Michael MIC failure");
    953 	os_memset(&data, 0, sizeof(data));
    954 	if (tb[NL80211_ATTR_MAC]) {
    955 		wpa_hexdump(MSG_DEBUG, "nl80211: Source MAC address",
    956 			    nla_data(tb[NL80211_ATTR_MAC]),
    957 			    nla_len(tb[NL80211_ATTR_MAC]));
    958 		data.michael_mic_failure.src = nla_data(tb[NL80211_ATTR_MAC]);
    959 	}
    960 	if (tb[NL80211_ATTR_KEY_SEQ]) {
    961 		wpa_hexdump(MSG_DEBUG, "nl80211: TSC",
    962 			    nla_data(tb[NL80211_ATTR_KEY_SEQ]),
    963 			    nla_len(tb[NL80211_ATTR_KEY_SEQ]));
    964 	}
    965 	if (tb[NL80211_ATTR_KEY_TYPE]) {
    966 		enum nl80211_key_type key_type =
    967 			nla_get_u32(tb[NL80211_ATTR_KEY_TYPE]);
    968 		wpa_printf(MSG_DEBUG, "nl80211: Key Type %d", key_type);
    969 		if (key_type == NL80211_KEYTYPE_PAIRWISE)
    970 			data.michael_mic_failure.unicast = 1;
    971 	} else
    972 		data.michael_mic_failure.unicast = 1;
    973 
    974 	if (tb[NL80211_ATTR_KEY_IDX]) {
    975 		u8 key_id = nla_get_u8(tb[NL80211_ATTR_KEY_IDX]);
    976 		wpa_printf(MSG_DEBUG, "nl80211: Key Id %d", key_id);
    977 	}
    978 
    979 	wpa_supplicant_event(bss->ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
    980 }
    981 
    982 
    983 static void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv,
    984 				 struct nlattr *tb[])
    985 {
    986 	unsigned int freq;
    987 	union wpa_event_data event;
    988 
    989 	if (tb[NL80211_ATTR_MAC] == NULL) {
    990 		wpa_printf(MSG_DEBUG, "nl80211: No address in IBSS joined "
    991 			   "event");
    992 		return;
    993 	}
    994 	os_memcpy(drv->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
    995 
    996 	drv->associated = 1;
    997 	wpa_printf(MSG_DEBUG, "nl80211: IBSS " MACSTR " joined",
    998 		   MAC2STR(drv->bssid));
    999 
   1000 	freq = nl80211_get_assoc_freq(drv);
   1001 	if (freq) {
   1002 		wpa_printf(MSG_DEBUG, "nl80211: IBSS on frequency %u MHz",
   1003 			   freq);
   1004 		drv->first_bss->freq = freq;
   1005 	}
   1006 
   1007 	os_memset(&event, 0, sizeof(event));
   1008 	event.assoc_info.freq = freq;
   1009 
   1010 	wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
   1011 }
   1012 
   1013 
   1014 static void mlme_event_remain_on_channel(struct wpa_driver_nl80211_data *drv,
   1015 					 int cancel_event, struct nlattr *tb[])
   1016 {
   1017 	unsigned int freq, chan_type, duration;
   1018 	union wpa_event_data data;
   1019 	u64 cookie;
   1020 
   1021 	if (tb[NL80211_ATTR_WIPHY_FREQ])
   1022 		freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
   1023 	else
   1024 		freq = 0;
   1025 
   1026 	if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
   1027 		chan_type = nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
   1028 	else
   1029 		chan_type = 0;
   1030 
   1031 	if (tb[NL80211_ATTR_DURATION])
   1032 		duration = nla_get_u32(tb[NL80211_ATTR_DURATION]);
   1033 	else
   1034 		duration = 0;
   1035 
   1036 	if (tb[NL80211_ATTR_COOKIE])
   1037 		cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
   1038 	else
   1039 		cookie = 0;
   1040 
   1041 	wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel event (cancel=%d "
   1042 		   "freq=%u channel_type=%u duration=%u cookie=0x%llx (%s))",
   1043 		   cancel_event, freq, chan_type, duration,
   1044 		   (long long unsigned int) cookie,
   1045 		   cookie == drv->remain_on_chan_cookie ? "match" : "unknown");
   1046 
   1047 	if (cookie != drv->remain_on_chan_cookie)
   1048 		return; /* not for us */
   1049 
   1050 	if (cancel_event)
   1051 		drv->pending_remain_on_chan = 0;
   1052 
   1053 	os_memset(&data, 0, sizeof(data));
   1054 	data.remain_on_channel.freq = freq;
   1055 	data.remain_on_channel.duration = duration;
   1056 	wpa_supplicant_event(drv->ctx, cancel_event ?
   1057 			     EVENT_CANCEL_REMAIN_ON_CHANNEL :
   1058 			     EVENT_REMAIN_ON_CHANNEL, &data);
   1059 }
   1060 
   1061 
   1062 static void mlme_event_ft_event(struct wpa_driver_nl80211_data *drv,
   1063 				struct nlattr *tb[])
   1064 {
   1065 	union wpa_event_data data;
   1066 
   1067 	os_memset(&data, 0, sizeof(data));
   1068 
   1069 	if (tb[NL80211_ATTR_IE]) {
   1070 		data.ft_ies.ies = nla_data(tb[NL80211_ATTR_IE]);
   1071 		data.ft_ies.ies_len = nla_len(tb[NL80211_ATTR_IE]);
   1072 	}
   1073 
   1074 	if (tb[NL80211_ATTR_IE_RIC]) {
   1075 		data.ft_ies.ric_ies = nla_data(tb[NL80211_ATTR_IE_RIC]);
   1076 		data.ft_ies.ric_ies_len = nla_len(tb[NL80211_ATTR_IE_RIC]);
   1077 	}
   1078 
   1079 	if (tb[NL80211_ATTR_MAC])
   1080 		os_memcpy(data.ft_ies.target_ap,
   1081 			  nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
   1082 
   1083 	wpa_printf(MSG_DEBUG, "nl80211: FT event target_ap " MACSTR,
   1084 		   MAC2STR(data.ft_ies.target_ap));
   1085 
   1086 	wpa_supplicant_event(drv->ctx, EVENT_FT_RESPONSE, &data);
   1087 }
   1088 
   1089 
   1090 static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
   1091 			    struct nlattr *tb[], int external_scan)
   1092 {
   1093 	union wpa_event_data event;
   1094 	struct nlattr *nl;
   1095 	int rem;
   1096 	struct scan_info *info;
   1097 #define MAX_REPORT_FREQS 50
   1098 	int freqs[MAX_REPORT_FREQS];
   1099 	int num_freqs = 0;
   1100 
   1101 	if (!external_scan && drv->scan_for_auth) {
   1102 		drv->scan_for_auth = 0;
   1103 		wpa_printf(MSG_DEBUG, "nl80211: Scan results for missing "
   1104 			   "cfg80211 BSS entry");
   1105 		wpa_driver_nl80211_authenticate_retry(drv);
   1106 		return;
   1107 	}
   1108 
   1109 	os_memset(&event, 0, sizeof(event));
   1110 	info = &event.scan_info;
   1111 	info->aborted = aborted;
   1112 	info->external_scan = external_scan;
   1113 	info->nl_scan_event = 1;
   1114 
   1115 	if (tb[NL80211_ATTR_SCAN_SSIDS]) {
   1116 		nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_SSIDS], rem) {
   1117 			struct wpa_driver_scan_ssid *s =
   1118 				&info->ssids[info->num_ssids];
   1119 			s->ssid = nla_data(nl);
   1120 			s->ssid_len = nla_len(nl);
   1121 			wpa_printf(MSG_DEBUG, "nl80211: Scan probed for SSID '%s'",
   1122 				   wpa_ssid_txt(s->ssid, s->ssid_len));
   1123 			info->num_ssids++;
   1124 			if (info->num_ssids == WPAS_MAX_SCAN_SSIDS)
   1125 				break;
   1126 		}
   1127 	}
   1128 	if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {
   1129 		char msg[300], *pos, *end;
   1130 		int res;
   1131 
   1132 		pos = msg;
   1133 		end = pos + sizeof(msg);
   1134 		*pos = '\0';
   1135 
   1136 		nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem)
   1137 		{
   1138 			freqs[num_freqs] = nla_get_u32(nl);
   1139 			res = os_snprintf(pos, end - pos, " %d",
   1140 					  freqs[num_freqs]);
   1141 			if (!os_snprintf_error(end - pos, res))
   1142 				pos += res;
   1143 			num_freqs++;
   1144 			if (num_freqs == MAX_REPORT_FREQS - 1)
   1145 				break;
   1146 		}
   1147 		info->freqs = freqs;
   1148 		info->num_freqs = num_freqs;
   1149 		wpa_printf(MSG_DEBUG, "nl80211: Scan included frequencies:%s",
   1150 			   msg);
   1151 	}
   1152 
   1153 	if (tb[NL80211_ATTR_SCAN_START_TIME_TSF] &&
   1154 	    tb[NL80211_ATTR_SCAN_START_TIME_TSF_BSSID]) {
   1155 		info->scan_start_tsf =
   1156 			nla_get_u64(tb[NL80211_ATTR_SCAN_START_TIME_TSF]);
   1157 		os_memcpy(info->scan_start_tsf_bssid,
   1158 			  nla_data(tb[NL80211_ATTR_SCAN_START_TIME_TSF_BSSID]),
   1159 			  ETH_ALEN);
   1160 	}
   1161 
   1162 	wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
   1163 }
   1164 
   1165 
   1166 static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
   1167 			      struct nlattr *tb[])
   1168 {
   1169 	static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
   1170 		[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
   1171 		[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },
   1172 		[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
   1173 		[NL80211_ATTR_CQM_PKT_LOSS_EVENT] = { .type = NLA_U32 },
   1174 		[NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
   1175 		[NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
   1176 		[NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
   1177 		[NL80211_ATTR_CQM_BEACON_LOSS_EVENT] = { .type = NLA_FLAG },
   1178 	};
   1179 	struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1];
   1180 	enum nl80211_cqm_rssi_threshold_event event;
   1181 	union wpa_event_data ed;
   1182 	struct wpa_signal_info sig;
   1183 	int res;
   1184 
   1185 	if (tb[NL80211_ATTR_CQM] == NULL ||
   1186 	    nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb[NL80211_ATTR_CQM],
   1187 			     cqm_policy)) {
   1188 		wpa_printf(MSG_DEBUG, "nl80211: Ignore invalid CQM event");
   1189 		return;
   1190 	}
   1191 
   1192 	os_memset(&ed, 0, sizeof(ed));
   1193 
   1194 	if (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) {
   1195 		if (!tb[NL80211_ATTR_MAC])
   1196 			return;
   1197 		os_memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]),
   1198 			  ETH_ALEN);
   1199 		ed.low_ack.num_packets =
   1200 			nla_get_u32(cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]);
   1201 		wpa_printf(MSG_DEBUG, "nl80211: Packet loss event for " MACSTR
   1202 			   " (num_packets %u)",
   1203 			   MAC2STR(ed.low_ack.addr), ed.low_ack.num_packets);
   1204 		wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);
   1205 		return;
   1206 	}
   1207 
   1208 	if (cqm[NL80211_ATTR_CQM_BEACON_LOSS_EVENT]) {
   1209 		wpa_printf(MSG_DEBUG, "nl80211: Beacon loss event");
   1210 		wpa_supplicant_event(drv->ctx, EVENT_BEACON_LOSS, NULL);
   1211 		return;
   1212 	}
   1213 
   1214 	if (cqm[NL80211_ATTR_CQM_TXE_RATE] &&
   1215 	    cqm[NL80211_ATTR_CQM_TXE_PKTS] &&
   1216 	    cqm[NL80211_ATTR_CQM_TXE_INTVL] &&
   1217 	    cqm[NL80211_ATTR_MAC]) {
   1218 		wpa_printf(MSG_DEBUG, "nl80211: CQM TXE event for " MACSTR
   1219 			   " (rate: %u pkts: %u interval: %u)",
   1220 			   MAC2STR((u8 *) nla_data(cqm[NL80211_ATTR_MAC])),
   1221 			   nla_get_u32(cqm[NL80211_ATTR_CQM_TXE_RATE]),
   1222 			   nla_get_u32(cqm[NL80211_ATTR_CQM_TXE_PKTS]),
   1223 			   nla_get_u32(cqm[NL80211_ATTR_CQM_TXE_INTVL]));
   1224 		return;
   1225 	}
   1226 
   1227 	if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL) {
   1228 		wpa_printf(MSG_DEBUG,
   1229 			   "nl80211: Not a CQM RSSI threshold event");
   1230 		return;
   1231 	}
   1232 	event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]);
   1233 
   1234 	if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) {
   1235 		wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
   1236 			   "event: RSSI high");
   1237 		ed.signal_change.above_threshold = 1;
   1238 	} else if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW) {
   1239 		wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
   1240 			   "event: RSSI low");
   1241 		ed.signal_change.above_threshold = 0;
   1242 	} else {
   1243 		wpa_printf(MSG_DEBUG,
   1244 			   "nl80211: Unknown CQM RSSI threshold event: %d",
   1245 			   event);
   1246 		return;
   1247 	}
   1248 
   1249 	res = nl80211_get_link_signal(drv, &sig);
   1250 	if (res == 0) {
   1251 		ed.signal_change.current_signal = sig.current_signal;
   1252 		ed.signal_change.current_txrate = sig.current_txrate;
   1253 		wpa_printf(MSG_DEBUG, "nl80211: Signal: %d dBm  txrate: %d",
   1254 			   sig.current_signal, sig.current_txrate);
   1255 	}
   1256 
   1257 	res = nl80211_get_link_noise(drv, &sig);
   1258 	if (res == 0) {
   1259 		ed.signal_change.current_noise = sig.current_noise;
   1260 		wpa_printf(MSG_DEBUG, "nl80211: Noise: %d dBm",
   1261 			   sig.current_noise);
   1262 	}
   1263 
   1264 	wpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed);
   1265 }
   1266 
   1267 
   1268 static void nl80211_new_peer_candidate(struct wpa_driver_nl80211_data *drv,
   1269 				       struct nlattr **tb)
   1270 {
   1271 	const u8 *addr;
   1272 	union wpa_event_data data;
   1273 
   1274 	if (drv->nlmode != NL80211_IFTYPE_MESH_POINT ||
   1275 	    !tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_IE])
   1276 		return;
   1277 
   1278 	addr = nla_data(tb[NL80211_ATTR_MAC]);
   1279 	wpa_printf(MSG_DEBUG, "nl80211: New peer candidate " MACSTR,
   1280 		   MAC2STR(addr));
   1281 
   1282 	os_memset(&data, 0, sizeof(data));
   1283 	data.mesh_peer.peer = addr;
   1284 	data.mesh_peer.ies = nla_data(tb[NL80211_ATTR_IE]);
   1285 	data.mesh_peer.ie_len = nla_len(tb[NL80211_ATTR_IE]);
   1286 	wpa_supplicant_event(drv->ctx, EVENT_NEW_PEER_CANDIDATE, &data);
   1287 }
   1288 
   1289 
   1290 static void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv,
   1291 				      struct i802_bss *bss,
   1292 				      struct nlattr **tb)
   1293 {
   1294 	u8 *addr;
   1295 	union wpa_event_data data;
   1296 
   1297 	if (tb[NL80211_ATTR_MAC] == NULL)
   1298 		return;
   1299 	addr = nla_data(tb[NL80211_ATTR_MAC]);
   1300 	wpa_printf(MSG_DEBUG, "nl80211: New station " MACSTR, MAC2STR(addr));
   1301 
   1302 	if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
   1303 		u8 *ies = NULL;
   1304 		size_t ies_len = 0;
   1305 		if (tb[NL80211_ATTR_IE]) {
   1306 			ies = nla_data(tb[NL80211_ATTR_IE]);
   1307 			ies_len = nla_len(tb[NL80211_ATTR_IE]);
   1308 		}
   1309 		wpa_hexdump(MSG_DEBUG, "nl80211: Assoc Req IEs", ies, ies_len);
   1310 		drv_event_assoc(bss->ctx, addr, ies, ies_len, 0);
   1311 		return;
   1312 	}
   1313 
   1314 	if (drv->nlmode != NL80211_IFTYPE_ADHOC)
   1315 		return;
   1316 
   1317 	os_memset(&data, 0, sizeof(data));
   1318 	os_memcpy(data.ibss_rsn_start.peer, addr, ETH_ALEN);
   1319 	wpa_supplicant_event(bss->ctx, EVENT_IBSS_RSN_START, &data);
   1320 }
   1321 
   1322 
   1323 static void nl80211_del_station_event(struct wpa_driver_nl80211_data *drv,
   1324 				      struct i802_bss *bss,
   1325 				      struct nlattr **tb)
   1326 {
   1327 	u8 *addr;
   1328 	union wpa_event_data data;
   1329 
   1330 	if (tb[NL80211_ATTR_MAC] == NULL)
   1331 		return;
   1332 	addr = nla_data(tb[NL80211_ATTR_MAC]);
   1333 	wpa_printf(MSG_DEBUG, "nl80211: Delete station " MACSTR,
   1334 		   MAC2STR(addr));
   1335 
   1336 	if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
   1337 		drv_event_disassoc(bss->ctx, addr);
   1338 		return;
   1339 	}
   1340 
   1341 	if (drv->nlmode != NL80211_IFTYPE_ADHOC)
   1342 		return;
   1343 
   1344 	os_memset(&data, 0, sizeof(data));
   1345 	os_memcpy(data.ibss_peer_lost.peer, addr, ETH_ALEN);
   1346 	wpa_supplicant_event(bss->ctx, EVENT_IBSS_PEER_LOST, &data);
   1347 }
   1348 
   1349 
   1350 static void nl80211_rekey_offload_event(struct wpa_driver_nl80211_data *drv,
   1351 					struct nlattr **tb)
   1352 {
   1353 	struct nlattr *rekey_info[NUM_NL80211_REKEY_DATA];
   1354 	static struct nla_policy rekey_policy[NUM_NL80211_REKEY_DATA] = {
   1355 		[NL80211_REKEY_DATA_KEK] = {
   1356 			.minlen = NL80211_KEK_LEN,
   1357 			.maxlen = NL80211_KEK_LEN,
   1358 		},
   1359 		[NL80211_REKEY_DATA_KCK] = {
   1360 			.minlen = NL80211_KCK_LEN,
   1361 			.maxlen = NL80211_KCK_LEN,
   1362 		},
   1363 		[NL80211_REKEY_DATA_REPLAY_CTR] = {
   1364 			.minlen = NL80211_REPLAY_CTR_LEN,
   1365 			.maxlen = NL80211_REPLAY_CTR_LEN,
   1366 		},
   1367 	};
   1368 	union wpa_event_data data;
   1369 
   1370 	if (!tb[NL80211_ATTR_MAC] ||
   1371 	    !tb[NL80211_ATTR_REKEY_DATA] ||
   1372 	    nla_parse_nested(rekey_info, MAX_NL80211_REKEY_DATA,
   1373 			     tb[NL80211_ATTR_REKEY_DATA], rekey_policy) ||
   1374 	    !rekey_info[NL80211_REKEY_DATA_REPLAY_CTR])
   1375 		return;
   1376 
   1377 	os_memset(&data, 0, sizeof(data));
   1378 	data.driver_gtk_rekey.bssid = nla_data(tb[NL80211_ATTR_MAC]);
   1379 	wpa_printf(MSG_DEBUG, "nl80211: Rekey offload event for BSSID " MACSTR,
   1380 		   MAC2STR(data.driver_gtk_rekey.bssid));
   1381 	data.driver_gtk_rekey.replay_ctr =
   1382 		nla_data(rekey_info[NL80211_REKEY_DATA_REPLAY_CTR]);
   1383 	wpa_hexdump(MSG_DEBUG, "nl80211: Rekey offload - Replay Counter",
   1384 		    data.driver_gtk_rekey.replay_ctr, NL80211_REPLAY_CTR_LEN);
   1385 	wpa_supplicant_event(drv->ctx, EVENT_DRIVER_GTK_REKEY, &data);
   1386 }
   1387 
   1388 
   1389 static void nl80211_pmksa_candidate_event(struct wpa_driver_nl80211_data *drv,
   1390 					  struct nlattr **tb)
   1391 {
   1392 	struct nlattr *cand[NUM_NL80211_PMKSA_CANDIDATE];
   1393 	static struct nla_policy cand_policy[NUM_NL80211_PMKSA_CANDIDATE] = {
   1394 		[NL80211_PMKSA_CANDIDATE_INDEX] = { .type = NLA_U32 },
   1395 		[NL80211_PMKSA_CANDIDATE_BSSID] = {
   1396 			.minlen = ETH_ALEN,
   1397 			.maxlen = ETH_ALEN,
   1398 		},
   1399 		[NL80211_PMKSA_CANDIDATE_PREAUTH] = { .type = NLA_FLAG },
   1400 	};
   1401 	union wpa_event_data data;
   1402 
   1403 	wpa_printf(MSG_DEBUG, "nl80211: PMKSA candidate event");
   1404 
   1405 	if (!tb[NL80211_ATTR_PMKSA_CANDIDATE] ||
   1406 	    nla_parse_nested(cand, MAX_NL80211_PMKSA_CANDIDATE,
   1407 			     tb[NL80211_ATTR_PMKSA_CANDIDATE], cand_policy) ||
   1408 	    !cand[NL80211_PMKSA_CANDIDATE_INDEX] ||
   1409 	    !cand[NL80211_PMKSA_CANDIDATE_BSSID])
   1410 		return;
   1411 
   1412 	os_memset(&data, 0, sizeof(data));
   1413 	os_memcpy(data.pmkid_candidate.bssid,
   1414 		  nla_data(cand[NL80211_PMKSA_CANDIDATE_BSSID]), ETH_ALEN);
   1415 	data.pmkid_candidate.index =
   1416 		nla_get_u32(cand[NL80211_PMKSA_CANDIDATE_INDEX]);
   1417 	data.pmkid_candidate.preauth =
   1418 		cand[NL80211_PMKSA_CANDIDATE_PREAUTH] != NULL;
   1419 	wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);
   1420 }
   1421 
   1422 
   1423 static void nl80211_client_probe_event(struct wpa_driver_nl80211_data *drv,
   1424 				       struct nlattr **tb)
   1425 {
   1426 	union wpa_event_data data;
   1427 
   1428 	wpa_printf(MSG_DEBUG, "nl80211: Probe client event");
   1429 
   1430 	if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_ACK])
   1431 		return;
   1432 
   1433 	os_memset(&data, 0, sizeof(data));
   1434 	os_memcpy(data.client_poll.addr,
   1435 		  nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
   1436 
   1437 	wpa_supplicant_event(drv->ctx, EVENT_DRIVER_CLIENT_POLL_OK, &data);
   1438 }
   1439 
   1440 
   1441 static void nl80211_tdls_oper_event(struct wpa_driver_nl80211_data *drv,
   1442 				    struct nlattr **tb)
   1443 {
   1444 	union wpa_event_data data;
   1445 
   1446 	wpa_printf(MSG_DEBUG, "nl80211: TDLS operation event");
   1447 
   1448 	if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_TDLS_OPERATION])
   1449 		return;
   1450 
   1451 	os_memset(&data, 0, sizeof(data));
   1452 	os_memcpy(data.tdls.peer, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
   1453 	switch (nla_get_u8(tb[NL80211_ATTR_TDLS_OPERATION])) {
   1454 	case NL80211_TDLS_SETUP:
   1455 		wpa_printf(MSG_DEBUG, "nl80211: TDLS setup request for peer "
   1456 			   MACSTR, MAC2STR(data.tdls.peer));
   1457 		data.tdls.oper = TDLS_REQUEST_SETUP;
   1458 		break;
   1459 	case NL80211_TDLS_TEARDOWN:
   1460 		wpa_printf(MSG_DEBUG, "nl80211: TDLS teardown request for peer "
   1461 			   MACSTR, MAC2STR(data.tdls.peer));
   1462 		data.tdls.oper = TDLS_REQUEST_TEARDOWN;
   1463 		break;
   1464 	case NL80211_TDLS_DISCOVERY_REQ:
   1465 		wpa_printf(MSG_DEBUG,
   1466 			   "nl80211: TDLS discovery request for peer " MACSTR,
   1467 			   MAC2STR(data.tdls.peer));
   1468 		data.tdls.oper = TDLS_REQUEST_DISCOVER;
   1469 		break;
   1470 	default:
   1471 		wpa_printf(MSG_DEBUG, "nl80211: Unsupported TDLS operatione "
   1472 			   "event");
   1473 		return;
   1474 	}
   1475 	if (tb[NL80211_ATTR_REASON_CODE]) {
   1476 		data.tdls.reason_code =
   1477 			nla_get_u16(tb[NL80211_ATTR_REASON_CODE]);
   1478 	}
   1479 
   1480 	wpa_supplicant_event(drv->ctx, EVENT_TDLS, &data);
   1481 }
   1482 
   1483 
   1484 static void nl80211_stop_ap(struct wpa_driver_nl80211_data *drv,
   1485 			    struct nlattr **tb)
   1486 {
   1487 	wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_UNAVAILABLE, NULL);
   1488 }
   1489 
   1490 
   1491 static void nl80211_connect_failed_event(struct wpa_driver_nl80211_data *drv,
   1492 					 struct nlattr **tb)
   1493 {
   1494 	union wpa_event_data data;
   1495 	u32 reason;
   1496 
   1497 	wpa_printf(MSG_DEBUG, "nl80211: Connect failed event");
   1498 
   1499 	if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_CONN_FAILED_REASON])
   1500 		return;
   1501 
   1502 	os_memset(&data, 0, sizeof(data));
   1503 	os_memcpy(data.connect_failed_reason.addr,
   1504 		  nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
   1505 
   1506 	reason = nla_get_u32(tb[NL80211_ATTR_CONN_FAILED_REASON]);
   1507 	switch (reason) {
   1508 	case NL80211_CONN_FAIL_MAX_CLIENTS:
   1509 		wpa_printf(MSG_DEBUG, "nl80211: Max client reached");
   1510 		data.connect_failed_reason.code = MAX_CLIENT_REACHED;
   1511 		break;
   1512 	case NL80211_CONN_FAIL_BLOCKED_CLIENT:
   1513 		wpa_printf(MSG_DEBUG, "nl80211: Blocked client " MACSTR
   1514 			   " tried to connect",
   1515 			   MAC2STR(data.connect_failed_reason.addr));
   1516 		data.connect_failed_reason.code = BLOCKED_CLIENT;
   1517 		break;
   1518 	default:
   1519 		wpa_printf(MSG_DEBUG, "nl8021l: Unknown connect failed reason "
   1520 			   "%u", reason);
   1521 		return;
   1522 	}
   1523 
   1524 	wpa_supplicant_event(drv->ctx, EVENT_CONNECT_FAILED_REASON, &data);
   1525 }
   1526 
   1527 
   1528 static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
   1529 				struct nlattr **tb)
   1530 {
   1531 	union wpa_event_data data;
   1532 	enum nl80211_radar_event event_type;
   1533 
   1534 	if (!tb[NL80211_ATTR_WIPHY_FREQ] || !tb[NL80211_ATTR_RADAR_EVENT])
   1535 		return;
   1536 
   1537 	os_memset(&data, 0, sizeof(data));
   1538 	data.dfs_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
   1539 	event_type = nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT]);
   1540 
   1541 	/* Check HT params */
   1542 	if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
   1543 		data.dfs_event.ht_enabled = 1;
   1544 		data.dfs_event.chan_offset = 0;
   1545 
   1546 		switch (nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])) {
   1547 		case NL80211_CHAN_NO_HT:
   1548 			data.dfs_event.ht_enabled = 0;
   1549 			break;
   1550 		case NL80211_CHAN_HT20:
   1551 			break;
   1552 		case NL80211_CHAN_HT40PLUS:
   1553 			data.dfs_event.chan_offset = 1;
   1554 			break;
   1555 		case NL80211_CHAN_HT40MINUS:
   1556 			data.dfs_event.chan_offset = -1;
   1557 			break;
   1558 		}
   1559 	}
   1560 
   1561 	/* Get VHT params */
   1562 	if (tb[NL80211_ATTR_CHANNEL_WIDTH])
   1563 		data.dfs_event.chan_width =
   1564 			convert2width(nla_get_u32(
   1565 					      tb[NL80211_ATTR_CHANNEL_WIDTH]));
   1566 	if (tb[NL80211_ATTR_CENTER_FREQ1])
   1567 		data.dfs_event.cf1 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
   1568 	if (tb[NL80211_ATTR_CENTER_FREQ2])
   1569 		data.dfs_event.cf2 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
   1570 
   1571 	wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz, ht: %d, offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz",
   1572 		   data.dfs_event.freq, data.dfs_event.ht_enabled,
   1573 		   data.dfs_event.chan_offset, data.dfs_event.chan_width,
   1574 		   data.dfs_event.cf1, data.dfs_event.cf2);
   1575 
   1576 	switch (event_type) {
   1577 	case NL80211_RADAR_DETECTED:
   1578 		wpa_supplicant_event(drv->ctx, EVENT_DFS_RADAR_DETECTED, &data);
   1579 		break;
   1580 	case NL80211_RADAR_CAC_FINISHED:
   1581 		wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_FINISHED, &data);
   1582 		break;
   1583 	case NL80211_RADAR_CAC_ABORTED:
   1584 		wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_ABORTED, &data);
   1585 		break;
   1586 	case NL80211_RADAR_NOP_FINISHED:
   1587 		wpa_supplicant_event(drv->ctx, EVENT_DFS_NOP_FINISHED, &data);
   1588 		break;
   1589 	case NL80211_RADAR_PRE_CAC_EXPIRED:
   1590 		wpa_supplicant_event(drv->ctx, EVENT_DFS_PRE_CAC_EXPIRED,
   1591 				     &data);
   1592 		break;
   1593 	default:
   1594 		wpa_printf(MSG_DEBUG, "nl80211: Unknown radar event %d "
   1595 			   "received", event_type);
   1596 		break;
   1597 	}
   1598 }
   1599 
   1600 
   1601 static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb,
   1602 				   int wds)
   1603 {
   1604 	struct wpa_driver_nl80211_data *drv = bss->drv;
   1605 	union wpa_event_data event;
   1606 
   1607 	if (!tb[NL80211_ATTR_MAC])
   1608 		return;
   1609 
   1610 	os_memset(&event, 0, sizeof(event));
   1611 	event.rx_from_unknown.bssid = bss->addr;
   1612 	event.rx_from_unknown.addr = nla_data(tb[NL80211_ATTR_MAC]);
   1613 	event.rx_from_unknown.wds = wds;
   1614 
   1615 	wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);
   1616 }
   1617 
   1618 
   1619 #ifdef CONFIG_DRIVER_NL80211_QCA
   1620 
   1621 static void qca_nl80211_avoid_freq(struct wpa_driver_nl80211_data *drv,
   1622 				   const u8 *data, size_t len)
   1623 {
   1624 	u32 i, count;
   1625 	union wpa_event_data event;
   1626 	struct wpa_freq_range *range = NULL;
   1627 	const struct qca_avoid_freq_list *freq_range;
   1628 
   1629 	freq_range = (const struct qca_avoid_freq_list *) data;
   1630 	if (len < sizeof(freq_range->count))
   1631 		return;
   1632 
   1633 	count = freq_range->count;
   1634 	if (len < sizeof(freq_range->count) +
   1635 	    count * sizeof(struct qca_avoid_freq_range)) {
   1636 		wpa_printf(MSG_DEBUG, "nl80211: Ignored too short avoid frequency list (len=%u)",
   1637 			   (unsigned int) len);
   1638 		return;
   1639 	}
   1640 
   1641 	if (count > 0) {
   1642 		range = os_calloc(count, sizeof(struct wpa_freq_range));
   1643 		if (range == NULL)
   1644 			return;
   1645 	}
   1646 
   1647 	os_memset(&event, 0, sizeof(event));
   1648 	for (i = 0; i < count; i++) {
   1649 		unsigned int idx = event.freq_range.num;
   1650 		range[idx].min = freq_range->range[i].start_freq;
   1651 		range[idx].max = freq_range->range[i].end_freq;
   1652 		wpa_printf(MSG_DEBUG, "nl80211: Avoid frequency range: %u-%u",
   1653 			   range[idx].min, range[idx].max);
   1654 		if (range[idx].min > range[idx].max) {
   1655 			wpa_printf(MSG_DEBUG, "nl80211: Ignore invalid frequency range");
   1656 			continue;
   1657 		}
   1658 		event.freq_range.num++;
   1659 	}
   1660 	event.freq_range.range = range;
   1661 
   1662 	wpa_supplicant_event(drv->ctx, EVENT_AVOID_FREQUENCIES, &event);
   1663 
   1664 	os_free(range);
   1665 }
   1666 
   1667 
   1668 static enum hostapd_hw_mode get_qca_hw_mode(u8 hw_mode)
   1669 {
   1670 	switch (hw_mode) {
   1671 	case QCA_ACS_MODE_IEEE80211B:
   1672 		return HOSTAPD_MODE_IEEE80211B;
   1673 	case QCA_ACS_MODE_IEEE80211G:
   1674 		return HOSTAPD_MODE_IEEE80211G;
   1675 	case QCA_ACS_MODE_IEEE80211A:
   1676 		return HOSTAPD_MODE_IEEE80211A;
   1677 	case QCA_ACS_MODE_IEEE80211AD:
   1678 		return HOSTAPD_MODE_IEEE80211AD;
   1679 	case QCA_ACS_MODE_IEEE80211ANY:
   1680 		return HOSTAPD_MODE_IEEE80211ANY;
   1681 	default:
   1682 		return NUM_HOSTAPD_MODES;
   1683 	}
   1684 }
   1685 
   1686 
   1687 static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv,
   1688 				   const u8 *data, size_t len)
   1689 {
   1690 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
   1691 	union wpa_event_data event;
   1692 
   1693 	wpa_printf(MSG_DEBUG,
   1694 		   "nl80211: ACS channel selection vendor event received");
   1695 
   1696 	if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX,
   1697 		      (struct nlattr *) data, len, NULL) ||
   1698 	    !tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL] ||
   1699 	    !tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL])
   1700 		return;
   1701 
   1702 	os_memset(&event, 0, sizeof(event));
   1703 	event.acs_selected_channels.pri_channel =
   1704 		nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]);
   1705 	event.acs_selected_channels.sec_channel =
   1706 		nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]);
   1707 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL])
   1708 		event.acs_selected_channels.vht_seg0_center_ch =
   1709 			nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]);
   1710 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL])
   1711 		event.acs_selected_channels.vht_seg1_center_ch =
   1712 			nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL]);
   1713 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH])
   1714 		event.acs_selected_channels.ch_width =
   1715 			nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
   1716 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
   1717 		u8 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
   1718 
   1719 		event.acs_selected_channels.hw_mode = get_qca_hw_mode(hw_mode);
   1720 		if (event.acs_selected_channels.hw_mode == NUM_HOSTAPD_MODES ||
   1721 		    event.acs_selected_channels.hw_mode ==
   1722 		    HOSTAPD_MODE_IEEE80211ANY) {
   1723 			wpa_printf(MSG_DEBUG,
   1724 				   "nl80211: Invalid hw_mode %d in ACS selection event",
   1725 				   hw_mode);
   1726 			return;
   1727 		}
   1728 	}
   1729 
   1730 	wpa_printf(MSG_INFO,
   1731 		   "nl80211: ACS Results: PCH: %d SCH: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d",
   1732 		   event.acs_selected_channels.pri_channel,
   1733 		   event.acs_selected_channels.sec_channel,
   1734 		   event.acs_selected_channels.ch_width,
   1735 		   event.acs_selected_channels.vht_seg0_center_ch,
   1736 		   event.acs_selected_channels.vht_seg1_center_ch,
   1737 		   event.acs_selected_channels.hw_mode);
   1738 
   1739 	/* Ignore ACS channel list check for backwards compatibility */
   1740 
   1741 	wpa_supplicant_event(drv->ctx, EVENT_ACS_CHANNEL_SELECTED, &event);
   1742 }
   1743 
   1744 
   1745 static void qca_nl80211_key_mgmt_auth(struct wpa_driver_nl80211_data *drv,
   1746 				      const u8 *data, size_t len)
   1747 {
   1748 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX + 1];
   1749 	u8 *bssid;
   1750 
   1751 	wpa_printf(MSG_DEBUG,
   1752 		   "nl80211: Key management roam+auth vendor event received");
   1753 
   1754 	if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX,
   1755 		      (struct nlattr *) data, len, NULL) ||
   1756 	    !tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID] ||
   1757 	    nla_len(tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID]) != ETH_ALEN ||
   1758 	    !tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE] ||
   1759 	    !tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE] ||
   1760 	    !tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED])
   1761 		return;
   1762 
   1763 	bssid = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID]);
   1764 	wpa_printf(MSG_DEBUG, "  * roam BSSID " MACSTR, MAC2STR(bssid));
   1765 
   1766 	mlme_event_connect(drv, NL80211_CMD_ROAM, NULL,
   1767 			   tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID],
   1768 			   tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE],
   1769 			   tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE],
   1770 			   NULL, NULL,
   1771 			   tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED],
   1772 			   tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR],
   1773 			   tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK],
   1774 			   tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK],
   1775 			   tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS],
   1776 			   tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM],
   1777 			   tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK],
   1778 			   tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID]);
   1779 }
   1780 
   1781 
   1782 static void qca_nl80211_dfs_offload_radar_event(
   1783 	struct wpa_driver_nl80211_data *drv, u32 subcmd, u8 *msg, int length)
   1784 {
   1785 	union wpa_event_data data;
   1786 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
   1787 
   1788 	wpa_printf(MSG_DEBUG,
   1789 		   "nl80211: DFS offload radar vendor event received");
   1790 
   1791 	if (nla_parse(tb, NL80211_ATTR_MAX,
   1792 		      (struct nlattr *) msg, length, NULL))
   1793 		return;
   1794 
   1795 	if (!tb[NL80211_ATTR_WIPHY_FREQ]) {
   1796 		wpa_printf(MSG_INFO,
   1797 			   "nl80211: Error parsing WIPHY_FREQ in FS offload radar vendor event");
   1798 		return;
   1799 	}
   1800 
   1801 	os_memset(&data, 0, sizeof(data));
   1802 	data.dfs_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
   1803 
   1804 	wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz",
   1805 		   data.dfs_event.freq);
   1806 
   1807 	/* Check HT params */
   1808 	if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
   1809 		data.dfs_event.ht_enabled = 1;
   1810 		data.dfs_event.chan_offset = 0;
   1811 
   1812 		switch (nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])) {
   1813 		case NL80211_CHAN_NO_HT:
   1814 			data.dfs_event.ht_enabled = 0;
   1815 			break;
   1816 		case NL80211_CHAN_HT20:
   1817 			break;
   1818 		case NL80211_CHAN_HT40PLUS:
   1819 			data.dfs_event.chan_offset = 1;
   1820 			break;
   1821 		case NL80211_CHAN_HT40MINUS:
   1822 			data.dfs_event.chan_offset = -1;
   1823 			break;
   1824 		}
   1825 	}
   1826 
   1827 	/* Get VHT params */
   1828 	if (tb[NL80211_ATTR_CHANNEL_WIDTH])
   1829 		data.dfs_event.chan_width =
   1830 			convert2width(nla_get_u32(
   1831 					      tb[NL80211_ATTR_CHANNEL_WIDTH]));
   1832 	if (tb[NL80211_ATTR_CENTER_FREQ1])
   1833 		data.dfs_event.cf1 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
   1834 	if (tb[NL80211_ATTR_CENTER_FREQ2])
   1835 		data.dfs_event.cf2 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
   1836 
   1837 	wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz, ht: %d, "
   1838 		    "offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz",
   1839 		    data.dfs_event.freq, data.dfs_event.ht_enabled,
   1840 		    data.dfs_event.chan_offset, data.dfs_event.chan_width,
   1841 		    data.dfs_event.cf1, data.dfs_event.cf2);
   1842 
   1843 	switch (subcmd) {
   1844 	case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED:
   1845 		wpa_supplicant_event(drv->ctx, EVENT_DFS_RADAR_DETECTED, &data);
   1846 		break;
   1847 	case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED:
   1848 		wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_STARTED, &data);
   1849 		break;
   1850 	case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED:
   1851 		wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_FINISHED, &data);
   1852 		break;
   1853 	case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED:
   1854 		wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_ABORTED, &data);
   1855 		break;
   1856 	case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED:
   1857 		wpa_supplicant_event(drv->ctx, EVENT_DFS_NOP_FINISHED, &data);
   1858 		break;
   1859 	default:
   1860 		wpa_printf(MSG_DEBUG,
   1861 			   "nl80211: Unknown DFS offload radar event %d received",
   1862 			   subcmd);
   1863 		break;
   1864 	}
   1865 }
   1866 
   1867 
   1868 static void qca_nl80211_scan_trigger_event(struct wpa_driver_nl80211_data *drv,
   1869 					   u8 *data, size_t len)
   1870 {
   1871 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1];
   1872 	u64 cookie = 0;
   1873 	union wpa_event_data event;
   1874 	struct scan_info *info;
   1875 
   1876 	if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SCAN_MAX,
   1877 		      (struct nlattr *) data, len, NULL) ||
   1878 	    !tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE])
   1879 		return;
   1880 
   1881 	cookie = nla_get_u64(tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]);
   1882 	if (cookie != drv->vendor_scan_cookie) {
   1883 		/* External scan trigger event, ignore */
   1884 		return;
   1885 	}
   1886 
   1887 	/* Cookie match, own scan */
   1888 	os_memset(&event, 0, sizeof(event));
   1889 	info = &event.scan_info;
   1890 	info->external_scan = 0;
   1891 	info->nl_scan_event = 0;
   1892 
   1893 	drv->scan_state = SCAN_STARTED;
   1894 	wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, &event);
   1895 }
   1896 
   1897 
   1898 static void send_vendor_scan_event(struct wpa_driver_nl80211_data *drv,
   1899 				   int aborted, struct nlattr *tb[],
   1900 				   int external_scan)
   1901 {
   1902 	union wpa_event_data event;
   1903 	struct nlattr *nl;
   1904 	int rem;
   1905 	struct scan_info *info;
   1906 	int freqs[MAX_REPORT_FREQS];
   1907 	int num_freqs = 0;
   1908 
   1909 	os_memset(&event, 0, sizeof(event));
   1910 	info = &event.scan_info;
   1911 	info->aborted = aborted;
   1912 	info->external_scan = external_scan;
   1913 
   1914 	if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS]) {
   1915 		nla_for_each_nested(nl,
   1916 				    tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS], rem) {
   1917 			struct wpa_driver_scan_ssid *s =
   1918 				&info->ssids[info->num_ssids];
   1919 			s->ssid = nla_data(nl);
   1920 			s->ssid_len = nla_len(nl);
   1921 			wpa_printf(MSG_DEBUG,
   1922 				   "nl80211: Scan probed for SSID '%s'",
   1923 				   wpa_ssid_txt(s->ssid, s->ssid_len));
   1924 			info->num_ssids++;
   1925 			if (info->num_ssids == WPAS_MAX_SCAN_SSIDS)
   1926 				break;
   1927 		}
   1928 	}
   1929 
   1930 	if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES]) {
   1931 		char msg[300], *pos, *end;
   1932 		int res;
   1933 
   1934 		pos = msg;
   1935 		end = pos + sizeof(msg);
   1936 		*pos = '\0';
   1937 
   1938 		nla_for_each_nested(nl,
   1939 				    tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES],
   1940 				    rem) {
   1941 			freqs[num_freqs] = nla_get_u32(nl);
   1942 			res = os_snprintf(pos, end - pos, " %d",
   1943 					  freqs[num_freqs]);
   1944 			if (!os_snprintf_error(end - pos, res))
   1945 				pos += res;
   1946 			num_freqs++;
   1947 			if (num_freqs == MAX_REPORT_FREQS - 1)
   1948 				break;
   1949 		}
   1950 
   1951 		info->freqs = freqs;
   1952 		info->num_freqs = num_freqs;
   1953 		wpa_printf(MSG_DEBUG, "nl80211: Scan included frequencies:%s",
   1954 			   msg);
   1955 	}
   1956 	wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
   1957 }
   1958 
   1959 
   1960 static void qca_nl80211_scan_done_event(struct wpa_driver_nl80211_data *drv,
   1961 					u8 *data, size_t len)
   1962 {
   1963 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1];
   1964 	u64 cookie = 0;
   1965 	enum scan_status status;
   1966 	int external_scan;
   1967 
   1968 	if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SCAN_MAX,
   1969 		      (struct nlattr *) data, len, NULL) ||
   1970 	    !tb[QCA_WLAN_VENDOR_ATTR_SCAN_STATUS] ||
   1971 	    !tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE])
   1972 		return;
   1973 
   1974 	status = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SCAN_STATUS]);
   1975 	if (status >= VENDOR_SCAN_STATUS_MAX)
   1976 		return; /* invalid status */
   1977 
   1978 	cookie = nla_get_u64(tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]);
   1979 	if (cookie != drv->vendor_scan_cookie) {
   1980 		/* Event from an external scan, get scan results */
   1981 		external_scan = 1;
   1982 	} else {
   1983 		external_scan = 0;
   1984 		if (status == VENDOR_SCAN_STATUS_NEW_RESULTS)
   1985 			drv->scan_state = SCAN_COMPLETED;
   1986 		else
   1987 			drv->scan_state = SCAN_ABORTED;
   1988 
   1989 		eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
   1990 				     drv->ctx);
   1991 		drv->vendor_scan_cookie = 0;
   1992 		drv->last_scan_cmd = 0;
   1993 	}
   1994 
   1995 	send_vendor_scan_event(drv, (status == VENDOR_SCAN_STATUS_ABORTED), tb,
   1996 			       external_scan);
   1997 }
   1998 
   1999 
   2000 static void qca_nl80211_p2p_lo_stop_event(struct wpa_driver_nl80211_data *drv,
   2001 					  u8 *data, size_t len)
   2002 {
   2003 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
   2004 	union wpa_event_data event;
   2005 
   2006 	wpa_printf(MSG_DEBUG,
   2007 		   "nl80211: P2P listen offload stop vendor event received");
   2008 
   2009 	if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
   2010 		      (struct nlattr *) data, len, NULL) ||
   2011 	    !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON])
   2012 		return;
   2013 
   2014 	os_memset(&event, 0, sizeof(event));
   2015 	event.p2p_lo_stop.reason_code =
   2016 		nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON]);
   2017 
   2018 	wpa_printf(MSG_DEBUG,
   2019 		   "nl80211: P2P Listen offload stop reason: %d",
   2020 		   event.p2p_lo_stop.reason_code);
   2021 	wpa_supplicant_event(drv->ctx, EVENT_P2P_LO_STOP, &event);
   2022 }
   2023 
   2024 #endif /* CONFIG_DRIVER_NL80211_QCA */
   2025 
   2026 
   2027 static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data *drv,
   2028 				     u32 subcmd, u8 *data, size_t len)
   2029 {
   2030 	switch (subcmd) {
   2031 	case QCA_NL80211_VENDOR_SUBCMD_TEST:
   2032 		wpa_hexdump(MSG_DEBUG, "nl80211: QCA test event", data, len);
   2033 		break;
   2034 #ifdef CONFIG_DRIVER_NL80211_QCA
   2035 	case QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY:
   2036 		qca_nl80211_avoid_freq(drv, data, len);
   2037 		break;
   2038 	case QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH:
   2039 		qca_nl80211_key_mgmt_auth(drv, data, len);
   2040 		break;
   2041 	case QCA_NL80211_VENDOR_SUBCMD_DO_ACS:
   2042 		qca_nl80211_acs_select_ch(drv, data, len);
   2043 		break;
   2044 	case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED:
   2045 	case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED:
   2046 	case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED:
   2047 	case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED:
   2048 	case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED:
   2049 		qca_nl80211_dfs_offload_radar_event(drv, subcmd, data, len);
   2050 		break;
   2051 	case QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN:
   2052 		qca_nl80211_scan_trigger_event(drv, data, len);
   2053 		break;
   2054 	case QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE:
   2055 		qca_nl80211_scan_done_event(drv, data, len);
   2056 		break;
   2057 	case QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP:
   2058 		qca_nl80211_p2p_lo_stop_event(drv, data, len);
   2059 		break;
   2060 #endif /* CONFIG_DRIVER_NL80211_QCA */
   2061 	default:
   2062 		wpa_printf(MSG_DEBUG,
   2063 			   "nl80211: Ignore unsupported QCA vendor event %u",
   2064 			   subcmd);
   2065 		break;
   2066 	}
   2067 }
   2068 
   2069 
   2070 static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
   2071 				 struct nlattr **tb)
   2072 {
   2073 	u32 vendor_id, subcmd, wiphy = 0;
   2074 	int wiphy_idx;
   2075 	u8 *data = NULL;
   2076 	size_t len = 0;
   2077 
   2078 	if (!tb[NL80211_ATTR_VENDOR_ID] ||
   2079 	    !tb[NL80211_ATTR_VENDOR_SUBCMD])
   2080 		return;
   2081 
   2082 	vendor_id = nla_get_u32(tb[NL80211_ATTR_VENDOR_ID]);
   2083 	subcmd = nla_get_u32(tb[NL80211_ATTR_VENDOR_SUBCMD]);
   2084 
   2085 	if (tb[NL80211_ATTR_WIPHY])
   2086 		wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
   2087 
   2088 	wpa_printf(MSG_DEBUG, "nl80211: Vendor event: wiphy=%u vendor_id=0x%x subcmd=%u",
   2089 		   wiphy, vendor_id, subcmd);
   2090 
   2091 	if (tb[NL80211_ATTR_VENDOR_DATA]) {
   2092 		data = nla_data(tb[NL80211_ATTR_VENDOR_DATA]);
   2093 		len = nla_len(tb[NL80211_ATTR_VENDOR_DATA]);
   2094 		wpa_hexdump(MSG_MSGDUMP, "nl80211: Vendor data", data, len);
   2095 	}
   2096 
   2097 	wiphy_idx = nl80211_get_wiphy_index(drv->first_bss);
   2098 	if (wiphy_idx >= 0 && wiphy_idx != (int) wiphy) {
   2099 		wpa_printf(MSG_DEBUG, "nl80211: Ignore vendor event for foreign wiphy %u (own: %d)",
   2100 			   wiphy, wiphy_idx);
   2101 		return;
   2102 	}
   2103 
   2104 	switch (vendor_id) {
   2105 	case OUI_QCA:
   2106 		nl80211_vendor_event_qca(drv, subcmd, data, len);
   2107 		break;
   2108 	default:
   2109 		wpa_printf(MSG_DEBUG, "nl80211: Ignore unsupported vendor event");
   2110 		break;
   2111 	}
   2112 }
   2113 
   2114 
   2115 static void nl80211_reg_change_event(struct wpa_driver_nl80211_data *drv,
   2116 				     struct nlattr *tb[])
   2117 {
   2118 	union wpa_event_data data;
   2119 	enum nl80211_reg_initiator init;
   2120 
   2121 	wpa_printf(MSG_DEBUG, "nl80211: Regulatory domain change");
   2122 
   2123 	if (tb[NL80211_ATTR_REG_INITIATOR] == NULL)
   2124 		return;
   2125 
   2126 	os_memset(&data, 0, sizeof(data));
   2127 	init = nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR]);
   2128 	wpa_printf(MSG_DEBUG, " * initiator=%d", init);
   2129 	switch (init) {
   2130 	case NL80211_REGDOM_SET_BY_CORE:
   2131 		data.channel_list_changed.initiator = REGDOM_SET_BY_CORE;
   2132 		break;
   2133 	case NL80211_REGDOM_SET_BY_USER:
   2134 		data.channel_list_changed.initiator = REGDOM_SET_BY_USER;
   2135 		break;
   2136 	case NL80211_REGDOM_SET_BY_DRIVER:
   2137 		data.channel_list_changed.initiator = REGDOM_SET_BY_DRIVER;
   2138 		break;
   2139 	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
   2140 		data.channel_list_changed.initiator = REGDOM_SET_BY_COUNTRY_IE;
   2141 		break;
   2142 	}
   2143 
   2144 	if (tb[NL80211_ATTR_REG_TYPE]) {
   2145 		enum nl80211_reg_type type;
   2146 		type = nla_get_u8(tb[NL80211_ATTR_REG_TYPE]);
   2147 		wpa_printf(MSG_DEBUG, " * type=%d", type);
   2148 		switch (type) {
   2149 		case NL80211_REGDOM_TYPE_COUNTRY:
   2150 			data.channel_list_changed.type = REGDOM_TYPE_COUNTRY;
   2151 			break;
   2152 		case NL80211_REGDOM_TYPE_WORLD:
   2153 			data.channel_list_changed.type = REGDOM_TYPE_WORLD;
   2154 			break;
   2155 		case NL80211_REGDOM_TYPE_CUSTOM_WORLD:
   2156 			data.channel_list_changed.type =
   2157 				REGDOM_TYPE_CUSTOM_WORLD;
   2158 			break;
   2159 		case NL80211_REGDOM_TYPE_INTERSECTION:
   2160 			data.channel_list_changed.type =
   2161 				REGDOM_TYPE_INTERSECTION;
   2162 			break;
   2163 		}
   2164 	}
   2165 
   2166 	if (tb[NL80211_ATTR_REG_ALPHA2]) {
   2167 		os_strlcpy(data.channel_list_changed.alpha2,
   2168 			   nla_get_string(tb[NL80211_ATTR_REG_ALPHA2]),
   2169 			   sizeof(data.channel_list_changed.alpha2));
   2170 		wpa_printf(MSG_DEBUG, " * alpha2=%s",
   2171 			   data.channel_list_changed.alpha2);
   2172 	}
   2173 
   2174 	wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED, &data);
   2175 }
   2176 
   2177 
   2178 static void do_process_drv_event(struct i802_bss *bss, int cmd,
   2179 				 struct nlattr **tb)
   2180 {
   2181 	struct wpa_driver_nl80211_data *drv = bss->drv;
   2182 	union wpa_event_data data;
   2183 	int external_scan_event = 0;
   2184 
   2185 	wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s",
   2186 		   cmd, nl80211_command_to_string(cmd), bss->ifname);
   2187 
   2188 	if (cmd == NL80211_CMD_ROAM &&
   2189 	    (drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) {
   2190 		/*
   2191 		 * Device will use roam+auth vendor event to indicate
   2192 		 * roaming, so ignore the regular roam event.
   2193 		 */
   2194 		wpa_printf(MSG_DEBUG,
   2195 			   "nl80211: Ignore roam event (cmd=%d), device will use vendor event roam+auth",
   2196 			   cmd);
   2197 		return;
   2198 	}
   2199 
   2200 	if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&
   2201 	    (cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
   2202 	     cmd == NL80211_CMD_SCAN_ABORTED)) {
   2203 		wpa_driver_nl80211_set_mode(drv->first_bss,
   2204 					    drv->ap_scan_as_station);
   2205 		drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
   2206 	}
   2207 
   2208 	switch (cmd) {
   2209 	case NL80211_CMD_TRIGGER_SCAN:
   2210 		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger");
   2211 		drv->scan_state = SCAN_STARTED;
   2212 		if (drv->scan_for_auth) {
   2213 			/*
   2214 			 * Cannot indicate EVENT_SCAN_STARTED here since we skip
   2215 			 * EVENT_SCAN_RESULTS in scan_for_auth case and the
   2216 			 * upper layer implementation could get confused about
   2217 			 * scanning state.
   2218 			 */
   2219 			wpa_printf(MSG_DEBUG, "nl80211: Do not indicate scan-start event due to internal scan_for_auth");
   2220 			break;
   2221 		}
   2222 		wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
   2223 		break;
   2224 	case NL80211_CMD_START_SCHED_SCAN:
   2225 		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started");
   2226 		drv->scan_state = SCHED_SCAN_STARTED;
   2227 		break;
   2228 	case NL80211_CMD_SCHED_SCAN_STOPPED:
   2229 		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
   2230 		drv->scan_state = SCHED_SCAN_STOPPED;
   2231 		wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
   2232 		break;
   2233 	case NL80211_CMD_NEW_SCAN_RESULTS:
   2234 		wpa_dbg(drv->ctx, MSG_DEBUG,
   2235 			"nl80211: New scan results available");
   2236 		if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
   2237 			drv->scan_state = SCAN_COMPLETED;
   2238 		drv->scan_complete_events = 1;
   2239 		if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
   2240 			eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
   2241 					     drv, drv->ctx);
   2242 			drv->last_scan_cmd = 0;
   2243 		} else {
   2244 			external_scan_event = 1;
   2245 		}
   2246 		send_scan_event(drv, 0, tb, external_scan_event);
   2247 		break;
   2248 	case NL80211_CMD_SCHED_SCAN_RESULTS:
   2249 		wpa_dbg(drv->ctx, MSG_DEBUG,
   2250 			"nl80211: New sched scan results available");
   2251 		drv->scan_state = SCHED_SCAN_RESULTS;
   2252 		send_scan_event(drv, 0, tb, 0);
   2253 		break;
   2254 	case NL80211_CMD_SCAN_ABORTED:
   2255 		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
   2256 		if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
   2257 			drv->scan_state = SCAN_ABORTED;
   2258 		if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
   2259 			/*
   2260 			 * Need to indicate that scan results are available in
   2261 			 * order not to make wpa_supplicant stop its scanning.
   2262 			 */
   2263 			eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
   2264 					     drv, drv->ctx);
   2265 			drv->last_scan_cmd = 0;
   2266 		} else {
   2267 			external_scan_event = 1;
   2268 		}
   2269 		send_scan_event(drv, 1, tb, external_scan_event);
   2270 		break;
   2271 	case NL80211_CMD_AUTHENTICATE:
   2272 	case NL80211_CMD_ASSOCIATE:
   2273 	case NL80211_CMD_DEAUTHENTICATE:
   2274 	case NL80211_CMD_DISASSOCIATE:
   2275 	case NL80211_CMD_FRAME_TX_STATUS:
   2276 	case NL80211_CMD_UNPROT_DEAUTHENTICATE:
   2277 	case NL80211_CMD_UNPROT_DISASSOCIATE:
   2278 		mlme_event(bss, cmd, tb[NL80211_ATTR_FRAME],
   2279 			   tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
   2280 			   tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
   2281 			   tb[NL80211_ATTR_COOKIE],
   2282 			   tb[NL80211_ATTR_RX_SIGNAL_DBM],
   2283 			   tb[NL80211_ATTR_STA_WME]);
   2284 		break;
   2285 	case NL80211_CMD_CONNECT:
   2286 	case NL80211_CMD_ROAM:
   2287 		mlme_event_connect(drv, cmd,
   2288 				   tb[NL80211_ATTR_STATUS_CODE],
   2289 				   tb[NL80211_ATTR_MAC],
   2290 				   tb[NL80211_ATTR_REQ_IE],
   2291 				   tb[NL80211_ATTR_RESP_IE],
   2292 				   tb[NL80211_ATTR_TIMED_OUT],
   2293 				   tb[NL80211_ATTR_TIMEOUT_REASON],
   2294 				   NULL, NULL, NULL,
   2295 				   tb[NL80211_ATTR_FILS_KEK],
   2296 				   NULL,
   2297 				   tb[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM],
   2298 				   tb[NL80211_ATTR_PMK],
   2299 				   tb[NL80211_ATTR_PMKID]);
   2300 		break;
   2301 	case NL80211_CMD_CH_SWITCH_NOTIFY:
   2302 		mlme_event_ch_switch(drv,
   2303 				     tb[NL80211_ATTR_IFINDEX],
   2304 				     tb[NL80211_ATTR_WIPHY_FREQ],
   2305 				     tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
   2306 				     tb[NL80211_ATTR_CHANNEL_WIDTH],
   2307 				     tb[NL80211_ATTR_CENTER_FREQ1],
   2308 				     tb[NL80211_ATTR_CENTER_FREQ2]);
   2309 		break;
   2310 	case NL80211_CMD_DISCONNECT:
   2311 		mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],
   2312 				      tb[NL80211_ATTR_MAC],
   2313 				      tb[NL80211_ATTR_DISCONNECTED_BY_AP]);
   2314 		break;
   2315 	case NL80211_CMD_MICHAEL_MIC_FAILURE:
   2316 		mlme_event_michael_mic_failure(bss, tb);
   2317 		break;
   2318 	case NL80211_CMD_JOIN_IBSS:
   2319 		mlme_event_join_ibss(drv, tb);
   2320 		break;
   2321 	case NL80211_CMD_REMAIN_ON_CHANNEL:
   2322 		mlme_event_remain_on_channel(drv, 0, tb);
   2323 		break;
   2324 	case NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL:
   2325 		mlme_event_remain_on_channel(drv, 1, tb);
   2326 		break;
   2327 	case NL80211_CMD_NOTIFY_CQM:
   2328 		nl80211_cqm_event(drv, tb);
   2329 		break;
   2330 	case NL80211_CMD_REG_CHANGE:
   2331 		nl80211_reg_change_event(drv, tb);
   2332 		break;
   2333 	case NL80211_CMD_REG_BEACON_HINT:
   2334 		wpa_printf(MSG_DEBUG, "nl80211: Regulatory beacon hint");
   2335 		os_memset(&data, 0, sizeof(data));
   2336 		data.channel_list_changed.initiator = REGDOM_BEACON_HINT;
   2337 		wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,
   2338 				     &data);
   2339 		break;
   2340 	case NL80211_CMD_NEW_STATION:
   2341 		nl80211_new_station_event(drv, bss, tb);
   2342 		break;
   2343 	case NL80211_CMD_DEL_STATION:
   2344 		nl80211_del_station_event(drv, bss, tb);
   2345 		break;
   2346 	case NL80211_CMD_SET_REKEY_OFFLOAD:
   2347 		nl80211_rekey_offload_event(drv, tb);
   2348 		break;
   2349 	case NL80211_CMD_PMKSA_CANDIDATE:
   2350 		nl80211_pmksa_candidate_event(drv, tb);
   2351 		break;
   2352 	case NL80211_CMD_PROBE_CLIENT:
   2353 		nl80211_client_probe_event(drv, tb);
   2354 		break;
   2355 	case NL80211_CMD_TDLS_OPER:
   2356 		nl80211_tdls_oper_event(drv, tb);
   2357 		break;
   2358 	case NL80211_CMD_CONN_FAILED:
   2359 		nl80211_connect_failed_event(drv, tb);
   2360 		break;
   2361 	case NL80211_CMD_FT_EVENT:
   2362 		mlme_event_ft_event(drv, tb);
   2363 		break;
   2364 	case NL80211_CMD_RADAR_DETECT:
   2365 		nl80211_radar_event(drv, tb);
   2366 		break;
   2367 	case NL80211_CMD_STOP_AP:
   2368 		nl80211_stop_ap(drv, tb);
   2369 		break;
   2370 	case NL80211_CMD_VENDOR:
   2371 		nl80211_vendor_event(drv, tb);
   2372 		break;
   2373 	case NL80211_CMD_NEW_PEER_CANDIDATE:
   2374 		nl80211_new_peer_candidate(drv, tb);
   2375 		break;
   2376 	default:
   2377 		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
   2378 			"(cmd=%d)", cmd);
   2379 		break;
   2380 	}
   2381 }
   2382 
   2383 
   2384 int process_global_event(struct nl_msg *msg, void *arg)
   2385 {
   2386 	struct nl80211_global *global = arg;
   2387 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
   2388 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
   2389 	struct wpa_driver_nl80211_data *drv, *tmp;
   2390 	int ifidx = -1;
   2391 	struct i802_bss *bss;
   2392 	u64 wdev_id = 0;
   2393 	int wdev_id_set = 0;
   2394 
   2395 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
   2396 		  genlmsg_attrlen(gnlh, 0), NULL);
   2397 
   2398 	if (tb[NL80211_ATTR_IFINDEX])
   2399 		ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
   2400 	else if (tb[NL80211_ATTR_WDEV]) {
   2401 		wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
   2402 		wdev_id_set = 1;
   2403 	}
   2404 
   2405 	dl_list_for_each_safe(drv, tmp, &global->interfaces,
   2406 			      struct wpa_driver_nl80211_data, list) {
   2407 		for (bss = drv->first_bss; bss; bss = bss->next) {
   2408 			if ((ifidx == -1 && !wdev_id_set) ||
   2409 			    ifidx == bss->ifindex ||
   2410 			    (wdev_id_set && bss->wdev_id_set &&
   2411 			     wdev_id == bss->wdev_id)) {
   2412 				do_process_drv_event(bss, gnlh->cmd, tb);
   2413 				return NL_SKIP;
   2414 			}
   2415 		}
   2416 		wpa_printf(MSG_DEBUG,
   2417 			   "nl80211: Ignored event (cmd=%d) for foreign interface (ifindex %d wdev 0x%llx)",
   2418 			   gnlh->cmd, ifidx, (long long unsigned int) wdev_id);
   2419 	}
   2420 
   2421 	return NL_SKIP;
   2422 }
   2423 
   2424 
   2425 int process_bss_event(struct nl_msg *msg, void *arg)
   2426 {
   2427 	struct i802_bss *bss = arg;
   2428 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
   2429 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
   2430 
   2431 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
   2432 		  genlmsg_attrlen(gnlh, 0), NULL);
   2433 
   2434 	wpa_printf(MSG_DEBUG, "nl80211: BSS Event %d (%s) received for %s",
   2435 		   gnlh->cmd, nl80211_command_to_string(gnlh->cmd),
   2436 		   bss->ifname);
   2437 
   2438 	switch (gnlh->cmd) {
   2439 	case NL80211_CMD_FRAME:
   2440 	case NL80211_CMD_FRAME_TX_STATUS:
   2441 		mlme_event(bss, gnlh->cmd, tb[NL80211_ATTR_FRAME],
   2442 			   tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
   2443 			   tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
   2444 			   tb[NL80211_ATTR_COOKIE],
   2445 			   tb[NL80211_ATTR_RX_SIGNAL_DBM],
   2446 			   tb[NL80211_ATTR_STA_WME]);
   2447 		break;
   2448 	case NL80211_CMD_UNEXPECTED_FRAME:
   2449 		nl80211_spurious_frame(bss, tb, 0);
   2450 		break;
   2451 	case NL80211_CMD_UNEXPECTED_4ADDR_FRAME:
   2452 		nl80211_spurious_frame(bss, tb, 1);
   2453 		break;
   2454 	default:
   2455 		wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
   2456 			   "(cmd=%d)", gnlh->cmd);
   2457 		break;
   2458 	}
   2459 
   2460 	return NL_SKIP;
   2461 }
   2462