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