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
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
12 #include <netlink/genl/genl.h>
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"
23 static const char * nl80211_command_to_string(enum nl80211_commands cmd
)
25 #define C2S(x) case x: return #x;
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
)
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
)
140 return "NL80211_CMD_UNKNOWN";
146 static void mlme_event_auth(struct wpa_driver_nl80211_data
*drv
,
147 const u8
*frame
, size_t len
)
149 const struct ieee80211_mgmt
*mgmt
;
150 union wpa_event_data event
;
152 if (!(drv
->capa
.flags
& WPA_DRIVER_FLAGS_SME
) &&
153 drv
->force_connect_cmd
) {
155 * Avoid reporting two association events that would confuse
158 wpa_printf(MSG_DEBUG
,
159 "nl80211: Ignore auth event when using driver SME");
163 wpa_printf(MSG_DEBUG
, "nl80211: Authenticate event");
164 mgmt
= (const struct ieee80211_mgmt
*) frame
;
165 if (len
< 24 + sizeof(mgmt
->u
.auth
)) {
166 wpa_printf(MSG_DEBUG
, "nl80211: Too short association event "
171 os_memcpy(drv
->auth_bssid
, mgmt
->sa
, ETH_ALEN
);
172 os_memset(drv
->auth_attempt_bssid
, 0, ETH_ALEN
);
173 os_memset(&event
, 0, sizeof(event
));
174 os_memcpy(event
.auth
.peer
, mgmt
->sa
, ETH_ALEN
);
175 event
.auth
.auth_type
= le_to_host16(mgmt
->u
.auth
.auth_alg
);
176 event
.auth
.auth_transaction
=
177 le_to_host16(mgmt
->u
.auth
.auth_transaction
);
178 event
.auth
.status_code
= le_to_host16(mgmt
->u
.auth
.status_code
);
179 if (len
> 24 + sizeof(mgmt
->u
.auth
)) {
180 event
.auth
.ies
= mgmt
->u
.auth
.variable
;
181 event
.auth
.ies_len
= len
- 24 - sizeof(mgmt
->u
.auth
);
184 wpa_supplicant_event(drv
->ctx
, EVENT_AUTH
, &event
);
188 static void nl80211_parse_wmm_params(struct nlattr
*wmm_attr
,
189 struct wmm_params
*wmm_params
)
191 struct nlattr
*wmm_info
[NL80211_STA_WME_MAX
+ 1];
192 static struct nla_policy wme_policy
[NL80211_STA_WME_MAX
+ 1] = {
193 [NL80211_STA_WME_UAPSD_QUEUES
] = { .type
= NLA_U8
},
197 nla_parse_nested(wmm_info
, NL80211_STA_WME_MAX
, wmm_attr
,
199 !wmm_info
[NL80211_STA_WME_UAPSD_QUEUES
])
202 wmm_params
->uapsd_queues
=
203 nla_get_u8(wmm_info
[NL80211_STA_WME_UAPSD_QUEUES
]);
204 wmm_params
->info_bitmap
|= WMM_PARAMS_UAPSD_QUEUES_INFO
;
208 static void mlme_event_assoc(struct wpa_driver_nl80211_data
*drv
,
209 const u8
*frame
, size_t len
, struct nlattr
*wmm
,
210 struct nlattr
*req_ie
)
212 const struct ieee80211_mgmt
*mgmt
;
213 union wpa_event_data event
;
217 if (!(drv
->capa
.flags
& WPA_DRIVER_FLAGS_SME
) &&
218 drv
->force_connect_cmd
) {
220 * Avoid reporting two association events that would confuse
223 wpa_printf(MSG_DEBUG
,
224 "nl80211: Ignore assoc event when using driver SME");
228 wpa_printf(MSG_DEBUG
, "nl80211: Associate event");
229 mgmt
= (const struct ieee80211_mgmt
*) frame
;
230 if (len
< 24 + sizeof(mgmt
->u
.assoc_resp
)) {
231 wpa_printf(MSG_DEBUG
, "nl80211: Too short association event "
236 status
= le_to_host16(mgmt
->u
.assoc_resp
.status_code
);
237 if (status
!= WLAN_STATUS_SUCCESS
) {
238 os_memset(&event
, 0, sizeof(event
));
239 event
.assoc_reject
.bssid
= mgmt
->bssid
;
240 if (len
> 24 + sizeof(mgmt
->u
.assoc_resp
)) {
241 event
.assoc_reject
.resp_ies
=
242 (u8
*) mgmt
->u
.assoc_resp
.variable
;
243 event
.assoc_reject
.resp_ies_len
=
244 len
- 24 - sizeof(mgmt
->u
.assoc_resp
);
246 event
.assoc_reject
.status_code
= status
;
248 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC_REJECT
, &event
);
253 os_memcpy(drv
->bssid
, mgmt
->sa
, ETH_ALEN
);
254 os_memcpy(drv
->prev_bssid
, mgmt
->sa
, ETH_ALEN
);
256 os_memset(&event
, 0, sizeof(event
));
257 event
.assoc_info
.resp_frame
= frame
;
258 event
.assoc_info
.resp_frame_len
= len
;
259 if (len
> 24 + sizeof(mgmt
->u
.assoc_resp
)) {
260 event
.assoc_info
.resp_ies
= (u8
*) mgmt
->u
.assoc_resp
.variable
;
261 event
.assoc_info
.resp_ies_len
=
262 len
- 24 - sizeof(mgmt
->u
.assoc_resp
);
266 event
.assoc_info
.req_ies
= nla_data(req_ie
);
267 event
.assoc_info
.req_ies_len
= nla_len(req_ie
);
270 /* When this association was initiated outside of wpa_supplicant,
271 * drv->ssid needs to be set here to satisfy later checking. */
272 ssid_len
= nl80211_get_assoc_ssid(drv
, drv
->ssid
);
274 drv
->ssid_len
= ssid_len
;
275 wpa_printf(MSG_DEBUG
,
276 "nl80211: Set drv->ssid based on scan res info to '%s'",
277 wpa_ssid_txt(drv
->ssid
, drv
->ssid_len
));
280 event
.assoc_info
.freq
= drv
->assoc_freq
;
281 drv
->first_bss
->freq
= drv
->assoc_freq
;
283 nl80211_parse_wmm_params(wmm
, &event
.assoc_info
.wmm_params
);
285 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC
, &event
);
289 static void mlme_event_connect(struct wpa_driver_nl80211_data
*drv
,
290 enum nl80211_commands cmd
, struct nlattr
*status
,
291 struct nlattr
*addr
, struct nlattr
*req_ie
,
292 struct nlattr
*resp_ie
,
293 struct nlattr
*timed_out
,
294 struct nlattr
*timeout_reason
,
295 struct nlattr
*authorized
,
296 struct nlattr
*key_replay_ctr
,
297 struct nlattr
*ptk_kck
,
298 struct nlattr
*ptk_kek
,
299 struct nlattr
*subnet_status
,
300 struct nlattr
*fils_erp_next_seq_num
,
301 struct nlattr
*fils_pmk
,
302 struct nlattr
*fils_pmkid
)
304 union wpa_event_data event
;
305 const u8
*ssid
= NULL
;
309 if (drv
->capa
.flags
& WPA_DRIVER_FLAGS_SME
) {
311 * Avoid reporting two association events that would confuse
314 wpa_printf(MSG_DEBUG
, "nl80211: Ignore connect event (cmd=%d) "
315 "when using userspace SME", cmd
);
319 drv
->connect_reassoc
= 0;
321 status_code
= status
? nla_get_u16(status
) : WLAN_STATUS_SUCCESS
;
323 if (cmd
== NL80211_CMD_CONNECT
) {
324 wpa_printf(MSG_DEBUG
,
325 "nl80211: Connect event (status=%u ignore_next_local_disconnect=%d)",
326 status_code
, drv
->ignore_next_local_disconnect
);
327 } else if (cmd
== NL80211_CMD_ROAM
) {
328 wpa_printf(MSG_DEBUG
, "nl80211: Roam event");
331 os_memset(&event
, 0, sizeof(event
));
332 if (cmd
== NL80211_CMD_CONNECT
&& status_code
!= WLAN_STATUS_SUCCESS
) {
334 event
.assoc_reject
.bssid
= nla_data(addr
);
335 if (drv
->ignore_next_local_disconnect
) {
336 drv
->ignore_next_local_disconnect
= 0;
337 if (!event
.assoc_reject
.bssid
||
338 (os_memcmp(event
.assoc_reject
.bssid
,
339 drv
->auth_attempt_bssid
,
342 * Ignore the event that came without a BSSID or
343 * for the old connection since this is likely
344 * not relevant to the new Connect command.
346 wpa_printf(MSG_DEBUG
,
347 "nl80211: Ignore connection failure event triggered during reassociation");
352 event
.assoc_reject
.resp_ies
= nla_data(resp_ie
);
353 event
.assoc_reject
.resp_ies_len
= nla_len(resp_ie
);
355 event
.assoc_reject
.status_code
= status_code
;
356 event
.assoc_reject
.timed_out
= timed_out
!= NULL
;
357 if (timed_out
&& timeout_reason
) {
358 enum nl80211_timeout_reason reason
;
360 reason
= nla_get_u32(timeout_reason
);
362 case NL80211_TIMEOUT_SCAN
:
363 event
.assoc_reject
.timeout_reason
= "scan";
365 case NL80211_TIMEOUT_AUTH
:
366 event
.assoc_reject
.timeout_reason
= "auth";
368 case NL80211_TIMEOUT_ASSOC
:
369 event
.assoc_reject
.timeout_reason
= "assoc";
375 if (fils_erp_next_seq_num
)
376 event
.assoc_reject
.fils_erp_next_seq_num
=
377 nla_get_u16(fils_erp_next_seq_num
);
378 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC_REJECT
, &event
);
384 os_memcpy(drv
->bssid
, nla_data(addr
), ETH_ALEN
);
385 os_memcpy(drv
->prev_bssid
, drv
->bssid
, ETH_ALEN
);
389 event
.assoc_info
.req_ies
= nla_data(req_ie
);
390 event
.assoc_info
.req_ies_len
= nla_len(req_ie
);
392 if (cmd
== NL80211_CMD_ROAM
) {
393 ssid
= get_ie(event
.assoc_info
.req_ies
,
394 event
.assoc_info
.req_ies_len
,
396 if (ssid
&& ssid
[1] > 0 && ssid
[1] <= 32) {
397 drv
->ssid_len
= ssid
[1];
398 os_memcpy(drv
->ssid
, ssid
+ 2, ssid
[1]);
399 wpa_printf(MSG_DEBUG
,
400 "nl80211: Set drv->ssid based on req_ie to '%s'",
401 wpa_ssid_txt(drv
->ssid
,
407 event
.assoc_info
.resp_ies
= nla_data(resp_ie
);
408 event
.assoc_info
.resp_ies_len
= nla_len(resp_ie
);
411 event
.assoc_info
.freq
= nl80211_get_assoc_freq(drv
);
412 drv
->first_bss
->freq
= drv
->assoc_freq
;
414 if ((!ssid
|| ssid
[1] == 0 || ssid
[1] > 32) &&
415 (ssid_len
= nl80211_get_assoc_ssid(drv
, drv
->ssid
)) > 0) {
416 /* When this connection was initiated outside of wpa_supplicant,
417 * drv->ssid needs to be set here to satisfy later checking. */
418 drv
->ssid_len
= ssid_len
;
419 wpa_printf(MSG_DEBUG
,
420 "nl80211: Set drv->ssid based on scan res info to '%s'",
421 wpa_ssid_txt(drv
->ssid
, drv
->ssid_len
));
424 if (authorized
&& nla_get_u8(authorized
)) {
425 event
.assoc_info
.authorized
= 1;
426 wpa_printf(MSG_DEBUG
, "nl80211: connection authorized");
428 if (key_replay_ctr
) {
429 event
.assoc_info
.key_replay_ctr
= nla_data(key_replay_ctr
);
430 event
.assoc_info
.key_replay_ctr_len
= nla_len(key_replay_ctr
);
433 event
.assoc_info
.ptk_kck
= nla_data(ptk_kck
);
434 event
.assoc_info
.ptk_kck_len
= nla_len(ptk_kck
);
437 event
.assoc_info
.ptk_kek
= nla_data(ptk_kek
);
438 event
.assoc_info
.ptk_kek_len
= nla_len(ptk_kek
);
443 * At least for now, this is only available from
444 * QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS and that
445 * attribute has the same values 0, 1, 2 as are used in the
446 * variable here, so no mapping between different values are
449 event
.assoc_info
.subnet_status
= nla_get_u8(subnet_status
);
452 if (fils_erp_next_seq_num
)
453 event
.assoc_info
.fils_erp_next_seq_num
=
454 nla_get_u16(fils_erp_next_seq_num
);
457 event
.assoc_info
.fils_pmk
= nla_data(fils_pmk
);
458 event
.assoc_info
.fils_pmk_len
= nla_len(fils_pmk
);
462 event
.assoc_info
.fils_pmkid
= nla_data(fils_pmkid
);
464 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC
, &event
);
468 static void mlme_event_disconnect(struct wpa_driver_nl80211_data
*drv
,
469 struct nlattr
*reason
, struct nlattr
*addr
,
470 struct nlattr
*by_ap
)
472 union wpa_event_data data
;
473 unsigned int locally_generated
= by_ap
== NULL
;
475 if (drv
->capa
.flags
& WPA_DRIVER_FLAGS_SME
) {
477 * Avoid reporting two disassociation events that could
478 * confuse the core code.
480 wpa_printf(MSG_DEBUG
, "nl80211: Ignore disconnect "
481 "event when using userspace SME");
485 if (drv
->ignore_next_local_disconnect
) {
486 drv
->ignore_next_local_disconnect
= 0;
487 if (locally_generated
) {
488 wpa_printf(MSG_DEBUG
, "nl80211: Ignore disconnect "
489 "event triggered during reassociation");
492 wpa_printf(MSG_WARNING
, "nl80211: Was expecting local "
493 "disconnect but got another disconnect "
497 wpa_printf(MSG_DEBUG
, "nl80211: Disconnect event");
498 nl80211_mark_disconnected(drv
);
499 os_memset(&data
, 0, sizeof(data
));
501 data
.deauth_info
.reason_code
= nla_get_u16(reason
);
502 data
.deauth_info
.locally_generated
= by_ap
== NULL
;
503 wpa_supplicant_event(drv
->ctx
, EVENT_DEAUTH
, &data
);
507 static int calculate_chan_offset(int width
, int freq
, int cf1
, int cf2
)
511 switch (convert2width(width
)) {
512 case CHAN_WIDTH_20_NOHT
:
524 case CHAN_WIDTH_UNKNOWN
:
525 case CHAN_WIDTH_80P80
:
526 /* FIXME: implement this */
530 return (abs(freq
- freq1
) / 20) % 2 == 0 ? 1 : -1;
534 static void mlme_event_ch_switch(struct wpa_driver_nl80211_data
*drv
,
535 struct nlattr
*ifindex
, struct nlattr
*freq
,
536 struct nlattr
*type
, struct nlattr
*bw
,
537 struct nlattr
*cf1
, struct nlattr
*cf2
,
540 struct i802_bss
*bss
;
541 union wpa_event_data data
;
546 wpa_printf(MSG_DEBUG
, "nl80211: Channel switch%s event",
547 finished
? "" : " started");
552 ifidx
= nla_get_u32(ifindex
);
553 bss
= get_bss_ifindex(drv
, ifidx
);
555 wpa_printf(MSG_WARNING
, "nl80211: Unknown ifindex (%d) for channel switch, ignoring",
561 enum nl80211_channel_type ch_type
= nla_get_u32(type
);
563 wpa_printf(MSG_DEBUG
, "nl80211: Channel type: %d", ch_type
);
565 case NL80211_CHAN_NO_HT
:
568 case NL80211_CHAN_HT20
:
570 case NL80211_CHAN_HT40PLUS
:
573 case NL80211_CHAN_HT40MINUS
:
577 } else if (bw
&& cf1
) {
578 /* This can happen for example with VHT80 ch switch */
579 chan_offset
= calculate_chan_offset(nla_get_u32(bw
),
582 cf2
? nla_get_u32(cf2
) : 0);
584 wpa_printf(MSG_WARNING
, "nl80211: Unknown secondary channel information - following channel definition calculations may fail");
587 os_memset(&data
, 0, sizeof(data
));
588 data
.ch_switch
.freq
= nla_get_u32(freq
);
589 data
.ch_switch
.ht_enabled
= ht_enabled
;
590 data
.ch_switch
.ch_offset
= chan_offset
;
592 data
.ch_switch
.ch_width
= convert2width(nla_get_u32(bw
));
594 data
.ch_switch
.cf1
= nla_get_u32(cf1
);
596 data
.ch_switch
.cf2
= nla_get_u32(cf2
);
598 bss
->freq
= data
.ch_switch
.freq
;
599 drv
->assoc_freq
= data
.ch_switch
.freq
;
601 wpa_supplicant_event(bss
->ctx
, finished
?
602 EVENT_CH_SWITCH
: EVENT_CH_SWITCH_STARTED
, &data
);
606 static void mlme_timeout_event(struct wpa_driver_nl80211_data
*drv
,
607 enum nl80211_commands cmd
, struct nlattr
*addr
)
609 union wpa_event_data event
;
610 enum wpa_event_type ev
;
612 if (nla_len(addr
) != ETH_ALEN
)
615 wpa_printf(MSG_DEBUG
, "nl80211: MLME event %d; timeout with " MACSTR
,
616 cmd
, MAC2STR((u8
*) nla_data(addr
)));
618 if (cmd
== NL80211_CMD_AUTHENTICATE
)
619 ev
= EVENT_AUTH_TIMED_OUT
;
620 else if (cmd
== NL80211_CMD_ASSOCIATE
)
621 ev
= EVENT_ASSOC_TIMED_OUT
;
625 os_memset(&event
, 0, sizeof(event
));
626 os_memcpy(event
.timeout_event
.addr
, nla_data(addr
), ETH_ALEN
);
627 wpa_supplicant_event(drv
->ctx
, ev
, &event
);
631 static void mlme_event_mgmt(struct i802_bss
*bss
,
632 struct nlattr
*freq
, struct nlattr
*sig
,
633 const u8
*frame
, size_t len
)
635 struct wpa_driver_nl80211_data
*drv
= bss
->drv
;
636 const struct ieee80211_mgmt
*mgmt
;
637 union wpa_event_data event
;
642 wpa_printf(MSG_MSGDUMP
, "nl80211: Frame event");
643 mgmt
= (const struct ieee80211_mgmt
*) frame
;
645 wpa_printf(MSG_DEBUG
, "nl80211: Too short management frame");
649 fc
= le_to_host16(mgmt
->frame_control
);
650 stype
= WLAN_FC_GET_STYPE(fc
);
653 ssi_signal
= (s32
) nla_get_u32(sig
);
655 os_memset(&event
, 0, sizeof(event
));
657 event
.rx_mgmt
.freq
= nla_get_u32(freq
);
658 rx_freq
= drv
->last_mgmt_freq
= event
.rx_mgmt
.freq
;
660 wpa_printf(MSG_DEBUG
,
661 "nl80211: RX frame da=" MACSTR
" sa=" MACSTR
" bssid=" MACSTR
662 " freq=%d ssi_signal=%d fc=0x%x seq_ctrl=0x%x stype=%u (%s) len=%u",
663 MAC2STR(mgmt
->da
), MAC2STR(mgmt
->sa
), MAC2STR(mgmt
->bssid
),
664 rx_freq
, ssi_signal
, fc
,
665 le_to_host16(mgmt
->seq_ctrl
), stype
, fc2str(fc
),
667 event
.rx_mgmt
.frame
= frame
;
668 event
.rx_mgmt
.frame_len
= len
;
669 event
.rx_mgmt
.ssi_signal
= ssi_signal
;
670 event
.rx_mgmt
.drv_priv
= bss
;
671 wpa_supplicant_event(drv
->ctx
, EVENT_RX_MGMT
, &event
);
675 static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data
*drv
,
676 struct nlattr
*cookie
, const u8
*frame
,
677 size_t len
, struct nlattr
*ack
)
679 union wpa_event_data event
;
680 const struct ieee80211_hdr
*hdr
;
683 wpa_printf(MSG_DEBUG
, "nl80211: Frame TX status event");
684 if (!is_ap_interface(drv
->nlmode
)) {
690 cookie_val
= nla_get_u64(cookie
);
691 wpa_printf(MSG_DEBUG
, "nl80211: Action TX status:"
692 " cookie=0x%llx%s (ack=%d)",
693 (long long unsigned int) cookie_val
,
694 cookie_val
== drv
->send_action_cookie
?
695 " (match)" : " (unknown)", ack
!= NULL
);
696 if (cookie_val
!= drv
->send_action_cookie
)
700 hdr
= (const struct ieee80211_hdr
*) frame
;
701 fc
= le_to_host16(hdr
->frame_control
);
703 os_memset(&event
, 0, sizeof(event
));
704 event
.tx_status
.type
= WLAN_FC_GET_TYPE(fc
);
705 event
.tx_status
.stype
= WLAN_FC_GET_STYPE(fc
);
706 event
.tx_status
.dst
= hdr
->addr1
;
707 event
.tx_status
.data
= frame
;
708 event
.tx_status
.data_len
= len
;
709 event
.tx_status
.ack
= ack
!= NULL
;
710 wpa_supplicant_event(drv
->ctx
, EVENT_TX_STATUS
, &event
);
714 static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data
*drv
,
715 enum wpa_event_type type
,
716 const u8
*frame
, size_t len
)
718 const struct ieee80211_mgmt
*mgmt
;
719 union wpa_event_data event
;
720 const u8
*bssid
= NULL
;
723 if (type
== EVENT_DEAUTH
)
724 wpa_printf(MSG_DEBUG
, "nl80211: Deauthenticate event");
726 wpa_printf(MSG_DEBUG
, "nl80211: Disassociate event");
728 mgmt
= (const struct ieee80211_mgmt
*) frame
;
732 if ((drv
->capa
.flags
& WPA_DRIVER_FLAGS_SME
) &&
734 os_memcmp(bssid
, drv
->auth_bssid
, ETH_ALEN
) != 0 &&
735 os_memcmp(bssid
, drv
->auth_attempt_bssid
, ETH_ALEN
) != 0 &&
736 os_memcmp(bssid
, drv
->prev_bssid
, ETH_ALEN
) == 0) {
738 * Avoid issues with some roaming cases where
739 * disconnection event for the old AP may show up after
740 * we have started connection with the new AP.
741 * In case of locally generated event clear
742 * ignore_next_local_deauth as well, to avoid next local
743 * deauth event be wrongly ignored.
745 if (!os_memcmp(mgmt
->sa
, drv
->first_bss
->addr
,
747 wpa_printf(MSG_DEBUG
,
748 "nl80211: Received a locally generated deauth event. Clear ignore_next_local_deauth flag");
749 drv
->ignore_next_local_deauth
= 0;
751 wpa_printf(MSG_DEBUG
,
752 "nl80211: Ignore deauth/disassoc event from old AP " MACSTR
" when already authenticating with " MACSTR
,
754 MAC2STR(drv
->auth_attempt_bssid
));
759 if (!(drv
->capa
.flags
& WPA_DRIVER_FLAGS_SME
) &&
760 drv
->connect_reassoc
&& drv
->associated
&&
761 os_memcmp(bssid
, drv
->prev_bssid
, ETH_ALEN
) == 0 &&
762 os_memcmp(bssid
, drv
->auth_attempt_bssid
, ETH_ALEN
) != 0) {
764 * Avoid issues with some roaming cases where
765 * disconnection event for the old AP may show up after
766 * we have started connection with the new AP.
768 wpa_printf(MSG_DEBUG
,
769 "nl80211: Ignore deauth/disassoc event from old AP "
771 " when already connecting with " MACSTR
,
773 MAC2STR(drv
->auth_attempt_bssid
));
777 if (drv
->associated
!= 0 &&
778 os_memcmp(bssid
, drv
->bssid
, ETH_ALEN
) != 0 &&
779 os_memcmp(bssid
, drv
->auth_bssid
, ETH_ALEN
) != 0) {
781 * We have presumably received this deauth as a
782 * response to a clear_state_mismatch() outgoing
783 * deauth. Don't let it take us offline!
785 wpa_printf(MSG_DEBUG
, "nl80211: Deauth received "
786 "from Unknown BSSID " MACSTR
" -- ignoring",
792 nl80211_mark_disconnected(drv
);
793 os_memset(&event
, 0, sizeof(event
));
795 /* Note: Same offset for Reason Code in both frame subtypes */
796 if (len
>= 24 + sizeof(mgmt
->u
.deauth
))
797 reason_code
= le_to_host16(mgmt
->u
.deauth
.reason_code
);
799 if (type
== EVENT_DISASSOC
) {
800 event
.disassoc_info
.locally_generated
=
801 !os_memcmp(mgmt
->sa
, drv
->first_bss
->addr
, ETH_ALEN
);
802 event
.disassoc_info
.addr
= bssid
;
803 event
.disassoc_info
.reason_code
= reason_code
;
804 if (frame
+ len
> mgmt
->u
.disassoc
.variable
) {
805 event
.disassoc_info
.ie
= mgmt
->u
.disassoc
.variable
;
806 event
.disassoc_info
.ie_len
= frame
+ len
-
807 mgmt
->u
.disassoc
.variable
;
810 event
.deauth_info
.locally_generated
=
811 !os_memcmp(mgmt
->sa
, drv
->first_bss
->addr
, ETH_ALEN
);
812 if (drv
->ignore_deauth_event
) {
813 wpa_printf(MSG_DEBUG
, "nl80211: Ignore deauth event due to previous forced deauth-during-auth");
814 drv
->ignore_deauth_event
= 0;
815 if (event
.deauth_info
.locally_generated
)
816 drv
->ignore_next_local_deauth
= 0;
819 if (drv
->ignore_next_local_deauth
) {
820 drv
->ignore_next_local_deauth
= 0;
821 if (event
.deauth_info
.locally_generated
) {
822 wpa_printf(MSG_DEBUG
, "nl80211: Ignore deauth event triggered due to own deauth request");
825 wpa_printf(MSG_WARNING
, "nl80211: Was expecting local deauth but got another disconnect event first");
827 event
.deauth_info
.addr
= bssid
;
828 event
.deauth_info
.reason_code
= reason_code
;
829 if (frame
+ len
> mgmt
->u
.deauth
.variable
) {
830 event
.deauth_info
.ie
= mgmt
->u
.deauth
.variable
;
831 event
.deauth_info
.ie_len
= frame
+ len
-
832 mgmt
->u
.deauth
.variable
;
836 wpa_supplicant_event(drv
->ctx
, type
, &event
);
840 static void mlme_event_unprot_disconnect(struct wpa_driver_nl80211_data
*drv
,
841 enum wpa_event_type type
,
842 const u8
*frame
, size_t len
)
844 const struct ieee80211_mgmt
*mgmt
;
845 union wpa_event_data event
;
848 if (type
== EVENT_UNPROT_DEAUTH
)
849 wpa_printf(MSG_DEBUG
, "nl80211: Unprot Deauthenticate event");
851 wpa_printf(MSG_DEBUG
, "nl80211: Unprot Disassociate event");
856 mgmt
= (const struct ieee80211_mgmt
*) frame
;
858 os_memset(&event
, 0, sizeof(event
));
859 /* Note: Same offset for Reason Code in both frame subtypes */
860 if (len
>= 24 + sizeof(mgmt
->u
.deauth
))
861 reason_code
= le_to_host16(mgmt
->u
.deauth
.reason_code
);
863 if (type
== EVENT_UNPROT_DISASSOC
) {
864 event
.unprot_disassoc
.sa
= mgmt
->sa
;
865 event
.unprot_disassoc
.da
= mgmt
->da
;
866 event
.unprot_disassoc
.reason_code
= reason_code
;
868 event
.unprot_deauth
.sa
= mgmt
->sa
;
869 event
.unprot_deauth
.da
= mgmt
->da
;
870 event
.unprot_deauth
.reason_code
= reason_code
;
873 wpa_supplicant_event(drv
->ctx
, type
, &event
);
877 static void mlme_event(struct i802_bss
*bss
,
878 enum nl80211_commands cmd
, struct nlattr
*frame
,
879 struct nlattr
*addr
, struct nlattr
*timed_out
,
880 struct nlattr
*freq
, struct nlattr
*ack
,
881 struct nlattr
*cookie
, struct nlattr
*sig
,
882 struct nlattr
*wmm
, struct nlattr
*req_ie
)
884 struct wpa_driver_nl80211_data
*drv
= bss
->drv
;
888 if (timed_out
&& addr
) {
889 mlme_timeout_event(drv
, cmd
, addr
);
894 wpa_printf(MSG_DEBUG
,
895 "nl80211: MLME event %d (%s) without frame data",
896 cmd
, nl80211_command_to_string(cmd
));
900 data
= nla_data(frame
);
901 len
= nla_len(frame
);
902 if (len
< 4 + 2 * ETH_ALEN
) {
903 wpa_printf(MSG_MSGDUMP
, "nl80211: MLME event %d (%s) on %s("
904 MACSTR
") - too short",
905 cmd
, nl80211_command_to_string(cmd
), bss
->ifname
,
909 wpa_printf(MSG_MSGDUMP
, "nl80211: MLME event %d (%s) on %s(" MACSTR
910 ") A1=" MACSTR
" A2=" MACSTR
, cmd
,
911 nl80211_command_to_string(cmd
), bss
->ifname
,
912 MAC2STR(bss
->addr
), MAC2STR(data
+ 4),
913 MAC2STR(data
+ 4 + ETH_ALEN
));
914 if (cmd
!= NL80211_CMD_FRAME_TX_STATUS
&& !(data
[4] & 0x01) &&
915 os_memcmp(bss
->addr
, data
+ 4, ETH_ALEN
) != 0 &&
916 (is_zero_ether_addr(bss
->rand_addr
) ||
917 os_memcmp(bss
->rand_addr
, data
+ 4, ETH_ALEN
) != 0) &&
918 os_memcmp(bss
->addr
, data
+ 4 + ETH_ALEN
, ETH_ALEN
) != 0) {
919 wpa_printf(MSG_MSGDUMP
, "nl80211: %s: Ignore MLME frame event "
920 "for foreign address", bss
->ifname
);
923 wpa_hexdump(MSG_MSGDUMP
, "nl80211: MLME event frame",
924 nla_data(frame
), nla_len(frame
));
927 case NL80211_CMD_AUTHENTICATE
:
928 mlme_event_auth(drv
, nla_data(frame
), nla_len(frame
));
930 case NL80211_CMD_ASSOCIATE
:
931 mlme_event_assoc(drv
, nla_data(frame
), nla_len(frame
), wmm
,
934 case NL80211_CMD_DEAUTHENTICATE
:
935 mlme_event_deauth_disassoc(drv
, EVENT_DEAUTH
,
936 nla_data(frame
), nla_len(frame
));
938 case NL80211_CMD_DISASSOCIATE
:
939 mlme_event_deauth_disassoc(drv
, EVENT_DISASSOC
,
940 nla_data(frame
), nla_len(frame
));
942 case NL80211_CMD_FRAME
:
943 mlme_event_mgmt(bss
, freq
, sig
, nla_data(frame
),
946 case NL80211_CMD_FRAME_TX_STATUS
:
947 mlme_event_mgmt_tx_status(drv
, cookie
, nla_data(frame
),
948 nla_len(frame
), ack
);
950 case NL80211_CMD_UNPROT_DEAUTHENTICATE
:
951 mlme_event_unprot_disconnect(drv
, EVENT_UNPROT_DEAUTH
,
952 nla_data(frame
), nla_len(frame
));
954 case NL80211_CMD_UNPROT_DISASSOCIATE
:
955 mlme_event_unprot_disconnect(drv
, EVENT_UNPROT_DISASSOC
,
956 nla_data(frame
), nla_len(frame
));
964 static void mlme_event_michael_mic_failure(struct i802_bss
*bss
,
967 union wpa_event_data data
;
969 wpa_printf(MSG_DEBUG
, "nl80211: MLME event Michael MIC failure");
970 os_memset(&data
, 0, sizeof(data
));
971 if (tb
[NL80211_ATTR_MAC
]) {
972 wpa_hexdump(MSG_DEBUG
, "nl80211: Source MAC address",
973 nla_data(tb
[NL80211_ATTR_MAC
]),
974 nla_len(tb
[NL80211_ATTR_MAC
]));
975 data
.michael_mic_failure
.src
= nla_data(tb
[NL80211_ATTR_MAC
]);
977 if (tb
[NL80211_ATTR_KEY_SEQ
]) {
978 wpa_hexdump(MSG_DEBUG
, "nl80211: TSC",
979 nla_data(tb
[NL80211_ATTR_KEY_SEQ
]),
980 nla_len(tb
[NL80211_ATTR_KEY_SEQ
]));
982 if (tb
[NL80211_ATTR_KEY_TYPE
]) {
983 enum nl80211_key_type key_type
=
984 nla_get_u32(tb
[NL80211_ATTR_KEY_TYPE
]);
985 wpa_printf(MSG_DEBUG
, "nl80211: Key Type %d", key_type
);
986 if (key_type
== NL80211_KEYTYPE_PAIRWISE
)
987 data
.michael_mic_failure
.unicast
= 1;
989 data
.michael_mic_failure
.unicast
= 1;
991 if (tb
[NL80211_ATTR_KEY_IDX
]) {
992 u8 key_id
= nla_get_u8(tb
[NL80211_ATTR_KEY_IDX
]);
993 wpa_printf(MSG_DEBUG
, "nl80211: Key Id %d", key_id
);
996 wpa_supplicant_event(bss
->ctx
, EVENT_MICHAEL_MIC_FAILURE
, &data
);
1000 static void mlme_event_join_ibss(struct wpa_driver_nl80211_data
*drv
,
1001 struct nlattr
*tb
[])
1004 union wpa_event_data event
;
1006 if (tb
[NL80211_ATTR_MAC
] == NULL
) {
1007 wpa_printf(MSG_DEBUG
, "nl80211: No address in IBSS joined "
1011 os_memcpy(drv
->bssid
, nla_data(tb
[NL80211_ATTR_MAC
]), ETH_ALEN
);
1013 drv
->associated
= 1;
1014 wpa_printf(MSG_DEBUG
, "nl80211: IBSS " MACSTR
" joined",
1015 MAC2STR(drv
->bssid
));
1017 freq
= nl80211_get_assoc_freq(drv
);
1019 wpa_printf(MSG_DEBUG
, "nl80211: IBSS on frequency %u MHz",
1021 drv
->first_bss
->freq
= freq
;
1024 os_memset(&event
, 0, sizeof(event
));
1025 event
.assoc_info
.freq
= freq
;
1027 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC
, &event
);
1031 static void mlme_event_remain_on_channel(struct wpa_driver_nl80211_data
*drv
,
1032 int cancel_event
, struct nlattr
*tb
[])
1034 unsigned int freq
, chan_type
, duration
;
1035 union wpa_event_data data
;
1038 if (tb
[NL80211_ATTR_WIPHY_FREQ
])
1039 freq
= nla_get_u32(tb
[NL80211_ATTR_WIPHY_FREQ
]);
1043 if (tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
])
1044 chan_type
= nla_get_u32(tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
]);
1048 if (tb
[NL80211_ATTR_DURATION
])
1049 duration
= nla_get_u32(tb
[NL80211_ATTR_DURATION
]);
1053 if (tb
[NL80211_ATTR_COOKIE
])
1054 cookie
= nla_get_u64(tb
[NL80211_ATTR_COOKIE
]);
1058 wpa_printf(MSG_DEBUG
, "nl80211: Remain-on-channel event (cancel=%d "
1059 "freq=%u channel_type=%u duration=%u cookie=0x%llx (%s))",
1060 cancel_event
, freq
, chan_type
, duration
,
1061 (long long unsigned int) cookie
,
1062 cookie
== drv
->remain_on_chan_cookie
? "match" : "unknown");
1064 if (cookie
!= drv
->remain_on_chan_cookie
)
1065 return; /* not for us */
1068 drv
->pending_remain_on_chan
= 0;
1070 os_memset(&data
, 0, sizeof(data
));
1071 data
.remain_on_channel
.freq
= freq
;
1072 data
.remain_on_channel
.duration
= duration
;
1073 wpa_supplicant_event(drv
->ctx
, cancel_event
?
1074 EVENT_CANCEL_REMAIN_ON_CHANNEL
:
1075 EVENT_REMAIN_ON_CHANNEL
, &data
);
1079 static void mlme_event_ft_event(struct wpa_driver_nl80211_data
*drv
,
1080 struct nlattr
*tb
[])
1082 union wpa_event_data data
;
1084 os_memset(&data
, 0, sizeof(data
));
1086 if (tb
[NL80211_ATTR_IE
]) {
1087 data
.ft_ies
.ies
= nla_data(tb
[NL80211_ATTR_IE
]);
1088 data
.ft_ies
.ies_len
= nla_len(tb
[NL80211_ATTR_IE
]);
1091 if (tb
[NL80211_ATTR_IE_RIC
]) {
1092 data
.ft_ies
.ric_ies
= nla_data(tb
[NL80211_ATTR_IE_RIC
]);
1093 data
.ft_ies
.ric_ies_len
= nla_len(tb
[NL80211_ATTR_IE_RIC
]);
1096 if (tb
[NL80211_ATTR_MAC
])
1097 os_memcpy(data
.ft_ies
.target_ap
,
1098 nla_data(tb
[NL80211_ATTR_MAC
]), ETH_ALEN
);
1100 wpa_printf(MSG_DEBUG
, "nl80211: FT event target_ap " MACSTR
,
1101 MAC2STR(data
.ft_ies
.target_ap
));
1103 wpa_supplicant_event(drv
->ctx
, EVENT_FT_RESPONSE
, &data
);
1107 static void send_scan_event(struct wpa_driver_nl80211_data
*drv
, int aborted
,
1108 struct nlattr
*tb
[], int external_scan
)
1110 union wpa_event_data event
;
1113 struct scan_info
*info
;
1114 #define MAX_REPORT_FREQS 50
1115 int freqs
[MAX_REPORT_FREQS
];
1118 if (!external_scan
&& drv
->scan_for_auth
) {
1119 drv
->scan_for_auth
= 0;
1120 wpa_printf(MSG_DEBUG
, "nl80211: Scan results for missing "
1121 "cfg80211 BSS entry");
1122 wpa_driver_nl80211_authenticate_retry(drv
);
1126 os_memset(&event
, 0, sizeof(event
));
1127 info
= &event
.scan_info
;
1128 info
->aborted
= aborted
;
1129 info
->external_scan
= external_scan
;
1130 info
->nl_scan_event
= 1;
1132 if (tb
[NL80211_ATTR_SCAN_SSIDS
]) {
1133 nla_for_each_nested(nl
, tb
[NL80211_ATTR_SCAN_SSIDS
], rem
) {
1134 struct wpa_driver_scan_ssid
*s
=
1135 &info
->ssids
[info
->num_ssids
];
1136 s
->ssid
= nla_data(nl
);
1137 s
->ssid_len
= nla_len(nl
);
1138 wpa_printf(MSG_DEBUG
, "nl80211: Scan probed for SSID '%s'",
1139 wpa_ssid_txt(s
->ssid
, s
->ssid_len
));
1141 if (info
->num_ssids
== WPAS_MAX_SCAN_SSIDS
)
1145 if (tb
[NL80211_ATTR_SCAN_FREQUENCIES
]) {
1146 char msg
[300], *pos
, *end
;
1150 end
= pos
+ sizeof(msg
);
1153 nla_for_each_nested(nl
, tb
[NL80211_ATTR_SCAN_FREQUENCIES
], rem
)
1155 freqs
[num_freqs
] = nla_get_u32(nl
);
1156 res
= os_snprintf(pos
, end
- pos
, " %d",
1158 if (!os_snprintf_error(end
- pos
, res
))
1161 if (num_freqs
== MAX_REPORT_FREQS
- 1)
1164 info
->freqs
= freqs
;
1165 info
->num_freqs
= num_freqs
;
1166 wpa_printf(MSG_DEBUG
, "nl80211: Scan included frequencies:%s",
1170 if (tb
[NL80211_ATTR_SCAN_START_TIME_TSF
] &&
1171 tb
[NL80211_ATTR_SCAN_START_TIME_TSF_BSSID
]) {
1172 info
->scan_start_tsf
=
1173 nla_get_u64(tb
[NL80211_ATTR_SCAN_START_TIME_TSF
]);
1174 os_memcpy(info
->scan_start_tsf_bssid
,
1175 nla_data(tb
[NL80211_ATTR_SCAN_START_TIME_TSF_BSSID
]),
1179 wpa_supplicant_event(drv
->ctx
, EVENT_SCAN_RESULTS
, &event
);
1183 static void nl80211_cqm_event(struct wpa_driver_nl80211_data
*drv
,
1184 struct nlattr
*tb
[])
1186 static struct nla_policy cqm_policy
[NL80211_ATTR_CQM_MAX
+ 1] = {
1187 [NL80211_ATTR_CQM_RSSI_THOLD
] = { .type
= NLA_U32
},
1188 [NL80211_ATTR_CQM_RSSI_HYST
] = { .type
= NLA_U8
},
1189 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT
] = { .type
= NLA_U32
},
1190 [NL80211_ATTR_CQM_PKT_LOSS_EVENT
] = { .type
= NLA_U32
},
1191 [NL80211_ATTR_CQM_TXE_RATE
] = { .type
= NLA_U32
},
1192 [NL80211_ATTR_CQM_TXE_PKTS
] = { .type
= NLA_U32
},
1193 [NL80211_ATTR_CQM_TXE_INTVL
] = { .type
= NLA_U32
},
1194 [NL80211_ATTR_CQM_BEACON_LOSS_EVENT
] = { .type
= NLA_FLAG
},
1196 struct nlattr
*cqm
[NL80211_ATTR_CQM_MAX
+ 1];
1197 enum nl80211_cqm_rssi_threshold_event event
;
1198 union wpa_event_data ed
;
1199 struct wpa_signal_info sig
;
1202 if (tb
[NL80211_ATTR_CQM
] == NULL
||
1203 nla_parse_nested(cqm
, NL80211_ATTR_CQM_MAX
, tb
[NL80211_ATTR_CQM
],
1205 wpa_printf(MSG_DEBUG
, "nl80211: Ignore invalid CQM event");
1209 os_memset(&ed
, 0, sizeof(ed
));
1211 if (cqm
[NL80211_ATTR_CQM_PKT_LOSS_EVENT
]) {
1212 if (!tb
[NL80211_ATTR_MAC
])
1214 os_memcpy(ed
.low_ack
.addr
, nla_data(tb
[NL80211_ATTR_MAC
]),
1216 ed
.low_ack
.num_packets
=
1217 nla_get_u32(cqm
[NL80211_ATTR_CQM_PKT_LOSS_EVENT
]);
1218 wpa_printf(MSG_DEBUG
, "nl80211: Packet loss event for " MACSTR
1219 " (num_packets %u)",
1220 MAC2STR(ed
.low_ack
.addr
), ed
.low_ack
.num_packets
);
1221 wpa_supplicant_event(drv
->ctx
, EVENT_STATION_LOW_ACK
, &ed
);
1225 if (cqm
[NL80211_ATTR_CQM_BEACON_LOSS_EVENT
]) {
1226 wpa_printf(MSG_DEBUG
, "nl80211: Beacon loss event");
1227 wpa_supplicant_event(drv
->ctx
, EVENT_BEACON_LOSS
, NULL
);
1231 if (cqm
[NL80211_ATTR_CQM_TXE_RATE
] &&
1232 cqm
[NL80211_ATTR_CQM_TXE_PKTS
] &&
1233 cqm
[NL80211_ATTR_CQM_TXE_INTVL
] &&
1234 cqm
[NL80211_ATTR_MAC
]) {
1235 wpa_printf(MSG_DEBUG
, "nl80211: CQM TXE event for " MACSTR
1236 " (rate: %u pkts: %u interval: %u)",
1237 MAC2STR((u8
*) nla_data(cqm
[NL80211_ATTR_MAC
])),
1238 nla_get_u32(cqm
[NL80211_ATTR_CQM_TXE_RATE
]),
1239 nla_get_u32(cqm
[NL80211_ATTR_CQM_TXE_PKTS
]),
1240 nla_get_u32(cqm
[NL80211_ATTR_CQM_TXE_INTVL
]));
1244 if (cqm
[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT
] == NULL
) {
1245 wpa_printf(MSG_DEBUG
,
1246 "nl80211: Not a CQM RSSI threshold event");
1249 event
= nla_get_u32(cqm
[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT
]);
1251 if (event
== NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH
) {
1252 wpa_printf(MSG_DEBUG
, "nl80211: Connection quality monitor "
1253 "event: RSSI high");
1254 ed
.signal_change
.above_threshold
= 1;
1255 } else if (event
== NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW
) {
1256 wpa_printf(MSG_DEBUG
, "nl80211: Connection quality monitor "
1258 ed
.signal_change
.above_threshold
= 0;
1260 wpa_printf(MSG_DEBUG
,
1261 "nl80211: Unknown CQM RSSI threshold event: %d",
1266 res
= nl80211_get_link_signal(drv
, &sig
);
1268 ed
.signal_change
.current_signal
= sig
.current_signal
;
1269 ed
.signal_change
.current_txrate
= sig
.current_txrate
;
1270 wpa_printf(MSG_DEBUG
, "nl80211: Signal: %d dBm txrate: %d",
1271 sig
.current_signal
, sig
.current_txrate
);
1274 res
= nl80211_get_link_noise(drv
, &sig
);
1276 ed
.signal_change
.current_noise
= sig
.current_noise
;
1277 wpa_printf(MSG_DEBUG
, "nl80211: Noise: %d dBm",
1281 wpa_supplicant_event(drv
->ctx
, EVENT_SIGNAL_CHANGE
, &ed
);
1285 static void nl80211_new_peer_candidate(struct wpa_driver_nl80211_data
*drv
,
1289 union wpa_event_data data
;
1291 if (drv
->nlmode
!= NL80211_IFTYPE_MESH_POINT
||
1292 !tb
[NL80211_ATTR_MAC
] || !tb
[NL80211_ATTR_IE
])
1295 addr
= nla_data(tb
[NL80211_ATTR_MAC
]);
1296 wpa_printf(MSG_DEBUG
, "nl80211: New peer candidate " MACSTR
,
1299 os_memset(&data
, 0, sizeof(data
));
1300 data
.mesh_peer
.peer
= addr
;
1301 data
.mesh_peer
.ies
= nla_data(tb
[NL80211_ATTR_IE
]);
1302 data
.mesh_peer
.ie_len
= nla_len(tb
[NL80211_ATTR_IE
]);
1303 wpa_supplicant_event(drv
->ctx
, EVENT_NEW_PEER_CANDIDATE
, &data
);
1307 static void nl80211_new_station_event(struct wpa_driver_nl80211_data
*drv
,
1308 struct i802_bss
*bss
,
1312 union wpa_event_data data
;
1314 if (tb
[NL80211_ATTR_MAC
] == NULL
)
1316 addr
= nla_data(tb
[NL80211_ATTR_MAC
]);
1317 wpa_printf(MSG_DEBUG
, "nl80211: New station " MACSTR
, MAC2STR(addr
));
1319 if (is_ap_interface(drv
->nlmode
) && drv
->device_ap_sme
) {
1322 if (tb
[NL80211_ATTR_IE
]) {
1323 ies
= nla_data(tb
[NL80211_ATTR_IE
]);
1324 ies_len
= nla_len(tb
[NL80211_ATTR_IE
]);
1326 wpa_hexdump(MSG_DEBUG
, "nl80211: Assoc Req IEs", ies
, ies_len
);
1327 drv_event_assoc(bss
->ctx
, addr
, ies
, ies_len
, 0);
1331 if (drv
->nlmode
!= NL80211_IFTYPE_ADHOC
)
1334 os_memset(&data
, 0, sizeof(data
));
1335 os_memcpy(data
.ibss_rsn_start
.peer
, addr
, ETH_ALEN
);
1336 wpa_supplicant_event(bss
->ctx
, EVENT_IBSS_RSN_START
, &data
);
1340 static void nl80211_del_station_event(struct wpa_driver_nl80211_data
*drv
,
1341 struct i802_bss
*bss
,
1345 union wpa_event_data data
;
1347 if (tb
[NL80211_ATTR_MAC
] == NULL
)
1349 addr
= nla_data(tb
[NL80211_ATTR_MAC
]);
1350 wpa_printf(MSG_DEBUG
, "nl80211: Delete station " MACSTR
,
1353 if (is_ap_interface(drv
->nlmode
) && drv
->device_ap_sme
) {
1354 drv_event_disassoc(bss
->ctx
, addr
);
1358 if (drv
->nlmode
!= NL80211_IFTYPE_ADHOC
)
1361 os_memset(&data
, 0, sizeof(data
));
1362 os_memcpy(data
.ibss_peer_lost
.peer
, addr
, ETH_ALEN
);
1363 wpa_supplicant_event(bss
->ctx
, EVENT_IBSS_PEER_LOST
, &data
);
1367 static void nl80211_rekey_offload_event(struct wpa_driver_nl80211_data
*drv
,
1370 struct nlattr
*rekey_info
[NUM_NL80211_REKEY_DATA
];
1371 static struct nla_policy rekey_policy
[NUM_NL80211_REKEY_DATA
] = {
1372 [NL80211_REKEY_DATA_KEK
] = {
1373 .minlen
= NL80211_KEK_LEN
,
1374 .maxlen
= NL80211_KEK_LEN
,
1376 [NL80211_REKEY_DATA_KCK
] = {
1377 .minlen
= NL80211_KCK_LEN
,
1378 .maxlen
= NL80211_KCK_LEN
,
1380 [NL80211_REKEY_DATA_REPLAY_CTR
] = {
1381 .minlen
= NL80211_REPLAY_CTR_LEN
,
1382 .maxlen
= NL80211_REPLAY_CTR_LEN
,
1385 union wpa_event_data data
;
1387 if (!tb
[NL80211_ATTR_MAC
] ||
1388 !tb
[NL80211_ATTR_REKEY_DATA
] ||
1389 nla_parse_nested(rekey_info
, MAX_NL80211_REKEY_DATA
,
1390 tb
[NL80211_ATTR_REKEY_DATA
], rekey_policy
) ||
1391 !rekey_info
[NL80211_REKEY_DATA_REPLAY_CTR
])
1394 os_memset(&data
, 0, sizeof(data
));
1395 data
.driver_gtk_rekey
.bssid
= nla_data(tb
[NL80211_ATTR_MAC
]);
1396 wpa_printf(MSG_DEBUG
, "nl80211: Rekey offload event for BSSID " MACSTR
,
1397 MAC2STR(data
.driver_gtk_rekey
.bssid
));
1398 data
.driver_gtk_rekey
.replay_ctr
=
1399 nla_data(rekey_info
[NL80211_REKEY_DATA_REPLAY_CTR
]);
1400 wpa_hexdump(MSG_DEBUG
, "nl80211: Rekey offload - Replay Counter",
1401 data
.driver_gtk_rekey
.replay_ctr
, NL80211_REPLAY_CTR_LEN
);
1402 wpa_supplicant_event(drv
->ctx
, EVENT_DRIVER_GTK_REKEY
, &data
);
1406 static void nl80211_pmksa_candidate_event(struct wpa_driver_nl80211_data
*drv
,
1409 struct nlattr
*cand
[NUM_NL80211_PMKSA_CANDIDATE
];
1410 static struct nla_policy cand_policy
[NUM_NL80211_PMKSA_CANDIDATE
] = {
1411 [NL80211_PMKSA_CANDIDATE_INDEX
] = { .type
= NLA_U32
},
1412 [NL80211_PMKSA_CANDIDATE_BSSID
] = {
1416 [NL80211_PMKSA_CANDIDATE_PREAUTH
] = { .type
= NLA_FLAG
},
1418 union wpa_event_data data
;
1420 wpa_printf(MSG_DEBUG
, "nl80211: PMKSA candidate event");
1422 if (!tb
[NL80211_ATTR_PMKSA_CANDIDATE
] ||
1423 nla_parse_nested(cand
, MAX_NL80211_PMKSA_CANDIDATE
,
1424 tb
[NL80211_ATTR_PMKSA_CANDIDATE
], cand_policy
) ||
1425 !cand
[NL80211_PMKSA_CANDIDATE_INDEX
] ||
1426 !cand
[NL80211_PMKSA_CANDIDATE_BSSID
])
1429 os_memset(&data
, 0, sizeof(data
));
1430 os_memcpy(data
.pmkid_candidate
.bssid
,
1431 nla_data(cand
[NL80211_PMKSA_CANDIDATE_BSSID
]), ETH_ALEN
);
1432 data
.pmkid_candidate
.index
=
1433 nla_get_u32(cand
[NL80211_PMKSA_CANDIDATE_INDEX
]);
1434 data
.pmkid_candidate
.preauth
=
1435 cand
[NL80211_PMKSA_CANDIDATE_PREAUTH
] != NULL
;
1436 wpa_supplicant_event(drv
->ctx
, EVENT_PMKID_CANDIDATE
, &data
);
1440 static void nl80211_client_probe_event(struct wpa_driver_nl80211_data
*drv
,
1443 union wpa_event_data data
;
1447 addr
= nla_data(tb
[NL80211_ATTR_MAC
]);
1450 if (tb
[NL80211_ATTR_COOKIE
])
1451 cookie
= nla_get_u64(tb
[NL80211_ATTR_COOKIE
]);
1452 wpa_printf(MSG_DEBUG
, "nl80211: Probe client event (addr=" MACSTR
1453 " ack=%d cookie=%llu)", MAC2STR(addr
),
1454 tb
[NL80211_ATTR_ACK
] != NULL
,
1455 (long long unsigned int) cookie
);
1456 if (!tb
[NL80211_ATTR_ACK
])
1459 os_memset(&data
, 0, sizeof(data
));
1460 os_memcpy(data
.client_poll
.addr
, addr
, ETH_ALEN
);
1461 wpa_supplicant_event(drv
->ctx
, EVENT_DRIVER_CLIENT_POLL_OK
, &data
);
1465 static void nl80211_tdls_oper_event(struct wpa_driver_nl80211_data
*drv
,
1468 union wpa_event_data data
;
1470 wpa_printf(MSG_DEBUG
, "nl80211: TDLS operation event");
1472 if (!tb
[NL80211_ATTR_MAC
] || !tb
[NL80211_ATTR_TDLS_OPERATION
])
1475 os_memset(&data
, 0, sizeof(data
));
1476 os_memcpy(data
.tdls
.peer
, nla_data(tb
[NL80211_ATTR_MAC
]), ETH_ALEN
);
1477 switch (nla_get_u8(tb
[NL80211_ATTR_TDLS_OPERATION
])) {
1478 case NL80211_TDLS_SETUP
:
1479 wpa_printf(MSG_DEBUG
, "nl80211: TDLS setup request for peer "
1480 MACSTR
, MAC2STR(data
.tdls
.peer
));
1481 data
.tdls
.oper
= TDLS_REQUEST_SETUP
;
1483 case NL80211_TDLS_TEARDOWN
:
1484 wpa_printf(MSG_DEBUG
, "nl80211: TDLS teardown request for peer "
1485 MACSTR
, MAC2STR(data
.tdls
.peer
));
1486 data
.tdls
.oper
= TDLS_REQUEST_TEARDOWN
;
1488 case NL80211_TDLS_DISCOVERY_REQ
:
1489 wpa_printf(MSG_DEBUG
,
1490 "nl80211: TDLS discovery request for peer " MACSTR
,
1491 MAC2STR(data
.tdls
.peer
));
1492 data
.tdls
.oper
= TDLS_REQUEST_DISCOVER
;
1495 wpa_printf(MSG_DEBUG
, "nl80211: Unsupported TDLS operatione "
1499 if (tb
[NL80211_ATTR_REASON_CODE
]) {
1500 data
.tdls
.reason_code
=
1501 nla_get_u16(tb
[NL80211_ATTR_REASON_CODE
]);
1504 wpa_supplicant_event(drv
->ctx
, EVENT_TDLS
, &data
);
1508 static void nl80211_stop_ap(struct wpa_driver_nl80211_data
*drv
,
1511 wpa_supplicant_event(drv
->ctx
, EVENT_INTERFACE_UNAVAILABLE
, NULL
);
1515 static void nl80211_connect_failed_event(struct wpa_driver_nl80211_data
*drv
,
1518 union wpa_event_data data
;
1521 wpa_printf(MSG_DEBUG
, "nl80211: Connect failed event");
1523 if (!tb
[NL80211_ATTR_MAC
] || !tb
[NL80211_ATTR_CONN_FAILED_REASON
])
1526 os_memset(&data
, 0, sizeof(data
));
1527 os_memcpy(data
.connect_failed_reason
.addr
,
1528 nla_data(tb
[NL80211_ATTR_MAC
]), ETH_ALEN
);
1530 reason
= nla_get_u32(tb
[NL80211_ATTR_CONN_FAILED_REASON
]);
1532 case NL80211_CONN_FAIL_MAX_CLIENTS
:
1533 wpa_printf(MSG_DEBUG
, "nl80211: Max client reached");
1534 data
.connect_failed_reason
.code
= MAX_CLIENT_REACHED
;
1536 case NL80211_CONN_FAIL_BLOCKED_CLIENT
:
1537 wpa_printf(MSG_DEBUG
, "nl80211: Blocked client " MACSTR
1538 " tried to connect",
1539 MAC2STR(data
.connect_failed_reason
.addr
));
1540 data
.connect_failed_reason
.code
= BLOCKED_CLIENT
;
1543 wpa_printf(MSG_DEBUG
, "nl8021l: Unknown connect failed reason "
1548 wpa_supplicant_event(drv
->ctx
, EVENT_CONNECT_FAILED_REASON
, &data
);
1552 static void nl80211_radar_event(struct wpa_driver_nl80211_data
*drv
,
1555 union wpa_event_data data
;
1556 enum nl80211_radar_event event_type
;
1558 if (!tb
[NL80211_ATTR_WIPHY_FREQ
] || !tb
[NL80211_ATTR_RADAR_EVENT
])
1561 os_memset(&data
, 0, sizeof(data
));
1562 data
.dfs_event
.freq
= nla_get_u32(tb
[NL80211_ATTR_WIPHY_FREQ
]);
1563 event_type
= nla_get_u32(tb
[NL80211_ATTR_RADAR_EVENT
]);
1565 /* Check HT params */
1566 if (tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
]) {
1567 data
.dfs_event
.ht_enabled
= 1;
1568 data
.dfs_event
.chan_offset
= 0;
1570 switch (nla_get_u32(tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
])) {
1571 case NL80211_CHAN_NO_HT
:
1572 data
.dfs_event
.ht_enabled
= 0;
1574 case NL80211_CHAN_HT20
:
1576 case NL80211_CHAN_HT40PLUS
:
1577 data
.dfs_event
.chan_offset
= 1;
1579 case NL80211_CHAN_HT40MINUS
:
1580 data
.dfs_event
.chan_offset
= -1;
1585 /* Get VHT params */
1586 if (tb
[NL80211_ATTR_CHANNEL_WIDTH
])
1587 data
.dfs_event
.chan_width
=
1588 convert2width(nla_get_u32(
1589 tb
[NL80211_ATTR_CHANNEL_WIDTH
]));
1590 if (tb
[NL80211_ATTR_CENTER_FREQ1
])
1591 data
.dfs_event
.cf1
= nla_get_u32(tb
[NL80211_ATTR_CENTER_FREQ1
]);
1592 if (tb
[NL80211_ATTR_CENTER_FREQ2
])
1593 data
.dfs_event
.cf2
= nla_get_u32(tb
[NL80211_ATTR_CENTER_FREQ2
]);
1595 wpa_printf(MSG_DEBUG
, "nl80211: DFS event on freq %d MHz, ht: %d, offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz",
1596 data
.dfs_event
.freq
, data
.dfs_event
.ht_enabled
,
1597 data
.dfs_event
.chan_offset
, data
.dfs_event
.chan_width
,
1598 data
.dfs_event
.cf1
, data
.dfs_event
.cf2
);
1600 switch (event_type
) {
1601 case NL80211_RADAR_DETECTED
:
1602 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_RADAR_DETECTED
, &data
);
1604 case NL80211_RADAR_CAC_FINISHED
:
1605 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_CAC_FINISHED
, &data
);
1607 case NL80211_RADAR_CAC_ABORTED
:
1608 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_CAC_ABORTED
, &data
);
1610 case NL80211_RADAR_NOP_FINISHED
:
1611 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_NOP_FINISHED
, &data
);
1613 case NL80211_RADAR_PRE_CAC_EXPIRED
:
1614 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_PRE_CAC_EXPIRED
,
1617 case NL80211_RADAR_CAC_STARTED
:
1618 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_CAC_STARTED
, &data
);
1621 wpa_printf(MSG_DEBUG
, "nl80211: Unknown radar event %d "
1622 "received", event_type
);
1628 static void nl80211_spurious_frame(struct i802_bss
*bss
, struct nlattr
**tb
,
1631 struct wpa_driver_nl80211_data
*drv
= bss
->drv
;
1632 union wpa_event_data event
;
1634 if (!tb
[NL80211_ATTR_MAC
])
1637 os_memset(&event
, 0, sizeof(event
));
1638 event
.rx_from_unknown
.bssid
= bss
->addr
;
1639 event
.rx_from_unknown
.addr
= nla_data(tb
[NL80211_ATTR_MAC
]);
1640 event
.rx_from_unknown
.wds
= wds
;
1642 wpa_supplicant_event(drv
->ctx
, EVENT_RX_FROM_UNKNOWN
, &event
);
1646 #ifdef CONFIG_DRIVER_NL80211_QCA
1648 static void qca_nl80211_avoid_freq(struct wpa_driver_nl80211_data
*drv
,
1649 const u8
*data
, size_t len
)
1652 union wpa_event_data event
;
1653 struct wpa_freq_range
*range
= NULL
;
1654 const struct qca_avoid_freq_list
*freq_range
;
1656 freq_range
= (const struct qca_avoid_freq_list
*) data
;
1657 if (len
< sizeof(freq_range
->count
))
1660 count
= freq_range
->count
;
1661 if (len
< sizeof(freq_range
->count
) +
1662 count
* sizeof(struct qca_avoid_freq_range
)) {
1663 wpa_printf(MSG_DEBUG
, "nl80211: Ignored too short avoid frequency list (len=%u)",
1664 (unsigned int) len
);
1669 range
= os_calloc(count
, sizeof(struct wpa_freq_range
));
1674 os_memset(&event
, 0, sizeof(event
));
1675 for (i
= 0; i
< count
; i
++) {
1676 unsigned int idx
= event
.freq_range
.num
;
1677 range
[idx
].min
= freq_range
->range
[i
].start_freq
;
1678 range
[idx
].max
= freq_range
->range
[i
].end_freq
;
1679 wpa_printf(MSG_DEBUG
, "nl80211: Avoid frequency range: %u-%u",
1680 range
[idx
].min
, range
[idx
].max
);
1681 if (range
[idx
].min
> range
[idx
].max
) {
1682 wpa_printf(MSG_DEBUG
, "nl80211: Ignore invalid frequency range");
1685 event
.freq_range
.num
++;
1687 event
.freq_range
.range
= range
;
1689 wpa_supplicant_event(drv
->ctx
, EVENT_AVOID_FREQUENCIES
, &event
);
1695 static enum hostapd_hw_mode
get_qca_hw_mode(u8 hw_mode
)
1698 case QCA_ACS_MODE_IEEE80211B
:
1699 return HOSTAPD_MODE_IEEE80211B
;
1700 case QCA_ACS_MODE_IEEE80211G
:
1701 return HOSTAPD_MODE_IEEE80211G
;
1702 case QCA_ACS_MODE_IEEE80211A
:
1703 return HOSTAPD_MODE_IEEE80211A
;
1704 case QCA_ACS_MODE_IEEE80211AD
:
1705 return HOSTAPD_MODE_IEEE80211AD
;
1706 case QCA_ACS_MODE_IEEE80211ANY
:
1707 return HOSTAPD_MODE_IEEE80211ANY
;
1709 return NUM_HOSTAPD_MODES
;
1714 static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data
*drv
,
1715 const u8
*data
, size_t len
)
1717 struct nlattr
*tb
[QCA_WLAN_VENDOR_ATTR_ACS_MAX
+ 1];
1718 union wpa_event_data event
;
1720 wpa_printf(MSG_DEBUG
,
1721 "nl80211: ACS channel selection vendor event received");
1723 if (nla_parse(tb
, QCA_WLAN_VENDOR_ATTR_ACS_MAX
,
1724 (struct nlattr
*) data
, len
, NULL
) ||
1725 !tb
[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL
] ||
1726 !tb
[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL
])
1729 os_memset(&event
, 0, sizeof(event
));
1730 event
.acs_selected_channels
.pri_channel
=
1731 nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL
]);
1732 event
.acs_selected_channels
.sec_channel
=
1733 nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL
]);
1734 if (tb
[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL
])
1735 event
.acs_selected_channels
.vht_seg0_center_ch
=
1736 nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL
]);
1737 if (tb
[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL
])
1738 event
.acs_selected_channels
.vht_seg1_center_ch
=
1739 nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL
]);
1740 if (tb
[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH
])
1741 event
.acs_selected_channels
.ch_width
=
1742 nla_get_u16(tb
[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH
]);
1743 if (tb
[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE
]) {
1744 u8 hw_mode
= nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE
]);
1746 event
.acs_selected_channels
.hw_mode
= get_qca_hw_mode(hw_mode
);
1747 if (event
.acs_selected_channels
.hw_mode
== NUM_HOSTAPD_MODES
||
1748 event
.acs_selected_channels
.hw_mode
==
1749 HOSTAPD_MODE_IEEE80211ANY
) {
1750 wpa_printf(MSG_DEBUG
,
1751 "nl80211: Invalid hw_mode %d in ACS selection event",
1757 wpa_printf(MSG_INFO
,
1758 "nl80211: ACS Results: PCH: %d SCH: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d",
1759 event
.acs_selected_channels
.pri_channel
,
1760 event
.acs_selected_channels
.sec_channel
,
1761 event
.acs_selected_channels
.ch_width
,
1762 event
.acs_selected_channels
.vht_seg0_center_ch
,
1763 event
.acs_selected_channels
.vht_seg1_center_ch
,
1764 event
.acs_selected_channels
.hw_mode
);
1766 /* Ignore ACS channel list check for backwards compatibility */
1768 wpa_supplicant_event(drv
->ctx
, EVENT_ACS_CHANNEL_SELECTED
, &event
);
1772 static void qca_nl80211_key_mgmt_auth(struct wpa_driver_nl80211_data
*drv
,
1773 const u8
*data
, size_t len
)
1775 struct nlattr
*tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX
+ 1];
1778 wpa_printf(MSG_DEBUG
,
1779 "nl80211: Key management roam+auth vendor event received");
1781 if (nla_parse(tb
, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX
,
1782 (struct nlattr
*) data
, len
, NULL
) ||
1783 !tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID
] ||
1784 nla_len(tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID
]) != ETH_ALEN
||
1785 !tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE
] ||
1786 !tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE
] ||
1787 !tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED
])
1790 bssid
= nla_data(tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID
]);
1791 wpa_printf(MSG_DEBUG
, " * roam BSSID " MACSTR
, MAC2STR(bssid
));
1793 mlme_event_connect(drv
, NL80211_CMD_ROAM
, NULL
,
1794 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID
],
1795 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE
],
1796 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE
],
1798 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED
],
1799 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR
],
1800 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK
],
1801 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK
],
1802 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS
],
1803 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM
],
1804 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK
],
1805 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID
]);
1809 static void qca_nl80211_dfs_offload_radar_event(
1810 struct wpa_driver_nl80211_data
*drv
, u32 subcmd
, u8
*msg
, int length
)
1812 union wpa_event_data data
;
1813 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
1815 wpa_printf(MSG_DEBUG
,
1816 "nl80211: DFS offload radar vendor event received");
1818 if (nla_parse(tb
, NL80211_ATTR_MAX
,
1819 (struct nlattr
*) msg
, length
, NULL
))
1822 if (!tb
[NL80211_ATTR_WIPHY_FREQ
]) {
1823 wpa_printf(MSG_INFO
,
1824 "nl80211: Error parsing WIPHY_FREQ in FS offload radar vendor event");
1828 os_memset(&data
, 0, sizeof(data
));
1829 data
.dfs_event
.freq
= nla_get_u32(tb
[NL80211_ATTR_WIPHY_FREQ
]);
1831 wpa_printf(MSG_DEBUG
, "nl80211: DFS event on freq %d MHz",
1832 data
.dfs_event
.freq
);
1834 /* Check HT params */
1835 if (tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
]) {
1836 data
.dfs_event
.ht_enabled
= 1;
1837 data
.dfs_event
.chan_offset
= 0;
1839 switch (nla_get_u32(tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
])) {
1840 case NL80211_CHAN_NO_HT
:
1841 data
.dfs_event
.ht_enabled
= 0;
1843 case NL80211_CHAN_HT20
:
1845 case NL80211_CHAN_HT40PLUS
:
1846 data
.dfs_event
.chan_offset
= 1;
1848 case NL80211_CHAN_HT40MINUS
:
1849 data
.dfs_event
.chan_offset
= -1;
1854 /* Get VHT params */
1855 if (tb
[NL80211_ATTR_CHANNEL_WIDTH
])
1856 data
.dfs_event
.chan_width
=
1857 convert2width(nla_get_u32(
1858 tb
[NL80211_ATTR_CHANNEL_WIDTH
]));
1859 if (tb
[NL80211_ATTR_CENTER_FREQ1
])
1860 data
.dfs_event
.cf1
= nla_get_u32(tb
[NL80211_ATTR_CENTER_FREQ1
]);
1861 if (tb
[NL80211_ATTR_CENTER_FREQ2
])
1862 data
.dfs_event
.cf2
= nla_get_u32(tb
[NL80211_ATTR_CENTER_FREQ2
]);
1864 wpa_printf(MSG_DEBUG
, "nl80211: DFS event on freq %d MHz, ht: %d, "
1865 "offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz",
1866 data
.dfs_event
.freq
, data
.dfs_event
.ht_enabled
,
1867 data
.dfs_event
.chan_offset
, data
.dfs_event
.chan_width
,
1868 data
.dfs_event
.cf1
, data
.dfs_event
.cf2
);
1871 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
:
1872 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_RADAR_DETECTED
, &data
);
1874 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
:
1875 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_CAC_STARTED
, &data
);
1877 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
:
1878 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_CAC_FINISHED
, &data
);
1880 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
:
1881 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_CAC_ABORTED
, &data
);
1883 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
:
1884 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_NOP_FINISHED
, &data
);
1887 wpa_printf(MSG_DEBUG
,
1888 "nl80211: Unknown DFS offload radar event %d received",
1895 static void qca_nl80211_scan_trigger_event(struct wpa_driver_nl80211_data
*drv
,
1896 u8
*data
, size_t len
)
1898 struct nlattr
*tb
[QCA_WLAN_VENDOR_ATTR_SCAN_MAX
+ 1];
1900 union wpa_event_data event
;
1901 struct scan_info
*info
;
1903 if (nla_parse(tb
, QCA_WLAN_VENDOR_ATTR_SCAN_MAX
,
1904 (struct nlattr
*) data
, len
, NULL
) ||
1905 !tb
[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE
])
1908 cookie
= nla_get_u64(tb
[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE
]);
1909 if (cookie
!= drv
->vendor_scan_cookie
) {
1910 /* External scan trigger event, ignore */
1914 /* Cookie match, own scan */
1915 os_memset(&event
, 0, sizeof(event
));
1916 info
= &event
.scan_info
;
1917 info
->external_scan
= 0;
1918 info
->nl_scan_event
= 0;
1920 drv
->scan_state
= SCAN_STARTED
;
1921 wpa_supplicant_event(drv
->ctx
, EVENT_SCAN_STARTED
, &event
);
1925 static void send_vendor_scan_event(struct wpa_driver_nl80211_data
*drv
,
1926 int aborted
, struct nlattr
*tb
[],
1929 union wpa_event_data event
;
1932 struct scan_info
*info
;
1933 int freqs
[MAX_REPORT_FREQS
];
1936 os_memset(&event
, 0, sizeof(event
));
1937 info
= &event
.scan_info
;
1938 info
->aborted
= aborted
;
1939 info
->external_scan
= external_scan
;
1941 if (tb
[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS
]) {
1942 nla_for_each_nested(nl
,
1943 tb
[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS
], rem
) {
1944 struct wpa_driver_scan_ssid
*s
=
1945 &info
->ssids
[info
->num_ssids
];
1946 s
->ssid
= nla_data(nl
);
1947 s
->ssid_len
= nla_len(nl
);
1948 wpa_printf(MSG_DEBUG
,
1949 "nl80211: Scan probed for SSID '%s'",
1950 wpa_ssid_txt(s
->ssid
, s
->ssid_len
));
1952 if (info
->num_ssids
== WPAS_MAX_SCAN_SSIDS
)
1957 if (tb
[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES
]) {
1958 char msg
[300], *pos
, *end
;
1962 end
= pos
+ sizeof(msg
);
1965 nla_for_each_nested(nl
,
1966 tb
[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES
],
1968 freqs
[num_freqs
] = nla_get_u32(nl
);
1969 res
= os_snprintf(pos
, end
- pos
, " %d",
1971 if (!os_snprintf_error(end
- pos
, res
))
1974 if (num_freqs
== MAX_REPORT_FREQS
- 1)
1978 info
->freqs
= freqs
;
1979 info
->num_freqs
= num_freqs
;
1980 wpa_printf(MSG_DEBUG
, "nl80211: Scan included frequencies:%s",
1983 wpa_supplicant_event(drv
->ctx
, EVENT_SCAN_RESULTS
, &event
);
1987 static void qca_nl80211_scan_done_event(struct wpa_driver_nl80211_data
*drv
,
1988 u8
*data
, size_t len
)
1990 struct nlattr
*tb
[QCA_WLAN_VENDOR_ATTR_SCAN_MAX
+ 1];
1992 enum scan_status status
;
1995 if (nla_parse(tb
, QCA_WLAN_VENDOR_ATTR_SCAN_MAX
,
1996 (struct nlattr
*) data
, len
, NULL
) ||
1997 !tb
[QCA_WLAN_VENDOR_ATTR_SCAN_STATUS
] ||
1998 !tb
[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE
])
2001 status
= nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_SCAN_STATUS
]);
2002 if (status
>= VENDOR_SCAN_STATUS_MAX
)
2003 return; /* invalid status */
2005 cookie
= nla_get_u64(tb
[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE
]);
2006 if (cookie
!= drv
->vendor_scan_cookie
) {
2007 /* Event from an external scan, get scan results */
2011 if (status
== VENDOR_SCAN_STATUS_NEW_RESULTS
)
2012 drv
->scan_state
= SCAN_COMPLETED
;
2014 drv
->scan_state
= SCAN_ABORTED
;
2016 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout
, drv
,
2018 drv
->vendor_scan_cookie
= 0;
2019 drv
->last_scan_cmd
= 0;
2022 send_vendor_scan_event(drv
, (status
== VENDOR_SCAN_STATUS_ABORTED
), tb
,
2027 static void qca_nl80211_p2p_lo_stop_event(struct wpa_driver_nl80211_data
*drv
,
2028 u8
*data
, size_t len
)
2030 struct nlattr
*tb
[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX
+ 1];
2031 union wpa_event_data event
;
2033 wpa_printf(MSG_DEBUG
,
2034 "nl80211: P2P listen offload stop vendor event received");
2036 if (nla_parse(tb
, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX
,
2037 (struct nlattr
*) data
, len
, NULL
) ||
2038 !tb
[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON
])
2041 os_memset(&event
, 0, sizeof(event
));
2042 event
.p2p_lo_stop
.reason_code
=
2043 nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON
]);
2045 wpa_printf(MSG_DEBUG
,
2046 "nl80211: P2P Listen offload stop reason: %d",
2047 event
.p2p_lo_stop
.reason_code
);
2048 wpa_supplicant_event(drv
->ctx
, EVENT_P2P_LO_STOP
, &event
);
2051 #endif /* CONFIG_DRIVER_NL80211_QCA */
2054 static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data
*drv
,
2055 u32 subcmd
, u8
*data
, size_t len
)
2058 case QCA_NL80211_VENDOR_SUBCMD_TEST
:
2059 wpa_hexdump(MSG_DEBUG
, "nl80211: QCA test event", data
, len
);
2061 #ifdef CONFIG_DRIVER_NL80211_QCA
2062 case QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
:
2063 qca_nl80211_avoid_freq(drv
, data
, len
);
2065 case QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
:
2066 qca_nl80211_key_mgmt_auth(drv
, data
, len
);
2068 case QCA_NL80211_VENDOR_SUBCMD_DO_ACS
:
2069 qca_nl80211_acs_select_ch(drv
, data
, len
);
2071 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
:
2072 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
:
2073 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
:
2074 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
:
2075 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
:
2076 qca_nl80211_dfs_offload_radar_event(drv
, subcmd
, data
, len
);
2078 case QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
:
2079 qca_nl80211_scan_trigger_event(drv
, data
, len
);
2081 case QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
:
2082 qca_nl80211_scan_done_event(drv
, data
, len
);
2084 case QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
:
2085 qca_nl80211_p2p_lo_stop_event(drv
, data
, len
);
2087 #endif /* CONFIG_DRIVER_NL80211_QCA */
2089 wpa_printf(MSG_DEBUG
,
2090 "nl80211: Ignore unsupported QCA vendor event %u",
2097 static void nl80211_vendor_event(struct wpa_driver_nl80211_data
*drv
,
2100 u32 vendor_id
, subcmd
, wiphy
= 0;
2105 if (!tb
[NL80211_ATTR_VENDOR_ID
] ||
2106 !tb
[NL80211_ATTR_VENDOR_SUBCMD
])
2109 vendor_id
= nla_get_u32(tb
[NL80211_ATTR_VENDOR_ID
]);
2110 subcmd
= nla_get_u32(tb
[NL80211_ATTR_VENDOR_SUBCMD
]);
2112 if (tb
[NL80211_ATTR_WIPHY
])
2113 wiphy
= nla_get_u32(tb
[NL80211_ATTR_WIPHY
]);
2115 wpa_printf(MSG_DEBUG
, "nl80211: Vendor event: wiphy=%u vendor_id=0x%x subcmd=%u",
2116 wiphy
, vendor_id
, subcmd
);
2118 if (tb
[NL80211_ATTR_VENDOR_DATA
]) {
2119 data
= nla_data(tb
[NL80211_ATTR_VENDOR_DATA
]);
2120 len
= nla_len(tb
[NL80211_ATTR_VENDOR_DATA
]);
2121 wpa_hexdump(MSG_MSGDUMP
, "nl80211: Vendor data", data
, len
);
2124 wiphy_idx
= nl80211_get_wiphy_index(drv
->first_bss
);
2125 if (wiphy_idx
>= 0 && wiphy_idx
!= (int) wiphy
) {
2126 wpa_printf(MSG_DEBUG
, "nl80211: Ignore vendor event for foreign wiphy %u (own: %d)",
2131 switch (vendor_id
) {
2133 nl80211_vendor_event_qca(drv
, subcmd
, data
, len
);
2136 wpa_printf(MSG_DEBUG
, "nl80211: Ignore unsupported vendor event");
2142 static void nl80211_reg_change_event(struct wpa_driver_nl80211_data
*drv
,
2143 struct nlattr
*tb
[])
2145 union wpa_event_data data
;
2146 enum nl80211_reg_initiator init
;
2148 wpa_printf(MSG_DEBUG
, "nl80211: Regulatory domain change");
2150 if (tb
[NL80211_ATTR_REG_INITIATOR
] == NULL
)
2153 os_memset(&data
, 0, sizeof(data
));
2154 init
= nla_get_u8(tb
[NL80211_ATTR_REG_INITIATOR
]);
2155 wpa_printf(MSG_DEBUG
, " * initiator=%d", init
);
2157 case NL80211_REGDOM_SET_BY_CORE
:
2158 data
.channel_list_changed
.initiator
= REGDOM_SET_BY_CORE
;
2160 case NL80211_REGDOM_SET_BY_USER
:
2161 data
.channel_list_changed
.initiator
= REGDOM_SET_BY_USER
;
2163 case NL80211_REGDOM_SET_BY_DRIVER
:
2164 data
.channel_list_changed
.initiator
= REGDOM_SET_BY_DRIVER
;
2166 case NL80211_REGDOM_SET_BY_COUNTRY_IE
:
2167 data
.channel_list_changed
.initiator
= REGDOM_SET_BY_COUNTRY_IE
;
2171 if (tb
[NL80211_ATTR_REG_TYPE
]) {
2172 enum nl80211_reg_type type
;
2173 type
= nla_get_u8(tb
[NL80211_ATTR_REG_TYPE
]);
2174 wpa_printf(MSG_DEBUG
, " * type=%d", type
);
2176 case NL80211_REGDOM_TYPE_COUNTRY
:
2177 data
.channel_list_changed
.type
= REGDOM_TYPE_COUNTRY
;
2179 case NL80211_REGDOM_TYPE_WORLD
:
2180 data
.channel_list_changed
.type
= REGDOM_TYPE_WORLD
;
2182 case NL80211_REGDOM_TYPE_CUSTOM_WORLD
:
2183 data
.channel_list_changed
.type
=
2184 REGDOM_TYPE_CUSTOM_WORLD
;
2186 case NL80211_REGDOM_TYPE_INTERSECTION
:
2187 data
.channel_list_changed
.type
=
2188 REGDOM_TYPE_INTERSECTION
;
2193 if (tb
[NL80211_ATTR_REG_ALPHA2
]) {
2194 os_strlcpy(data
.channel_list_changed
.alpha2
,
2195 nla_get_string(tb
[NL80211_ATTR_REG_ALPHA2
]),
2196 sizeof(data
.channel_list_changed
.alpha2
));
2197 wpa_printf(MSG_DEBUG
, " * alpha2=%s",
2198 data
.channel_list_changed
.alpha2
);
2201 wpa_supplicant_event(drv
->ctx
, EVENT_CHANNEL_LIST_CHANGED
, &data
);
2205 static void nl80211_dump_freq(const char *title
, struct nlattr
*nl_freq
)
2207 static struct nla_policy freq_policy
[NL80211_FREQUENCY_ATTR_MAX
+ 1] = {
2208 [NL80211_FREQUENCY_ATTR_FREQ
] = { .type
= NLA_U32
},
2209 [NL80211_FREQUENCY_ATTR_DISABLED
] = { .type
= NLA_FLAG
},
2210 [NL80211_FREQUENCY_ATTR_NO_IR
] = { .type
= NLA_FLAG
},
2211 [NL80211_FREQUENCY_ATTR_RADAR
] = { .type
= NLA_FLAG
},
2212 [NL80211_FREQUENCY_ATTR_MAX_TX_POWER
] = { .type
= NLA_U32
},
2214 struct nlattr
*tb
[NL80211_FREQUENCY_ATTR_MAX
+ 1];
2215 u32 freq
= 0, max_tx_power
= 0;
2217 nla_parse(tb
, NL80211_FREQUENCY_ATTR_MAX
,
2218 nla_data(nl_freq
), nla_len(nl_freq
), freq_policy
);
2220 if (tb
[NL80211_FREQUENCY_ATTR_FREQ
])
2221 freq
= nla_get_u32(tb
[NL80211_FREQUENCY_ATTR_FREQ
]);
2222 if (tb
[NL80211_FREQUENCY_ATTR_MAX_TX_POWER
])
2224 nla_get_u32(tb
[NL80211_FREQUENCY_ATTR_MAX_TX_POWER
]);
2226 wpa_printf(MSG_DEBUG
,
2227 "nl80211: Channel (%s): freq=%u max_tx_power=%u%s%s%s",
2228 title
, freq
, max_tx_power
,
2229 tb
[NL80211_FREQUENCY_ATTR_DISABLED
] ? " disabled" : "",
2230 tb
[NL80211_FREQUENCY_ATTR_NO_IR
] ? " no-IR" : "",
2231 tb
[NL80211_FREQUENCY_ATTR_RADAR
] ? " radar" : "");
2235 static void nl80211_reg_beacon_hint_event(struct wpa_driver_nl80211_data
*drv
,
2236 struct nlattr
*tb
[])
2238 union wpa_event_data data
;
2240 wpa_printf(MSG_DEBUG
, "nl80211: Regulatory beacon hint");
2241 os_memset(&data
, 0, sizeof(data
));
2242 data
.channel_list_changed
.initiator
= REGDOM_BEACON_HINT
;
2244 if (tb
[NL80211_ATTR_FREQ_BEFORE
])
2245 nl80211_dump_freq("before", tb
[NL80211_ATTR_FREQ_BEFORE
]);
2246 if (tb
[NL80211_ATTR_FREQ_AFTER
])
2247 nl80211_dump_freq("after", tb
[NL80211_ATTR_FREQ_AFTER
]);
2249 wpa_supplicant_event(drv
->ctx
, EVENT_CHANNEL_LIST_CHANGED
, &data
);
2253 static void nl80211_external_auth(struct wpa_driver_nl80211_data
*drv
,
2256 union wpa_event_data event
;
2257 enum nl80211_external_auth_action act
;
2259 if (!tb
[NL80211_ATTR_AKM_SUITES
] ||
2260 !tb
[NL80211_ATTR_EXTERNAL_AUTH_ACTION
] ||
2261 !tb
[NL80211_ATTR_BSSID
] ||
2262 !tb
[NL80211_ATTR_SSID
])
2265 os_memset(&event
, 0, sizeof(event
));
2266 act
= nla_get_u32(tb
[NL80211_ATTR_EXTERNAL_AUTH_ACTION
]);
2268 case NL80211_EXTERNAL_AUTH_START
:
2269 event
.external_auth
.action
= EXT_AUTH_START
;
2271 case NL80211_EXTERNAL_AUTH_ABORT
:
2272 event
.external_auth
.action
= EXT_AUTH_ABORT
;
2278 event
.external_auth
.key_mgmt_suite
=
2279 nla_get_u32(tb
[NL80211_ATTR_AKM_SUITES
]);
2281 event
.external_auth
.ssid_len
= nla_len(tb
[NL80211_ATTR_SSID
]);
2282 if (event
.external_auth
.ssid_len
> SSID_MAX_LEN
)
2284 event
.external_auth
.ssid
= nla_data(tb
[NL80211_ATTR_SSID
]);
2286 event
.external_auth
.bssid
= nla_data(tb
[NL80211_ATTR_BSSID
]);
2288 wpa_printf(MSG_DEBUG
,
2289 "nl80211: External auth action: %u, AKM: 0x%x",
2290 event
.external_auth
.action
,
2291 event
.external_auth
.key_mgmt_suite
);
2292 wpa_supplicant_event(drv
->ctx
, EVENT_EXTERNAL_AUTH
, &event
);
2296 static void nl80211_port_authorized(struct wpa_driver_nl80211_data
*drv
,
2301 if (!tb
[NL80211_ATTR_MAC
] ||
2302 nla_len(tb
[NL80211_ATTR_MAC
]) != ETH_ALEN
) {
2303 wpa_printf(MSG_DEBUG
,
2304 "nl80211: Ignore port authorized event without BSSID");
2308 addr
= nla_data(tb
[NL80211_ATTR_MAC
]);
2309 if (os_memcmp(addr
, drv
->bssid
, ETH_ALEN
) != 0) {
2310 wpa_printf(MSG_DEBUG
,
2311 "nl80211: Ignore port authorized event for " MACSTR
2312 " (not the currently connected BSSID " MACSTR
")",
2313 MAC2STR(addr
), MAC2STR(drv
->bssid
));
2317 wpa_supplicant_event(drv
->ctx
, EVENT_PORT_AUTHORIZED
, NULL
);
2321 static void nl80211_sta_opmode_change_event(struct wpa_driver_nl80211_data
*drv
,
2324 union wpa_event_data ed
;
2325 u8 smps_mode
, max_bw
;
2327 if (!tb
[NL80211_ATTR_MAC
] ||
2328 (!tb
[NL80211_ATTR_CHANNEL_WIDTH
] &&
2329 !tb
[NL80211_ATTR_SMPS_MODE
] &&
2330 !tb
[NL80211_ATTR_NSS
]))
2333 ed
.sta_opmode
.smps_mode
= SMPS_INVALID
;
2334 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_UNKNOWN
;
2335 ed
.sta_opmode
.rx_nss
= 0xff;
2336 ed
.sta_opmode
.addr
= nla_data(tb
[NL80211_ATTR_MAC
]);
2338 if (tb
[NL80211_ATTR_SMPS_MODE
]) {
2339 smps_mode
= nla_get_u8(tb
[NL80211_ATTR_SMPS_MODE
]);
2340 switch (smps_mode
) {
2341 case NL80211_SMPS_OFF
:
2342 ed
.sta_opmode
.smps_mode
= SMPS_OFF
;
2344 case NL80211_SMPS_STATIC
:
2345 ed
.sta_opmode
.smps_mode
= SMPS_STATIC
;
2347 case NL80211_SMPS_DYNAMIC
:
2348 ed
.sta_opmode
.smps_mode
= SMPS_DYNAMIC
;
2351 ed
.sta_opmode
.smps_mode
= SMPS_INVALID
;
2356 if (tb
[NL80211_ATTR_CHANNEL_WIDTH
]) {
2357 max_bw
= nla_get_u32(tb
[NL80211_ATTR_CHANNEL_WIDTH
]);
2359 case NL80211_CHAN_WIDTH_20_NOHT
:
2360 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_20_NOHT
;
2362 case NL80211_CHAN_WIDTH_20
:
2363 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_20
;
2365 case NL80211_CHAN_WIDTH_40
:
2366 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_40
;
2368 case NL80211_CHAN_WIDTH_80
:
2369 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_80
;
2371 case NL80211_CHAN_WIDTH_80P80
:
2372 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_80P80
;
2374 case NL80211_CHAN_WIDTH_160
:
2375 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_160
;
2378 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_UNKNOWN
;
2384 if (tb
[NL80211_ATTR_NSS
])
2385 ed
.sta_opmode
.rx_nss
= nla_get_u8(tb
[NL80211_ATTR_NSS
]);
2387 wpa_supplicant_event(drv
->ctx
, EVENT_STATION_OPMODE_CHANGED
, &ed
);
2391 static void do_process_drv_event(struct i802_bss
*bss
, int cmd
,
2394 struct wpa_driver_nl80211_data
*drv
= bss
->drv
;
2395 int external_scan_event
= 0;
2397 wpa_printf(MSG_DEBUG
, "nl80211: Drv Event %d (%s) received for %s",
2398 cmd
, nl80211_command_to_string(cmd
), bss
->ifname
);
2400 if (cmd
== NL80211_CMD_ROAM
&&
2401 (drv
->capa
.flags
& WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD
)) {
2403 * Device will use roam+auth vendor event to indicate
2404 * roaming, so ignore the regular roam event.
2406 wpa_printf(MSG_DEBUG
,
2407 "nl80211: Ignore roam event (cmd=%d), device will use vendor event roam+auth",
2412 if (drv
->ap_scan_as_station
!= NL80211_IFTYPE_UNSPECIFIED
&&
2413 (cmd
== NL80211_CMD_NEW_SCAN_RESULTS
||
2414 cmd
== NL80211_CMD_SCAN_ABORTED
)) {
2415 wpa_driver_nl80211_set_mode(drv
->first_bss
,
2416 drv
->ap_scan_as_station
);
2417 drv
->ap_scan_as_station
= NL80211_IFTYPE_UNSPECIFIED
;
2421 case NL80211_CMD_TRIGGER_SCAN
:
2422 wpa_dbg(drv
->ctx
, MSG_DEBUG
, "nl80211: Scan trigger");
2423 drv
->scan_state
= SCAN_STARTED
;
2424 if (drv
->scan_for_auth
) {
2426 * Cannot indicate EVENT_SCAN_STARTED here since we skip
2427 * EVENT_SCAN_RESULTS in scan_for_auth case and the
2428 * upper layer implementation could get confused about
2431 wpa_printf(MSG_DEBUG
, "nl80211: Do not indicate scan-start event due to internal scan_for_auth");
2434 wpa_supplicant_event(drv
->ctx
, EVENT_SCAN_STARTED
, NULL
);
2436 case NL80211_CMD_START_SCHED_SCAN
:
2437 wpa_dbg(drv
->ctx
, MSG_DEBUG
, "nl80211: Sched scan started");
2438 drv
->scan_state
= SCHED_SCAN_STARTED
;
2440 case NL80211_CMD_SCHED_SCAN_STOPPED
:
2441 wpa_dbg(drv
->ctx
, MSG_DEBUG
, "nl80211: Sched scan stopped");
2442 drv
->scan_state
= SCHED_SCAN_STOPPED
;
2443 wpa_supplicant_event(drv
->ctx
, EVENT_SCHED_SCAN_STOPPED
, NULL
);
2445 case NL80211_CMD_NEW_SCAN_RESULTS
:
2446 wpa_dbg(drv
->ctx
, MSG_DEBUG
,
2447 "nl80211: New scan results available");
2448 if (drv
->last_scan_cmd
!= NL80211_CMD_VENDOR
)
2449 drv
->scan_state
= SCAN_COMPLETED
;
2450 drv
->scan_complete_events
= 1;
2451 if (drv
->last_scan_cmd
== NL80211_CMD_TRIGGER_SCAN
) {
2452 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout
,
2454 drv
->last_scan_cmd
= 0;
2456 external_scan_event
= 1;
2458 send_scan_event(drv
, 0, tb
, external_scan_event
);
2460 case NL80211_CMD_SCHED_SCAN_RESULTS
:
2461 wpa_dbg(drv
->ctx
, MSG_DEBUG
,
2462 "nl80211: New sched scan results available");
2463 drv
->scan_state
= SCHED_SCAN_RESULTS
;
2464 send_scan_event(drv
, 0, tb
, 0);
2466 case NL80211_CMD_SCAN_ABORTED
:
2467 wpa_dbg(drv
->ctx
, MSG_DEBUG
, "nl80211: Scan aborted");
2468 if (drv
->last_scan_cmd
!= NL80211_CMD_VENDOR
)
2469 drv
->scan_state
= SCAN_ABORTED
;
2470 if (drv
->last_scan_cmd
== NL80211_CMD_TRIGGER_SCAN
) {
2472 * Need to indicate that scan results are available in
2473 * order not to make wpa_supplicant stop its scanning.
2475 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout
,
2477 drv
->last_scan_cmd
= 0;
2479 external_scan_event
= 1;
2481 send_scan_event(drv
, 1, tb
, external_scan_event
);
2483 case NL80211_CMD_AUTHENTICATE
:
2484 case NL80211_CMD_ASSOCIATE
:
2485 case NL80211_CMD_DEAUTHENTICATE
:
2486 case NL80211_CMD_DISASSOCIATE
:
2487 case NL80211_CMD_FRAME_TX_STATUS
:
2488 case NL80211_CMD_UNPROT_DEAUTHENTICATE
:
2489 case NL80211_CMD_UNPROT_DISASSOCIATE
:
2490 mlme_event(bss
, cmd
, tb
[NL80211_ATTR_FRAME
],
2491 tb
[NL80211_ATTR_MAC
], tb
[NL80211_ATTR_TIMED_OUT
],
2492 tb
[NL80211_ATTR_WIPHY_FREQ
], tb
[NL80211_ATTR_ACK
],
2493 tb
[NL80211_ATTR_COOKIE
],
2494 tb
[NL80211_ATTR_RX_SIGNAL_DBM
],
2495 tb
[NL80211_ATTR_STA_WME
],
2496 tb
[NL80211_ATTR_REQ_IE
]);
2498 case NL80211_CMD_CONNECT
:
2499 case NL80211_CMD_ROAM
:
2500 mlme_event_connect(drv
, cmd
,
2501 tb
[NL80211_ATTR_STATUS_CODE
],
2502 tb
[NL80211_ATTR_MAC
],
2503 tb
[NL80211_ATTR_REQ_IE
],
2504 tb
[NL80211_ATTR_RESP_IE
],
2505 tb
[NL80211_ATTR_TIMED_OUT
],
2506 tb
[NL80211_ATTR_TIMEOUT_REASON
],
2508 tb
[NL80211_ATTR_FILS_KEK
],
2510 tb
[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM
],
2511 tb
[NL80211_ATTR_PMK
],
2512 tb
[NL80211_ATTR_PMKID
]);
2514 case NL80211_CMD_CH_SWITCH_STARTED_NOTIFY
:
2515 mlme_event_ch_switch(drv
,
2516 tb
[NL80211_ATTR_IFINDEX
],
2517 tb
[NL80211_ATTR_WIPHY_FREQ
],
2518 tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
],
2519 tb
[NL80211_ATTR_CHANNEL_WIDTH
],
2520 tb
[NL80211_ATTR_CENTER_FREQ1
],
2521 tb
[NL80211_ATTR_CENTER_FREQ2
],
2524 case NL80211_CMD_CH_SWITCH_NOTIFY
:
2525 mlme_event_ch_switch(drv
,
2526 tb
[NL80211_ATTR_IFINDEX
],
2527 tb
[NL80211_ATTR_WIPHY_FREQ
],
2528 tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
],
2529 tb
[NL80211_ATTR_CHANNEL_WIDTH
],
2530 tb
[NL80211_ATTR_CENTER_FREQ1
],
2531 tb
[NL80211_ATTR_CENTER_FREQ2
],
2534 case NL80211_CMD_DISCONNECT
:
2535 mlme_event_disconnect(drv
, tb
[NL80211_ATTR_REASON_CODE
],
2536 tb
[NL80211_ATTR_MAC
],
2537 tb
[NL80211_ATTR_DISCONNECTED_BY_AP
]);
2539 case NL80211_CMD_MICHAEL_MIC_FAILURE
:
2540 mlme_event_michael_mic_failure(bss
, tb
);
2542 case NL80211_CMD_JOIN_IBSS
:
2543 mlme_event_join_ibss(drv
, tb
);
2545 case NL80211_CMD_REMAIN_ON_CHANNEL
:
2546 mlme_event_remain_on_channel(drv
, 0, tb
);
2548 case NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL
:
2549 mlme_event_remain_on_channel(drv
, 1, tb
);
2551 case NL80211_CMD_NOTIFY_CQM
:
2552 nl80211_cqm_event(drv
, tb
);
2554 case NL80211_CMD_REG_CHANGE
:
2555 case NL80211_CMD_WIPHY_REG_CHANGE
:
2556 nl80211_reg_change_event(drv
, tb
);
2558 case NL80211_CMD_REG_BEACON_HINT
:
2559 nl80211_reg_beacon_hint_event(drv
, tb
);
2561 case NL80211_CMD_NEW_STATION
:
2562 nl80211_new_station_event(drv
, bss
, tb
);
2564 case NL80211_CMD_DEL_STATION
:
2565 nl80211_del_station_event(drv
, bss
, tb
);
2567 case NL80211_CMD_SET_REKEY_OFFLOAD
:
2568 nl80211_rekey_offload_event(drv
, tb
);
2570 case NL80211_CMD_PMKSA_CANDIDATE
:
2571 nl80211_pmksa_candidate_event(drv
, tb
);
2573 case NL80211_CMD_PROBE_CLIENT
:
2574 nl80211_client_probe_event(drv
, tb
);
2576 case NL80211_CMD_TDLS_OPER
:
2577 nl80211_tdls_oper_event(drv
, tb
);
2579 case NL80211_CMD_CONN_FAILED
:
2580 nl80211_connect_failed_event(drv
, tb
);
2582 case NL80211_CMD_FT_EVENT
:
2583 mlme_event_ft_event(drv
, tb
);
2585 case NL80211_CMD_RADAR_DETECT
:
2586 nl80211_radar_event(drv
, tb
);
2588 case NL80211_CMD_STOP_AP
:
2589 nl80211_stop_ap(drv
, tb
);
2591 case NL80211_CMD_VENDOR
:
2592 nl80211_vendor_event(drv
, tb
);
2594 case NL80211_CMD_NEW_PEER_CANDIDATE
:
2595 nl80211_new_peer_candidate(drv
, tb
);
2597 case NL80211_CMD_PORT_AUTHORIZED
:
2598 nl80211_port_authorized(drv
, tb
);
2600 case NL80211_CMD_STA_OPMODE_CHANGED
:
2601 nl80211_sta_opmode_change_event(drv
, tb
);
2604 wpa_dbg(drv
->ctx
, MSG_DEBUG
, "nl80211: Ignored unknown event "
2611 int process_global_event(struct nl_msg
*msg
, void *arg
)
2613 struct nl80211_global
*global
= arg
;
2614 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
2615 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
2616 struct wpa_driver_nl80211_data
*drv
, *tmp
;
2617 int ifidx
= -1, wiphy_idx
= -1, wiphy_idx_rx
= -1;
2618 struct i802_bss
*bss
;
2620 int wdev_id_set
= 0;
2621 int wiphy_idx_set
= 0;
2623 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
2624 genlmsg_attrlen(gnlh
, 0), NULL
);
2626 if (tb
[NL80211_ATTR_IFINDEX
])
2627 ifidx
= nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]);
2628 else if (tb
[NL80211_ATTR_WDEV
]) {
2629 wdev_id
= nla_get_u64(tb
[NL80211_ATTR_WDEV
]);
2631 } else if (tb
[NL80211_ATTR_WIPHY
]) {
2632 wiphy_idx_rx
= nla_get_u32(tb
[NL80211_ATTR_WIPHY
]);
2636 dl_list_for_each_safe(drv
, tmp
, &global
->interfaces
,
2637 struct wpa_driver_nl80211_data
, list
) {
2638 for (bss
= drv
->first_bss
; bss
; bss
= bss
->next
) {
2640 wiphy_idx
= nl80211_get_wiphy_index(bss
);
2641 if ((ifidx
== -1 && !wiphy_idx_set
&& !wdev_id_set
) ||
2642 ifidx
== bss
->ifindex
||
2643 (wiphy_idx_set
&& wiphy_idx
== wiphy_idx_rx
) ||
2644 (wdev_id_set
&& bss
->wdev_id_set
&&
2645 wdev_id
== bss
->wdev_id
)) {
2646 do_process_drv_event(bss
, gnlh
->cmd
, tb
);
2650 wpa_printf(MSG_DEBUG
,
2651 "nl80211: Ignored event %d (%s) for foreign interface (ifindex %d wdev 0x%llx)",
2652 gnlh
->cmd
, nl80211_command_to_string(gnlh
->cmd
),
2653 ifidx
, (long long unsigned int) wdev_id
);
2660 int process_bss_event(struct nl_msg
*msg
, void *arg
)
2662 struct i802_bss
*bss
= arg
;
2663 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
2664 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
2666 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
2667 genlmsg_attrlen(gnlh
, 0), NULL
);
2669 wpa_printf(MSG_DEBUG
, "nl80211: BSS Event %d (%s) received for %s",
2670 gnlh
->cmd
, nl80211_command_to_string(gnlh
->cmd
),
2673 switch (gnlh
->cmd
) {
2674 case NL80211_CMD_FRAME
:
2675 case NL80211_CMD_FRAME_TX_STATUS
:
2676 mlme_event(bss
, gnlh
->cmd
, tb
[NL80211_ATTR_FRAME
],
2677 tb
[NL80211_ATTR_MAC
], tb
[NL80211_ATTR_TIMED_OUT
],
2678 tb
[NL80211_ATTR_WIPHY_FREQ
], tb
[NL80211_ATTR_ACK
],
2679 tb
[NL80211_ATTR_COOKIE
],
2680 tb
[NL80211_ATTR_RX_SIGNAL_DBM
],
2681 tb
[NL80211_ATTR_STA_WME
], NULL
);
2683 case NL80211_CMD_UNEXPECTED_FRAME
:
2684 nl80211_spurious_frame(bss
, tb
, 0);
2686 case NL80211_CMD_UNEXPECTED_4ADDR_FRAME
:
2687 nl80211_spurious_frame(bss
, tb
, 1);
2689 case NL80211_CMD_EXTERNAL_AUTH
:
2690 nl80211_external_auth(bss
->drv
, tb
);
2693 wpa_printf(MSG_DEBUG
, "nl80211: Ignored unknown event "
2694 "(cmd=%d)", gnlh
->cmd
);