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_EXTERNAL_AUTH
)
135 C2S(NL80211_CMD_STA_OPMODE_CHANGED
)
137 return "NL80211_CMD_UNKNOWN";
143 static void mlme_event_auth(struct wpa_driver_nl80211_data
*drv
,
144 const u8
*frame
, size_t len
)
146 const struct ieee80211_mgmt
*mgmt
;
147 union wpa_event_data event
;
149 if (!(drv
->capa
.flags
& WPA_DRIVER_FLAGS_SME
) &&
150 drv
->force_connect_cmd
) {
152 * Avoid reporting two association events that would confuse
155 wpa_printf(MSG_DEBUG
,
156 "nl80211: Ignore auth event when using driver SME");
160 wpa_printf(MSG_DEBUG
, "nl80211: Authenticate event");
161 mgmt
= (const struct ieee80211_mgmt
*) frame
;
162 if (len
< 24 + sizeof(mgmt
->u
.auth
)) {
163 wpa_printf(MSG_DEBUG
, "nl80211: Too short association event "
168 os_memcpy(drv
->auth_bssid
, mgmt
->sa
, ETH_ALEN
);
169 os_memset(drv
->auth_attempt_bssid
, 0, ETH_ALEN
);
170 os_memset(&event
, 0, sizeof(event
));
171 os_memcpy(event
.auth
.peer
, mgmt
->sa
, ETH_ALEN
);
172 event
.auth
.auth_type
= le_to_host16(mgmt
->u
.auth
.auth_alg
);
173 event
.auth
.auth_transaction
=
174 le_to_host16(mgmt
->u
.auth
.auth_transaction
);
175 event
.auth
.status_code
= le_to_host16(mgmt
->u
.auth
.status_code
);
176 if (len
> 24 + sizeof(mgmt
->u
.auth
)) {
177 event
.auth
.ies
= mgmt
->u
.auth
.variable
;
178 event
.auth
.ies_len
= len
- 24 - sizeof(mgmt
->u
.auth
);
181 wpa_supplicant_event(drv
->ctx
, EVENT_AUTH
, &event
);
185 static void nl80211_parse_wmm_params(struct nlattr
*wmm_attr
,
186 struct wmm_params
*wmm_params
)
188 struct nlattr
*wmm_info
[NL80211_STA_WME_MAX
+ 1];
189 static struct nla_policy wme_policy
[NL80211_STA_WME_MAX
+ 1] = {
190 [NL80211_STA_WME_UAPSD_QUEUES
] = { .type
= NLA_U8
},
194 nla_parse_nested(wmm_info
, NL80211_STA_WME_MAX
, wmm_attr
,
196 !wmm_info
[NL80211_STA_WME_UAPSD_QUEUES
])
199 wmm_params
->uapsd_queues
=
200 nla_get_u8(wmm_info
[NL80211_STA_WME_UAPSD_QUEUES
]);
201 wmm_params
->info_bitmap
|= WMM_PARAMS_UAPSD_QUEUES_INFO
;
205 static void mlme_event_assoc(struct wpa_driver_nl80211_data
*drv
,
206 const u8
*frame
, size_t len
, struct nlattr
*wmm
)
208 const struct ieee80211_mgmt
*mgmt
;
209 union wpa_event_data event
;
213 if (!(drv
->capa
.flags
& WPA_DRIVER_FLAGS_SME
) &&
214 drv
->force_connect_cmd
) {
216 * Avoid reporting two association events that would confuse
219 wpa_printf(MSG_DEBUG
,
220 "nl80211: Ignore assoc event when using driver SME");
224 wpa_printf(MSG_DEBUG
, "nl80211: Associate event");
225 mgmt
= (const struct ieee80211_mgmt
*) frame
;
226 if (len
< 24 + sizeof(mgmt
->u
.assoc_resp
)) {
227 wpa_printf(MSG_DEBUG
, "nl80211: Too short association event "
232 status
= le_to_host16(mgmt
->u
.assoc_resp
.status_code
);
233 if (status
!= WLAN_STATUS_SUCCESS
) {
234 os_memset(&event
, 0, sizeof(event
));
235 event
.assoc_reject
.bssid
= mgmt
->bssid
;
236 if (len
> 24 + sizeof(mgmt
->u
.assoc_resp
)) {
237 event
.assoc_reject
.resp_ies
=
238 (u8
*) mgmt
->u
.assoc_resp
.variable
;
239 event
.assoc_reject
.resp_ies_len
=
240 len
- 24 - sizeof(mgmt
->u
.assoc_resp
);
242 event
.assoc_reject
.status_code
= status
;
244 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC_REJECT
, &event
);
249 os_memcpy(drv
->bssid
, mgmt
->sa
, ETH_ALEN
);
250 os_memcpy(drv
->prev_bssid
, mgmt
->sa
, ETH_ALEN
);
252 os_memset(&event
, 0, sizeof(event
));
253 event
.assoc_info
.resp_frame
= frame
;
254 event
.assoc_info
.resp_frame_len
= len
;
255 if (len
> 24 + sizeof(mgmt
->u
.assoc_resp
)) {
256 event
.assoc_info
.resp_ies
= (u8
*) mgmt
->u
.assoc_resp
.variable
;
257 event
.assoc_info
.resp_ies_len
=
258 len
- 24 - sizeof(mgmt
->u
.assoc_resp
);
261 event
.assoc_info
.freq
= drv
->assoc_freq
;
263 /* When this association was initiated outside of wpa_supplicant,
264 * drv->ssid needs to be set here to satisfy later checking. */
265 ssid_len
= nl80211_get_assoc_ssid(drv
, drv
->ssid
);
267 drv
->ssid_len
= ssid_len
;
268 wpa_printf(MSG_DEBUG
,
269 "nl80211: Set drv->ssid based on scan res info to '%s'",
270 wpa_ssid_txt(drv
->ssid
, drv
->ssid_len
));
273 nl80211_parse_wmm_params(wmm
, &event
.assoc_info
.wmm_params
);
275 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC
, &event
);
279 static void mlme_event_connect(struct wpa_driver_nl80211_data
*drv
,
280 enum nl80211_commands cmd
, struct nlattr
*status
,
281 struct nlattr
*addr
, struct nlattr
*req_ie
,
282 struct nlattr
*resp_ie
,
283 struct nlattr
*timed_out
,
284 struct nlattr
*timeout_reason
,
285 struct nlattr
*authorized
,
286 struct nlattr
*key_replay_ctr
,
287 struct nlattr
*ptk_kck
,
288 struct nlattr
*ptk_kek
,
289 struct nlattr
*subnet_status
,
290 struct nlattr
*fils_erp_next_seq_num
,
291 struct nlattr
*fils_pmk
,
292 struct nlattr
*fils_pmkid
)
294 union wpa_event_data event
;
295 const u8
*ssid
= NULL
;
299 if (drv
->capa
.flags
& WPA_DRIVER_FLAGS_SME
) {
301 * Avoid reporting two association events that would confuse
304 wpa_printf(MSG_DEBUG
, "nl80211: Ignore connect event (cmd=%d) "
305 "when using userspace SME", cmd
);
309 drv
->connect_reassoc
= 0;
311 status_code
= status
? nla_get_u16(status
) : WLAN_STATUS_SUCCESS
;
313 if (cmd
== NL80211_CMD_CONNECT
) {
314 wpa_printf(MSG_DEBUG
,
315 "nl80211: Connect event (status=%u ignore_next_local_disconnect=%d)",
316 status_code
, drv
->ignore_next_local_disconnect
);
317 } else if (cmd
== NL80211_CMD_ROAM
) {
318 wpa_printf(MSG_DEBUG
, "nl80211: Roam event");
321 os_memset(&event
, 0, sizeof(event
));
322 if (cmd
== NL80211_CMD_CONNECT
&& status_code
!= WLAN_STATUS_SUCCESS
) {
324 event
.assoc_reject
.bssid
= nla_data(addr
);
325 if (drv
->ignore_next_local_disconnect
) {
326 drv
->ignore_next_local_disconnect
= 0;
327 if (!event
.assoc_reject
.bssid
||
328 (os_memcmp(event
.assoc_reject
.bssid
,
329 drv
->auth_attempt_bssid
,
332 * Ignore the event that came without a BSSID or
333 * for the old connection since this is likely
334 * not relevant to the new Connect command.
336 wpa_printf(MSG_DEBUG
,
337 "nl80211: Ignore connection failure event triggered during reassociation");
342 event
.assoc_reject
.resp_ies
= nla_data(resp_ie
);
343 event
.assoc_reject
.resp_ies_len
= nla_len(resp_ie
);
345 event
.assoc_reject
.status_code
= status_code
;
346 event
.assoc_reject
.timed_out
= timed_out
!= NULL
;
347 if (timed_out
&& timeout_reason
) {
348 enum nl80211_timeout_reason reason
;
350 reason
= nla_get_u32(timeout_reason
);
352 case NL80211_TIMEOUT_SCAN
:
353 event
.assoc_reject
.timeout_reason
= "scan";
355 case NL80211_TIMEOUT_AUTH
:
356 event
.assoc_reject
.timeout_reason
= "auth";
358 case NL80211_TIMEOUT_ASSOC
:
359 event
.assoc_reject
.timeout_reason
= "assoc";
365 if (fils_erp_next_seq_num
)
366 event
.assoc_reject
.fils_erp_next_seq_num
=
367 nla_get_u16(fils_erp_next_seq_num
);
368 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC_REJECT
, &event
);
374 os_memcpy(drv
->bssid
, nla_data(addr
), ETH_ALEN
);
375 os_memcpy(drv
->prev_bssid
, drv
->bssid
, ETH_ALEN
);
379 event
.assoc_info
.req_ies
= nla_data(req_ie
);
380 event
.assoc_info
.req_ies_len
= nla_len(req_ie
);
382 if (cmd
== NL80211_CMD_ROAM
) {
383 ssid
= get_ie(event
.assoc_info
.req_ies
,
384 event
.assoc_info
.req_ies_len
,
386 if (ssid
&& ssid
[1] > 0 && ssid
[1] <= 32) {
387 drv
->ssid_len
= ssid
[1];
388 os_memcpy(drv
->ssid
, ssid
+ 2, ssid
[1]);
389 wpa_printf(MSG_DEBUG
,
390 "nl80211: Set drv->ssid based on req_ie to '%s'",
391 wpa_ssid_txt(drv
->ssid
,
397 event
.assoc_info
.resp_ies
= nla_data(resp_ie
);
398 event
.assoc_info
.resp_ies_len
= nla_len(resp_ie
);
401 event
.assoc_info
.freq
= nl80211_get_assoc_freq(drv
);
403 if ((!ssid
|| ssid
[1] == 0 || ssid
[1] > 32) &&
404 (ssid_len
= nl80211_get_assoc_ssid(drv
, drv
->ssid
)) > 0) {
405 /* When this connection was initiated outside of wpa_supplicant,
406 * drv->ssid needs to be set here to satisfy later checking. */
407 drv
->ssid_len
= ssid_len
;
408 wpa_printf(MSG_DEBUG
,
409 "nl80211: Set drv->ssid based on scan res info to '%s'",
410 wpa_ssid_txt(drv
->ssid
, drv
->ssid_len
));
413 if (authorized
&& nla_get_u8(authorized
)) {
414 event
.assoc_info
.authorized
= 1;
415 wpa_printf(MSG_DEBUG
, "nl80211: connection authorized");
417 if (key_replay_ctr
) {
418 event
.assoc_info
.key_replay_ctr
= nla_data(key_replay_ctr
);
419 event
.assoc_info
.key_replay_ctr_len
= nla_len(key_replay_ctr
);
422 event
.assoc_info
.ptk_kck
= nla_data(ptk_kck
);
423 event
.assoc_info
.ptk_kck_len
= nla_len(ptk_kck
);
426 event
.assoc_info
.ptk_kek
= nla_data(ptk_kek
);
427 event
.assoc_info
.ptk_kek_len
= nla_len(ptk_kek
);
432 * At least for now, this is only available from
433 * QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS and that
434 * attribute has the same values 0, 1, 2 as are used in the
435 * variable here, so no mapping between different values are
438 event
.assoc_info
.subnet_status
= nla_get_u8(subnet_status
);
441 if (fils_erp_next_seq_num
)
442 event
.assoc_info
.fils_erp_next_seq_num
=
443 nla_get_u16(fils_erp_next_seq_num
);
446 event
.assoc_info
.fils_pmk
= nla_data(fils_pmk
);
447 event
.assoc_info
.fils_pmk_len
= nla_len(fils_pmk
);
451 event
.assoc_info
.fils_pmkid
= nla_data(fils_pmkid
);
453 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC
, &event
);
457 static void mlme_event_disconnect(struct wpa_driver_nl80211_data
*drv
,
458 struct nlattr
*reason
, struct nlattr
*addr
,
459 struct nlattr
*by_ap
)
461 union wpa_event_data data
;
462 unsigned int locally_generated
= by_ap
== NULL
;
464 if (drv
->capa
.flags
& WPA_DRIVER_FLAGS_SME
) {
466 * Avoid reporting two disassociation events that could
467 * confuse the core code.
469 wpa_printf(MSG_DEBUG
, "nl80211: Ignore disconnect "
470 "event when using userspace SME");
474 if (drv
->ignore_next_local_disconnect
) {
475 drv
->ignore_next_local_disconnect
= 0;
476 if (locally_generated
) {
477 wpa_printf(MSG_DEBUG
, "nl80211: Ignore disconnect "
478 "event triggered during reassociation");
481 wpa_printf(MSG_WARNING
, "nl80211: Was expecting local "
482 "disconnect but got another disconnect "
486 wpa_printf(MSG_DEBUG
, "nl80211: Disconnect event");
487 nl80211_mark_disconnected(drv
);
488 os_memset(&data
, 0, sizeof(data
));
490 data
.deauth_info
.reason_code
= nla_get_u16(reason
);
491 data
.deauth_info
.locally_generated
= by_ap
== NULL
;
492 wpa_supplicant_event(drv
->ctx
, EVENT_DEAUTH
, &data
);
496 static int calculate_chan_offset(int width
, int freq
, int cf1
, int cf2
)
500 switch (convert2width(width
)) {
501 case CHAN_WIDTH_20_NOHT
:
513 case CHAN_WIDTH_UNKNOWN
:
514 case CHAN_WIDTH_80P80
:
515 /* FIXME: implement this */
519 return (abs(freq
- freq1
) / 20) % 2 == 0 ? 1 : -1;
523 static void mlme_event_ch_switch(struct wpa_driver_nl80211_data
*drv
,
524 struct nlattr
*ifindex
, struct nlattr
*freq
,
525 struct nlattr
*type
, struct nlattr
*bw
,
526 struct nlattr
*cf1
, struct nlattr
*cf2
)
528 struct i802_bss
*bss
;
529 union wpa_event_data data
;
534 wpa_printf(MSG_DEBUG
, "nl80211: Channel switch event");
539 ifidx
= nla_get_u32(ifindex
);
540 bss
= get_bss_ifindex(drv
, ifidx
);
542 wpa_printf(MSG_WARNING
, "nl80211: Unknown ifindex (%d) for channel switch, ignoring",
548 enum nl80211_channel_type ch_type
= nla_get_u32(type
);
550 wpa_printf(MSG_DEBUG
, "nl80211: Channel type: %d", ch_type
);
552 case NL80211_CHAN_NO_HT
:
555 case NL80211_CHAN_HT20
:
557 case NL80211_CHAN_HT40PLUS
:
560 case NL80211_CHAN_HT40MINUS
:
564 } else if (bw
&& cf1
) {
565 /* This can happen for example with VHT80 ch switch */
566 chan_offset
= calculate_chan_offset(nla_get_u32(bw
),
569 cf2
? nla_get_u32(cf2
) : 0);
571 wpa_printf(MSG_WARNING
, "nl80211: Unknown secondary channel information - following channel definition calculations may fail");
574 os_memset(&data
, 0, sizeof(data
));
575 data
.ch_switch
.freq
= nla_get_u32(freq
);
576 data
.ch_switch
.ht_enabled
= ht_enabled
;
577 data
.ch_switch
.ch_offset
= chan_offset
;
579 data
.ch_switch
.ch_width
= convert2width(nla_get_u32(bw
));
581 data
.ch_switch
.cf1
= nla_get_u32(cf1
);
583 data
.ch_switch
.cf2
= nla_get_u32(cf2
);
585 bss
->freq
= data
.ch_switch
.freq
;
586 drv
->assoc_freq
= data
.ch_switch
.freq
;
588 wpa_supplicant_event(bss
->ctx
, EVENT_CH_SWITCH
, &data
);
592 static void mlme_timeout_event(struct wpa_driver_nl80211_data
*drv
,
593 enum nl80211_commands cmd
, struct nlattr
*addr
)
595 union wpa_event_data event
;
596 enum wpa_event_type ev
;
598 if (nla_len(addr
) != ETH_ALEN
)
601 wpa_printf(MSG_DEBUG
, "nl80211: MLME event %d; timeout with " MACSTR
,
602 cmd
, MAC2STR((u8
*) nla_data(addr
)));
604 if (cmd
== NL80211_CMD_AUTHENTICATE
)
605 ev
= EVENT_AUTH_TIMED_OUT
;
606 else if (cmd
== NL80211_CMD_ASSOCIATE
)
607 ev
= EVENT_ASSOC_TIMED_OUT
;
611 os_memset(&event
, 0, sizeof(event
));
612 os_memcpy(event
.timeout_event
.addr
, nla_data(addr
), ETH_ALEN
);
613 wpa_supplicant_event(drv
->ctx
, ev
, &event
);
617 static void mlme_event_mgmt(struct i802_bss
*bss
,
618 struct nlattr
*freq
, struct nlattr
*sig
,
619 const u8
*frame
, size_t len
)
621 struct wpa_driver_nl80211_data
*drv
= bss
->drv
;
622 const struct ieee80211_mgmt
*mgmt
;
623 union wpa_event_data event
;
628 wpa_printf(MSG_MSGDUMP
, "nl80211: Frame event");
629 mgmt
= (const struct ieee80211_mgmt
*) frame
;
631 wpa_printf(MSG_DEBUG
, "nl80211: Too short management frame");
635 fc
= le_to_host16(mgmt
->frame_control
);
636 stype
= WLAN_FC_GET_STYPE(fc
);
639 ssi_signal
= (s32
) nla_get_u32(sig
);
641 os_memset(&event
, 0, sizeof(event
));
643 event
.rx_mgmt
.freq
= nla_get_u32(freq
);
644 rx_freq
= drv
->last_mgmt_freq
= event
.rx_mgmt
.freq
;
646 wpa_printf(MSG_DEBUG
,
647 "nl80211: RX frame da=" MACSTR
" sa=" MACSTR
" bssid=" MACSTR
648 " freq=%d ssi_signal=%d fc=0x%x seq_ctrl=0x%x stype=%u (%s) len=%u",
649 MAC2STR(mgmt
->da
), MAC2STR(mgmt
->sa
), MAC2STR(mgmt
->bssid
),
650 rx_freq
, ssi_signal
, fc
,
651 le_to_host16(mgmt
->seq_ctrl
), stype
, fc2str(fc
),
653 event
.rx_mgmt
.frame
= frame
;
654 event
.rx_mgmt
.frame_len
= len
;
655 event
.rx_mgmt
.ssi_signal
= ssi_signal
;
656 event
.rx_mgmt
.drv_priv
= bss
;
657 wpa_supplicant_event(drv
->ctx
, EVENT_RX_MGMT
, &event
);
661 static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data
*drv
,
662 struct nlattr
*cookie
, const u8
*frame
,
663 size_t len
, struct nlattr
*ack
)
665 union wpa_event_data event
;
666 const struct ieee80211_hdr
*hdr
;
669 wpa_printf(MSG_DEBUG
, "nl80211: Frame TX status event");
670 if (!is_ap_interface(drv
->nlmode
)) {
676 cookie_val
= nla_get_u64(cookie
);
677 wpa_printf(MSG_DEBUG
, "nl80211: Action TX status:"
678 " cookie=0x%llx%s (ack=%d)",
679 (long long unsigned int) cookie_val
,
680 cookie_val
== drv
->send_action_cookie
?
681 " (match)" : " (unknown)", ack
!= NULL
);
682 if (cookie_val
!= drv
->send_action_cookie
)
686 hdr
= (const struct ieee80211_hdr
*) frame
;
687 fc
= le_to_host16(hdr
->frame_control
);
689 os_memset(&event
, 0, sizeof(event
));
690 event
.tx_status
.type
= WLAN_FC_GET_TYPE(fc
);
691 event
.tx_status
.stype
= WLAN_FC_GET_STYPE(fc
);
692 event
.tx_status
.dst
= hdr
->addr1
;
693 event
.tx_status
.data
= frame
;
694 event
.tx_status
.data_len
= len
;
695 event
.tx_status
.ack
= ack
!= NULL
;
696 wpa_supplicant_event(drv
->ctx
, EVENT_TX_STATUS
, &event
);
700 static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data
*drv
,
701 enum wpa_event_type type
,
702 const u8
*frame
, size_t len
)
704 const struct ieee80211_mgmt
*mgmt
;
705 union wpa_event_data event
;
706 const u8
*bssid
= NULL
;
709 if (type
== EVENT_DEAUTH
)
710 wpa_printf(MSG_DEBUG
, "nl80211: Deauthenticate event");
712 wpa_printf(MSG_DEBUG
, "nl80211: Disassociate event");
714 mgmt
= (const struct ieee80211_mgmt
*) frame
;
718 if ((drv
->capa
.flags
& WPA_DRIVER_FLAGS_SME
) &&
720 os_memcmp(bssid
, drv
->auth_bssid
, ETH_ALEN
) != 0 &&
721 os_memcmp(bssid
, drv
->auth_attempt_bssid
, ETH_ALEN
) != 0 &&
722 os_memcmp(bssid
, drv
->prev_bssid
, ETH_ALEN
) == 0) {
724 * Avoid issues with some roaming cases where
725 * disconnection event for the old AP may show up after
726 * we have started connection with the new AP.
727 * In case of locally generated event clear
728 * ignore_next_local_deauth as well, to avoid next local
729 * deauth event be wrongly ignored.
731 if (!os_memcmp(mgmt
->sa
, drv
->first_bss
->addr
,
733 wpa_printf(MSG_DEBUG
,
734 "nl80211: Received a locally generated deauth event. Clear ignore_next_local_deauth flag");
735 drv
->ignore_next_local_deauth
= 0;
737 wpa_printf(MSG_DEBUG
,
738 "nl80211: Ignore deauth/disassoc event from old AP " MACSTR
" when already authenticating with " MACSTR
,
740 MAC2STR(drv
->auth_attempt_bssid
));
745 if (!(drv
->capa
.flags
& WPA_DRIVER_FLAGS_SME
) &&
746 drv
->connect_reassoc
&& drv
->associated
&&
747 os_memcmp(bssid
, drv
->prev_bssid
, ETH_ALEN
) == 0 &&
748 os_memcmp(bssid
, drv
->auth_attempt_bssid
, ETH_ALEN
) != 0) {
750 * Avoid issues with some roaming cases where
751 * disconnection event for the old AP may show up after
752 * we have started connection with the new AP.
754 wpa_printf(MSG_DEBUG
,
755 "nl80211: Ignore deauth/disassoc event from old AP "
757 " when already connecting with " MACSTR
,
759 MAC2STR(drv
->auth_attempt_bssid
));
763 if (drv
->associated
!= 0 &&
764 os_memcmp(bssid
, drv
->bssid
, ETH_ALEN
) != 0 &&
765 os_memcmp(bssid
, drv
->auth_bssid
, ETH_ALEN
) != 0) {
767 * We have presumably received this deauth as a
768 * response to a clear_state_mismatch() outgoing
769 * deauth. Don't let it take us offline!
771 wpa_printf(MSG_DEBUG
, "nl80211: Deauth received "
772 "from Unknown BSSID " MACSTR
" -- ignoring",
778 nl80211_mark_disconnected(drv
);
779 os_memset(&event
, 0, sizeof(event
));
781 /* Note: Same offset for Reason Code in both frame subtypes */
782 if (len
>= 24 + sizeof(mgmt
->u
.deauth
))
783 reason_code
= le_to_host16(mgmt
->u
.deauth
.reason_code
);
785 if (type
== EVENT_DISASSOC
) {
786 event
.disassoc_info
.locally_generated
=
787 !os_memcmp(mgmt
->sa
, drv
->first_bss
->addr
, ETH_ALEN
);
788 event
.disassoc_info
.addr
= bssid
;
789 event
.disassoc_info
.reason_code
= reason_code
;
790 if (frame
+ len
> mgmt
->u
.disassoc
.variable
) {
791 event
.disassoc_info
.ie
= mgmt
->u
.disassoc
.variable
;
792 event
.disassoc_info
.ie_len
= frame
+ len
-
793 mgmt
->u
.disassoc
.variable
;
796 event
.deauth_info
.locally_generated
=
797 !os_memcmp(mgmt
->sa
, drv
->first_bss
->addr
, ETH_ALEN
);
798 if (drv
->ignore_deauth_event
) {
799 wpa_printf(MSG_DEBUG
, "nl80211: Ignore deauth event due to previous forced deauth-during-auth");
800 drv
->ignore_deauth_event
= 0;
801 if (event
.deauth_info
.locally_generated
)
802 drv
->ignore_next_local_deauth
= 0;
805 if (drv
->ignore_next_local_deauth
) {
806 drv
->ignore_next_local_deauth
= 0;
807 if (event
.deauth_info
.locally_generated
) {
808 wpa_printf(MSG_DEBUG
, "nl80211: Ignore deauth event triggered due to own deauth request");
811 wpa_printf(MSG_WARNING
, "nl80211: Was expecting local deauth but got another disconnect event first");
813 event
.deauth_info
.addr
= bssid
;
814 event
.deauth_info
.reason_code
= reason_code
;
815 if (frame
+ len
> mgmt
->u
.deauth
.variable
) {
816 event
.deauth_info
.ie
= mgmt
->u
.deauth
.variable
;
817 event
.deauth_info
.ie_len
= frame
+ len
-
818 mgmt
->u
.deauth
.variable
;
822 wpa_supplicant_event(drv
->ctx
, type
, &event
);
826 static void mlme_event_unprot_disconnect(struct wpa_driver_nl80211_data
*drv
,
827 enum wpa_event_type type
,
828 const u8
*frame
, size_t len
)
830 const struct ieee80211_mgmt
*mgmt
;
831 union wpa_event_data event
;
834 if (type
== EVENT_UNPROT_DEAUTH
)
835 wpa_printf(MSG_DEBUG
, "nl80211: Unprot Deauthenticate event");
837 wpa_printf(MSG_DEBUG
, "nl80211: Unprot Disassociate event");
842 mgmt
= (const struct ieee80211_mgmt
*) frame
;
844 os_memset(&event
, 0, sizeof(event
));
845 /* Note: Same offset for Reason Code in both frame subtypes */
846 if (len
>= 24 + sizeof(mgmt
->u
.deauth
))
847 reason_code
= le_to_host16(mgmt
->u
.deauth
.reason_code
);
849 if (type
== EVENT_UNPROT_DISASSOC
) {
850 event
.unprot_disassoc
.sa
= mgmt
->sa
;
851 event
.unprot_disassoc
.da
= mgmt
->da
;
852 event
.unprot_disassoc
.reason_code
= reason_code
;
854 event
.unprot_deauth
.sa
= mgmt
->sa
;
855 event
.unprot_deauth
.da
= mgmt
->da
;
856 event
.unprot_deauth
.reason_code
= reason_code
;
859 wpa_supplicant_event(drv
->ctx
, type
, &event
);
863 static void mlme_event(struct i802_bss
*bss
,
864 enum nl80211_commands cmd
, struct nlattr
*frame
,
865 struct nlattr
*addr
, struct nlattr
*timed_out
,
866 struct nlattr
*freq
, struct nlattr
*ack
,
867 struct nlattr
*cookie
, struct nlattr
*sig
,
870 struct wpa_driver_nl80211_data
*drv
= bss
->drv
;
874 if (timed_out
&& addr
) {
875 mlme_timeout_event(drv
, cmd
, addr
);
880 wpa_printf(MSG_DEBUG
,
881 "nl80211: MLME event %d (%s) without frame data",
882 cmd
, nl80211_command_to_string(cmd
));
886 data
= nla_data(frame
);
887 len
= nla_len(frame
);
888 if (len
< 4 + 2 * ETH_ALEN
) {
889 wpa_printf(MSG_MSGDUMP
, "nl80211: MLME event %d (%s) on %s("
890 MACSTR
") - too short",
891 cmd
, nl80211_command_to_string(cmd
), bss
->ifname
,
895 wpa_printf(MSG_MSGDUMP
, "nl80211: MLME event %d (%s) on %s(" MACSTR
896 ") A1=" MACSTR
" A2=" MACSTR
, cmd
,
897 nl80211_command_to_string(cmd
), bss
->ifname
,
898 MAC2STR(bss
->addr
), MAC2STR(data
+ 4),
899 MAC2STR(data
+ 4 + ETH_ALEN
));
900 if (cmd
!= NL80211_CMD_FRAME_TX_STATUS
&& !(data
[4] & 0x01) &&
901 os_memcmp(bss
->addr
, data
+ 4, ETH_ALEN
) != 0 &&
902 (is_zero_ether_addr(bss
->rand_addr
) ||
903 os_memcmp(bss
->rand_addr
, data
+ 4, ETH_ALEN
) != 0) &&
904 os_memcmp(bss
->addr
, data
+ 4 + ETH_ALEN
, ETH_ALEN
) != 0) {
905 wpa_printf(MSG_MSGDUMP
, "nl80211: %s: Ignore MLME frame event "
906 "for foreign address", bss
->ifname
);
909 wpa_hexdump(MSG_MSGDUMP
, "nl80211: MLME event frame",
910 nla_data(frame
), nla_len(frame
));
913 case NL80211_CMD_AUTHENTICATE
:
914 mlme_event_auth(drv
, nla_data(frame
), nla_len(frame
));
916 case NL80211_CMD_ASSOCIATE
:
917 mlme_event_assoc(drv
, nla_data(frame
), nla_len(frame
), wmm
);
919 case NL80211_CMD_DEAUTHENTICATE
:
920 mlme_event_deauth_disassoc(drv
, EVENT_DEAUTH
,
921 nla_data(frame
), nla_len(frame
));
923 case NL80211_CMD_DISASSOCIATE
:
924 mlme_event_deauth_disassoc(drv
, EVENT_DISASSOC
,
925 nla_data(frame
), nla_len(frame
));
927 case NL80211_CMD_FRAME
:
928 mlme_event_mgmt(bss
, freq
, sig
, nla_data(frame
),
931 case NL80211_CMD_FRAME_TX_STATUS
:
932 mlme_event_mgmt_tx_status(drv
, cookie
, nla_data(frame
),
933 nla_len(frame
), ack
);
935 case NL80211_CMD_UNPROT_DEAUTHENTICATE
:
936 mlme_event_unprot_disconnect(drv
, EVENT_UNPROT_DEAUTH
,
937 nla_data(frame
), nla_len(frame
));
939 case NL80211_CMD_UNPROT_DISASSOCIATE
:
940 mlme_event_unprot_disconnect(drv
, EVENT_UNPROT_DISASSOC
,
941 nla_data(frame
), nla_len(frame
));
949 static void mlme_event_michael_mic_failure(struct i802_bss
*bss
,
952 union wpa_event_data data
;
954 wpa_printf(MSG_DEBUG
, "nl80211: MLME event Michael MIC failure");
955 os_memset(&data
, 0, sizeof(data
));
956 if (tb
[NL80211_ATTR_MAC
]) {
957 wpa_hexdump(MSG_DEBUG
, "nl80211: Source MAC address",
958 nla_data(tb
[NL80211_ATTR_MAC
]),
959 nla_len(tb
[NL80211_ATTR_MAC
]));
960 data
.michael_mic_failure
.src
= nla_data(tb
[NL80211_ATTR_MAC
]);
962 if (tb
[NL80211_ATTR_KEY_SEQ
]) {
963 wpa_hexdump(MSG_DEBUG
, "nl80211: TSC",
964 nla_data(tb
[NL80211_ATTR_KEY_SEQ
]),
965 nla_len(tb
[NL80211_ATTR_KEY_SEQ
]));
967 if (tb
[NL80211_ATTR_KEY_TYPE
]) {
968 enum nl80211_key_type key_type
=
969 nla_get_u32(tb
[NL80211_ATTR_KEY_TYPE
]);
970 wpa_printf(MSG_DEBUG
, "nl80211: Key Type %d", key_type
);
971 if (key_type
== NL80211_KEYTYPE_PAIRWISE
)
972 data
.michael_mic_failure
.unicast
= 1;
974 data
.michael_mic_failure
.unicast
= 1;
976 if (tb
[NL80211_ATTR_KEY_IDX
]) {
977 u8 key_id
= nla_get_u8(tb
[NL80211_ATTR_KEY_IDX
]);
978 wpa_printf(MSG_DEBUG
, "nl80211: Key Id %d", key_id
);
981 wpa_supplicant_event(bss
->ctx
, EVENT_MICHAEL_MIC_FAILURE
, &data
);
985 static void mlme_event_join_ibss(struct wpa_driver_nl80211_data
*drv
,
989 union wpa_event_data event
;
991 if (tb
[NL80211_ATTR_MAC
] == NULL
) {
992 wpa_printf(MSG_DEBUG
, "nl80211: No address in IBSS joined "
996 os_memcpy(drv
->bssid
, nla_data(tb
[NL80211_ATTR_MAC
]), ETH_ALEN
);
999 wpa_printf(MSG_DEBUG
, "nl80211: IBSS " MACSTR
" joined",
1000 MAC2STR(drv
->bssid
));
1002 freq
= nl80211_get_assoc_freq(drv
);
1004 wpa_printf(MSG_DEBUG
, "nl80211: IBSS on frequency %u MHz",
1006 drv
->first_bss
->freq
= freq
;
1009 os_memset(&event
, 0, sizeof(event
));
1010 event
.assoc_info
.freq
= freq
;
1012 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC
, &event
);
1016 static void mlme_event_remain_on_channel(struct wpa_driver_nl80211_data
*drv
,
1017 int cancel_event
, struct nlattr
*tb
[])
1019 unsigned int freq
, chan_type
, duration
;
1020 union wpa_event_data data
;
1023 if (tb
[NL80211_ATTR_WIPHY_FREQ
])
1024 freq
= nla_get_u32(tb
[NL80211_ATTR_WIPHY_FREQ
]);
1028 if (tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
])
1029 chan_type
= nla_get_u32(tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
]);
1033 if (tb
[NL80211_ATTR_DURATION
])
1034 duration
= nla_get_u32(tb
[NL80211_ATTR_DURATION
]);
1038 if (tb
[NL80211_ATTR_COOKIE
])
1039 cookie
= nla_get_u64(tb
[NL80211_ATTR_COOKIE
]);
1043 wpa_printf(MSG_DEBUG
, "nl80211: Remain-on-channel event (cancel=%d "
1044 "freq=%u channel_type=%u duration=%u cookie=0x%llx (%s))",
1045 cancel_event
, freq
, chan_type
, duration
,
1046 (long long unsigned int) cookie
,
1047 cookie
== drv
->remain_on_chan_cookie
? "match" : "unknown");
1049 if (cookie
!= drv
->remain_on_chan_cookie
)
1050 return; /* not for us */
1053 drv
->pending_remain_on_chan
= 0;
1055 os_memset(&data
, 0, sizeof(data
));
1056 data
.remain_on_channel
.freq
= freq
;
1057 data
.remain_on_channel
.duration
= duration
;
1058 wpa_supplicant_event(drv
->ctx
, cancel_event
?
1059 EVENT_CANCEL_REMAIN_ON_CHANNEL
:
1060 EVENT_REMAIN_ON_CHANNEL
, &data
);
1064 static void mlme_event_ft_event(struct wpa_driver_nl80211_data
*drv
,
1065 struct nlattr
*tb
[])
1067 union wpa_event_data data
;
1069 os_memset(&data
, 0, sizeof(data
));
1071 if (tb
[NL80211_ATTR_IE
]) {
1072 data
.ft_ies
.ies
= nla_data(tb
[NL80211_ATTR_IE
]);
1073 data
.ft_ies
.ies_len
= nla_len(tb
[NL80211_ATTR_IE
]);
1076 if (tb
[NL80211_ATTR_IE_RIC
]) {
1077 data
.ft_ies
.ric_ies
= nla_data(tb
[NL80211_ATTR_IE_RIC
]);
1078 data
.ft_ies
.ric_ies_len
= nla_len(tb
[NL80211_ATTR_IE_RIC
]);
1081 if (tb
[NL80211_ATTR_MAC
])
1082 os_memcpy(data
.ft_ies
.target_ap
,
1083 nla_data(tb
[NL80211_ATTR_MAC
]), ETH_ALEN
);
1085 wpa_printf(MSG_DEBUG
, "nl80211: FT event target_ap " MACSTR
,
1086 MAC2STR(data
.ft_ies
.target_ap
));
1088 wpa_supplicant_event(drv
->ctx
, EVENT_FT_RESPONSE
, &data
);
1092 static void send_scan_event(struct wpa_driver_nl80211_data
*drv
, int aborted
,
1093 struct nlattr
*tb
[], int external_scan
)
1095 union wpa_event_data event
;
1098 struct scan_info
*info
;
1099 #define MAX_REPORT_FREQS 50
1100 int freqs
[MAX_REPORT_FREQS
];
1103 if (!external_scan
&& drv
->scan_for_auth
) {
1104 drv
->scan_for_auth
= 0;
1105 wpa_printf(MSG_DEBUG
, "nl80211: Scan results for missing "
1106 "cfg80211 BSS entry");
1107 wpa_driver_nl80211_authenticate_retry(drv
);
1111 os_memset(&event
, 0, sizeof(event
));
1112 info
= &event
.scan_info
;
1113 info
->aborted
= aborted
;
1114 info
->external_scan
= external_scan
;
1115 info
->nl_scan_event
= 1;
1117 if (tb
[NL80211_ATTR_SCAN_SSIDS
]) {
1118 nla_for_each_nested(nl
, tb
[NL80211_ATTR_SCAN_SSIDS
], rem
) {
1119 struct wpa_driver_scan_ssid
*s
=
1120 &info
->ssids
[info
->num_ssids
];
1121 s
->ssid
= nla_data(nl
);
1122 s
->ssid_len
= nla_len(nl
);
1123 wpa_printf(MSG_DEBUG
, "nl80211: Scan probed for SSID '%s'",
1124 wpa_ssid_txt(s
->ssid
, s
->ssid_len
));
1126 if (info
->num_ssids
== WPAS_MAX_SCAN_SSIDS
)
1130 if (tb
[NL80211_ATTR_SCAN_FREQUENCIES
]) {
1131 char msg
[300], *pos
, *end
;
1135 end
= pos
+ sizeof(msg
);
1138 nla_for_each_nested(nl
, tb
[NL80211_ATTR_SCAN_FREQUENCIES
], rem
)
1140 freqs
[num_freqs
] = nla_get_u32(nl
);
1141 res
= os_snprintf(pos
, end
- pos
, " %d",
1143 if (!os_snprintf_error(end
- pos
, res
))
1146 if (num_freqs
== MAX_REPORT_FREQS
- 1)
1149 info
->freqs
= freqs
;
1150 info
->num_freqs
= num_freqs
;
1151 wpa_printf(MSG_DEBUG
, "nl80211: Scan included frequencies:%s",
1155 if (tb
[NL80211_ATTR_SCAN_START_TIME_TSF
] &&
1156 tb
[NL80211_ATTR_SCAN_START_TIME_TSF_BSSID
]) {
1157 info
->scan_start_tsf
=
1158 nla_get_u64(tb
[NL80211_ATTR_SCAN_START_TIME_TSF
]);
1159 os_memcpy(info
->scan_start_tsf_bssid
,
1160 nla_data(tb
[NL80211_ATTR_SCAN_START_TIME_TSF_BSSID
]),
1164 wpa_supplicant_event(drv
->ctx
, EVENT_SCAN_RESULTS
, &event
);
1168 static void nl80211_cqm_event(struct wpa_driver_nl80211_data
*drv
,
1169 struct nlattr
*tb
[])
1171 static struct nla_policy cqm_policy
[NL80211_ATTR_CQM_MAX
+ 1] = {
1172 [NL80211_ATTR_CQM_RSSI_THOLD
] = { .type
= NLA_U32
},
1173 [NL80211_ATTR_CQM_RSSI_HYST
] = { .type
= NLA_U8
},
1174 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT
] = { .type
= NLA_U32
},
1175 [NL80211_ATTR_CQM_PKT_LOSS_EVENT
] = { .type
= NLA_U32
},
1176 [NL80211_ATTR_CQM_TXE_RATE
] = { .type
= NLA_U32
},
1177 [NL80211_ATTR_CQM_TXE_PKTS
] = { .type
= NLA_U32
},
1178 [NL80211_ATTR_CQM_TXE_INTVL
] = { .type
= NLA_U32
},
1179 [NL80211_ATTR_CQM_BEACON_LOSS_EVENT
] = { .type
= NLA_FLAG
},
1181 struct nlattr
*cqm
[NL80211_ATTR_CQM_MAX
+ 1];
1182 enum nl80211_cqm_rssi_threshold_event event
;
1183 union wpa_event_data ed
;
1184 struct wpa_signal_info sig
;
1187 if (tb
[NL80211_ATTR_CQM
] == NULL
||
1188 nla_parse_nested(cqm
, NL80211_ATTR_CQM_MAX
, tb
[NL80211_ATTR_CQM
],
1190 wpa_printf(MSG_DEBUG
, "nl80211: Ignore invalid CQM event");
1194 os_memset(&ed
, 0, sizeof(ed
));
1196 if (cqm
[NL80211_ATTR_CQM_PKT_LOSS_EVENT
]) {
1197 if (!tb
[NL80211_ATTR_MAC
])
1199 os_memcpy(ed
.low_ack
.addr
, nla_data(tb
[NL80211_ATTR_MAC
]),
1201 ed
.low_ack
.num_packets
=
1202 nla_get_u32(cqm
[NL80211_ATTR_CQM_PKT_LOSS_EVENT
]);
1203 wpa_printf(MSG_DEBUG
, "nl80211: Packet loss event for " MACSTR
1204 " (num_packets %u)",
1205 MAC2STR(ed
.low_ack
.addr
), ed
.low_ack
.num_packets
);
1206 wpa_supplicant_event(drv
->ctx
, EVENT_STATION_LOW_ACK
, &ed
);
1210 if (cqm
[NL80211_ATTR_CQM_BEACON_LOSS_EVENT
]) {
1211 wpa_printf(MSG_DEBUG
, "nl80211: Beacon loss event");
1212 wpa_supplicant_event(drv
->ctx
, EVENT_BEACON_LOSS
, NULL
);
1216 if (cqm
[NL80211_ATTR_CQM_TXE_RATE
] &&
1217 cqm
[NL80211_ATTR_CQM_TXE_PKTS
] &&
1218 cqm
[NL80211_ATTR_CQM_TXE_INTVL
] &&
1219 cqm
[NL80211_ATTR_MAC
]) {
1220 wpa_printf(MSG_DEBUG
, "nl80211: CQM TXE event for " MACSTR
1221 " (rate: %u pkts: %u interval: %u)",
1222 MAC2STR((u8
*) nla_data(cqm
[NL80211_ATTR_MAC
])),
1223 nla_get_u32(cqm
[NL80211_ATTR_CQM_TXE_RATE
]),
1224 nla_get_u32(cqm
[NL80211_ATTR_CQM_TXE_PKTS
]),
1225 nla_get_u32(cqm
[NL80211_ATTR_CQM_TXE_INTVL
]));
1229 if (cqm
[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT
] == NULL
) {
1230 wpa_printf(MSG_DEBUG
,
1231 "nl80211: Not a CQM RSSI threshold event");
1234 event
= nla_get_u32(cqm
[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT
]);
1236 if (event
== NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH
) {
1237 wpa_printf(MSG_DEBUG
, "nl80211: Connection quality monitor "
1238 "event: RSSI high");
1239 ed
.signal_change
.above_threshold
= 1;
1240 } else if (event
== NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW
) {
1241 wpa_printf(MSG_DEBUG
, "nl80211: Connection quality monitor "
1243 ed
.signal_change
.above_threshold
= 0;
1245 wpa_printf(MSG_DEBUG
,
1246 "nl80211: Unknown CQM RSSI threshold event: %d",
1251 res
= nl80211_get_link_signal(drv
, &sig
);
1253 ed
.signal_change
.current_signal
= sig
.current_signal
;
1254 ed
.signal_change
.current_txrate
= sig
.current_txrate
;
1255 wpa_printf(MSG_DEBUG
, "nl80211: Signal: %d dBm txrate: %d",
1256 sig
.current_signal
, sig
.current_txrate
);
1259 res
= nl80211_get_link_noise(drv
, &sig
);
1261 ed
.signal_change
.current_noise
= sig
.current_noise
;
1262 wpa_printf(MSG_DEBUG
, "nl80211: Noise: %d dBm",
1266 wpa_supplicant_event(drv
->ctx
, EVENT_SIGNAL_CHANGE
, &ed
);
1270 static void nl80211_new_peer_candidate(struct wpa_driver_nl80211_data
*drv
,
1274 union wpa_event_data data
;
1276 if (drv
->nlmode
!= NL80211_IFTYPE_MESH_POINT
||
1277 !tb
[NL80211_ATTR_MAC
] || !tb
[NL80211_ATTR_IE
])
1280 addr
= nla_data(tb
[NL80211_ATTR_MAC
]);
1281 wpa_printf(MSG_DEBUG
, "nl80211: New peer candidate " MACSTR
,
1284 os_memset(&data
, 0, sizeof(data
));
1285 data
.mesh_peer
.peer
= addr
;
1286 data
.mesh_peer
.ies
= nla_data(tb
[NL80211_ATTR_IE
]);
1287 data
.mesh_peer
.ie_len
= nla_len(tb
[NL80211_ATTR_IE
]);
1288 wpa_supplicant_event(drv
->ctx
, EVENT_NEW_PEER_CANDIDATE
, &data
);
1292 static void nl80211_new_station_event(struct wpa_driver_nl80211_data
*drv
,
1293 struct i802_bss
*bss
,
1297 union wpa_event_data data
;
1299 if (tb
[NL80211_ATTR_MAC
] == NULL
)
1301 addr
= nla_data(tb
[NL80211_ATTR_MAC
]);
1302 wpa_printf(MSG_DEBUG
, "nl80211: New station " MACSTR
, MAC2STR(addr
));
1304 if (is_ap_interface(drv
->nlmode
) && drv
->device_ap_sme
) {
1307 if (tb
[NL80211_ATTR_IE
]) {
1308 ies
= nla_data(tb
[NL80211_ATTR_IE
]);
1309 ies_len
= nla_len(tb
[NL80211_ATTR_IE
]);
1311 wpa_hexdump(MSG_DEBUG
, "nl80211: Assoc Req IEs", ies
, ies_len
);
1312 drv_event_assoc(bss
->ctx
, addr
, ies
, ies_len
, 0);
1316 if (drv
->nlmode
!= NL80211_IFTYPE_ADHOC
)
1319 os_memset(&data
, 0, sizeof(data
));
1320 os_memcpy(data
.ibss_rsn_start
.peer
, addr
, ETH_ALEN
);
1321 wpa_supplicant_event(bss
->ctx
, EVENT_IBSS_RSN_START
, &data
);
1325 static void nl80211_del_station_event(struct wpa_driver_nl80211_data
*drv
,
1326 struct i802_bss
*bss
,
1330 union wpa_event_data data
;
1332 if (tb
[NL80211_ATTR_MAC
] == NULL
)
1334 addr
= nla_data(tb
[NL80211_ATTR_MAC
]);
1335 wpa_printf(MSG_DEBUG
, "nl80211: Delete station " MACSTR
,
1338 if (is_ap_interface(drv
->nlmode
) && drv
->device_ap_sme
) {
1339 drv_event_disassoc(bss
->ctx
, addr
);
1343 if (drv
->nlmode
!= NL80211_IFTYPE_ADHOC
)
1346 os_memset(&data
, 0, sizeof(data
));
1347 os_memcpy(data
.ibss_peer_lost
.peer
, addr
, ETH_ALEN
);
1348 wpa_supplicant_event(bss
->ctx
, EVENT_IBSS_PEER_LOST
, &data
);
1352 static void nl80211_rekey_offload_event(struct wpa_driver_nl80211_data
*drv
,
1355 struct nlattr
*rekey_info
[NUM_NL80211_REKEY_DATA
];
1356 static struct nla_policy rekey_policy
[NUM_NL80211_REKEY_DATA
] = {
1357 [NL80211_REKEY_DATA_KEK
] = {
1358 .minlen
= NL80211_KEK_LEN
,
1359 .maxlen
= NL80211_KEK_LEN
,
1361 [NL80211_REKEY_DATA_KCK
] = {
1362 .minlen
= NL80211_KCK_LEN
,
1363 .maxlen
= NL80211_KCK_LEN
,
1365 [NL80211_REKEY_DATA_REPLAY_CTR
] = {
1366 .minlen
= NL80211_REPLAY_CTR_LEN
,
1367 .maxlen
= NL80211_REPLAY_CTR_LEN
,
1370 union wpa_event_data data
;
1372 if (!tb
[NL80211_ATTR_MAC
] ||
1373 !tb
[NL80211_ATTR_REKEY_DATA
] ||
1374 nla_parse_nested(rekey_info
, MAX_NL80211_REKEY_DATA
,
1375 tb
[NL80211_ATTR_REKEY_DATA
], rekey_policy
) ||
1376 !rekey_info
[NL80211_REKEY_DATA_REPLAY_CTR
])
1379 os_memset(&data
, 0, sizeof(data
));
1380 data
.driver_gtk_rekey
.bssid
= nla_data(tb
[NL80211_ATTR_MAC
]);
1381 wpa_printf(MSG_DEBUG
, "nl80211: Rekey offload event for BSSID " MACSTR
,
1382 MAC2STR(data
.driver_gtk_rekey
.bssid
));
1383 data
.driver_gtk_rekey
.replay_ctr
=
1384 nla_data(rekey_info
[NL80211_REKEY_DATA_REPLAY_CTR
]);
1385 wpa_hexdump(MSG_DEBUG
, "nl80211: Rekey offload - Replay Counter",
1386 data
.driver_gtk_rekey
.replay_ctr
, NL80211_REPLAY_CTR_LEN
);
1387 wpa_supplicant_event(drv
->ctx
, EVENT_DRIVER_GTK_REKEY
, &data
);
1391 static void nl80211_pmksa_candidate_event(struct wpa_driver_nl80211_data
*drv
,
1394 struct nlattr
*cand
[NUM_NL80211_PMKSA_CANDIDATE
];
1395 static struct nla_policy cand_policy
[NUM_NL80211_PMKSA_CANDIDATE
] = {
1396 [NL80211_PMKSA_CANDIDATE_INDEX
] = { .type
= NLA_U32
},
1397 [NL80211_PMKSA_CANDIDATE_BSSID
] = {
1401 [NL80211_PMKSA_CANDIDATE_PREAUTH
] = { .type
= NLA_FLAG
},
1403 union wpa_event_data data
;
1405 wpa_printf(MSG_DEBUG
, "nl80211: PMKSA candidate event");
1407 if (!tb
[NL80211_ATTR_PMKSA_CANDIDATE
] ||
1408 nla_parse_nested(cand
, MAX_NL80211_PMKSA_CANDIDATE
,
1409 tb
[NL80211_ATTR_PMKSA_CANDIDATE
], cand_policy
) ||
1410 !cand
[NL80211_PMKSA_CANDIDATE_INDEX
] ||
1411 !cand
[NL80211_PMKSA_CANDIDATE_BSSID
])
1414 os_memset(&data
, 0, sizeof(data
));
1415 os_memcpy(data
.pmkid_candidate
.bssid
,
1416 nla_data(cand
[NL80211_PMKSA_CANDIDATE_BSSID
]), ETH_ALEN
);
1417 data
.pmkid_candidate
.index
=
1418 nla_get_u32(cand
[NL80211_PMKSA_CANDIDATE_INDEX
]);
1419 data
.pmkid_candidate
.preauth
=
1420 cand
[NL80211_PMKSA_CANDIDATE_PREAUTH
] != NULL
;
1421 wpa_supplicant_event(drv
->ctx
, EVENT_PMKID_CANDIDATE
, &data
);
1425 static void nl80211_client_probe_event(struct wpa_driver_nl80211_data
*drv
,
1428 union wpa_event_data data
;
1430 wpa_printf(MSG_DEBUG
, "nl80211: Probe client event");
1432 if (!tb
[NL80211_ATTR_MAC
] || !tb
[NL80211_ATTR_ACK
])
1435 os_memset(&data
, 0, sizeof(data
));
1436 os_memcpy(data
.client_poll
.addr
,
1437 nla_data(tb
[NL80211_ATTR_MAC
]), ETH_ALEN
);
1439 wpa_supplicant_event(drv
->ctx
, EVENT_DRIVER_CLIENT_POLL_OK
, &data
);
1443 static void nl80211_tdls_oper_event(struct wpa_driver_nl80211_data
*drv
,
1446 union wpa_event_data data
;
1448 wpa_printf(MSG_DEBUG
, "nl80211: TDLS operation event");
1450 if (!tb
[NL80211_ATTR_MAC
] || !tb
[NL80211_ATTR_TDLS_OPERATION
])
1453 os_memset(&data
, 0, sizeof(data
));
1454 os_memcpy(data
.tdls
.peer
, nla_data(tb
[NL80211_ATTR_MAC
]), ETH_ALEN
);
1455 switch (nla_get_u8(tb
[NL80211_ATTR_TDLS_OPERATION
])) {
1456 case NL80211_TDLS_SETUP
:
1457 wpa_printf(MSG_DEBUG
, "nl80211: TDLS setup request for peer "
1458 MACSTR
, MAC2STR(data
.tdls
.peer
));
1459 data
.tdls
.oper
= TDLS_REQUEST_SETUP
;
1461 case NL80211_TDLS_TEARDOWN
:
1462 wpa_printf(MSG_DEBUG
, "nl80211: TDLS teardown request for peer "
1463 MACSTR
, MAC2STR(data
.tdls
.peer
));
1464 data
.tdls
.oper
= TDLS_REQUEST_TEARDOWN
;
1466 case NL80211_TDLS_DISCOVERY_REQ
:
1467 wpa_printf(MSG_DEBUG
,
1468 "nl80211: TDLS discovery request for peer " MACSTR
,
1469 MAC2STR(data
.tdls
.peer
));
1470 data
.tdls
.oper
= TDLS_REQUEST_DISCOVER
;
1473 wpa_printf(MSG_DEBUG
, "nl80211: Unsupported TDLS operatione "
1477 if (tb
[NL80211_ATTR_REASON_CODE
]) {
1478 data
.tdls
.reason_code
=
1479 nla_get_u16(tb
[NL80211_ATTR_REASON_CODE
]);
1482 wpa_supplicant_event(drv
->ctx
, EVENT_TDLS
, &data
);
1486 static void nl80211_stop_ap(struct wpa_driver_nl80211_data
*drv
,
1489 wpa_supplicant_event(drv
->ctx
, EVENT_INTERFACE_UNAVAILABLE
, NULL
);
1493 static void nl80211_connect_failed_event(struct wpa_driver_nl80211_data
*drv
,
1496 union wpa_event_data data
;
1499 wpa_printf(MSG_DEBUG
, "nl80211: Connect failed event");
1501 if (!tb
[NL80211_ATTR_MAC
] || !tb
[NL80211_ATTR_CONN_FAILED_REASON
])
1504 os_memset(&data
, 0, sizeof(data
));
1505 os_memcpy(data
.connect_failed_reason
.addr
,
1506 nla_data(tb
[NL80211_ATTR_MAC
]), ETH_ALEN
);
1508 reason
= nla_get_u32(tb
[NL80211_ATTR_CONN_FAILED_REASON
]);
1510 case NL80211_CONN_FAIL_MAX_CLIENTS
:
1511 wpa_printf(MSG_DEBUG
, "nl80211: Max client reached");
1512 data
.connect_failed_reason
.code
= MAX_CLIENT_REACHED
;
1514 case NL80211_CONN_FAIL_BLOCKED_CLIENT
:
1515 wpa_printf(MSG_DEBUG
, "nl80211: Blocked client " MACSTR
1516 " tried to connect",
1517 MAC2STR(data
.connect_failed_reason
.addr
));
1518 data
.connect_failed_reason
.code
= BLOCKED_CLIENT
;
1521 wpa_printf(MSG_DEBUG
, "nl8021l: Unknown connect failed reason "
1526 wpa_supplicant_event(drv
->ctx
, EVENT_CONNECT_FAILED_REASON
, &data
);
1530 static void nl80211_radar_event(struct wpa_driver_nl80211_data
*drv
,
1533 union wpa_event_data data
;
1534 enum nl80211_radar_event event_type
;
1536 if (!tb
[NL80211_ATTR_WIPHY_FREQ
] || !tb
[NL80211_ATTR_RADAR_EVENT
])
1539 os_memset(&data
, 0, sizeof(data
));
1540 data
.dfs_event
.freq
= nla_get_u32(tb
[NL80211_ATTR_WIPHY_FREQ
]);
1541 event_type
= nla_get_u32(tb
[NL80211_ATTR_RADAR_EVENT
]);
1543 /* Check HT params */
1544 if (tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
]) {
1545 data
.dfs_event
.ht_enabled
= 1;
1546 data
.dfs_event
.chan_offset
= 0;
1548 switch (nla_get_u32(tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
])) {
1549 case NL80211_CHAN_NO_HT
:
1550 data
.dfs_event
.ht_enabled
= 0;
1552 case NL80211_CHAN_HT20
:
1554 case NL80211_CHAN_HT40PLUS
:
1555 data
.dfs_event
.chan_offset
= 1;
1557 case NL80211_CHAN_HT40MINUS
:
1558 data
.dfs_event
.chan_offset
= -1;
1563 /* Get VHT params */
1564 if (tb
[NL80211_ATTR_CHANNEL_WIDTH
])
1565 data
.dfs_event
.chan_width
=
1566 convert2width(nla_get_u32(
1567 tb
[NL80211_ATTR_CHANNEL_WIDTH
]));
1568 if (tb
[NL80211_ATTR_CENTER_FREQ1
])
1569 data
.dfs_event
.cf1
= nla_get_u32(tb
[NL80211_ATTR_CENTER_FREQ1
]);
1570 if (tb
[NL80211_ATTR_CENTER_FREQ2
])
1571 data
.dfs_event
.cf2
= nla_get_u32(tb
[NL80211_ATTR_CENTER_FREQ2
]);
1573 wpa_printf(MSG_DEBUG
, "nl80211: DFS event on freq %d MHz, ht: %d, offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz",
1574 data
.dfs_event
.freq
, data
.dfs_event
.ht_enabled
,
1575 data
.dfs_event
.chan_offset
, data
.dfs_event
.chan_width
,
1576 data
.dfs_event
.cf1
, data
.dfs_event
.cf2
);
1578 switch (event_type
) {
1579 case NL80211_RADAR_DETECTED
:
1580 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_RADAR_DETECTED
, &data
);
1582 case NL80211_RADAR_CAC_FINISHED
:
1583 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_CAC_FINISHED
, &data
);
1585 case NL80211_RADAR_CAC_ABORTED
:
1586 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_CAC_ABORTED
, &data
);
1588 case NL80211_RADAR_NOP_FINISHED
:
1589 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_NOP_FINISHED
, &data
);
1591 case NL80211_RADAR_PRE_CAC_EXPIRED
:
1592 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_PRE_CAC_EXPIRED
,
1596 wpa_printf(MSG_DEBUG
, "nl80211: Unknown radar event %d "
1597 "received", event_type
);
1603 static void nl80211_spurious_frame(struct i802_bss
*bss
, struct nlattr
**tb
,
1606 struct wpa_driver_nl80211_data
*drv
= bss
->drv
;
1607 union wpa_event_data event
;
1609 if (!tb
[NL80211_ATTR_MAC
])
1612 os_memset(&event
, 0, sizeof(event
));
1613 event
.rx_from_unknown
.bssid
= bss
->addr
;
1614 event
.rx_from_unknown
.addr
= nla_data(tb
[NL80211_ATTR_MAC
]);
1615 event
.rx_from_unknown
.wds
= wds
;
1617 wpa_supplicant_event(drv
->ctx
, EVENT_RX_FROM_UNKNOWN
, &event
);
1621 #ifdef CONFIG_DRIVER_NL80211_QCA
1623 static void qca_nl80211_avoid_freq(struct wpa_driver_nl80211_data
*drv
,
1624 const u8
*data
, size_t len
)
1627 union wpa_event_data event
;
1628 struct wpa_freq_range
*range
= NULL
;
1629 const struct qca_avoid_freq_list
*freq_range
;
1631 freq_range
= (const struct qca_avoid_freq_list
*) data
;
1632 if (len
< sizeof(freq_range
->count
))
1635 count
= freq_range
->count
;
1636 if (len
< sizeof(freq_range
->count
) +
1637 count
* sizeof(struct qca_avoid_freq_range
)) {
1638 wpa_printf(MSG_DEBUG
, "nl80211: Ignored too short avoid frequency list (len=%u)",
1639 (unsigned int) len
);
1644 range
= os_calloc(count
, sizeof(struct wpa_freq_range
));
1649 os_memset(&event
, 0, sizeof(event
));
1650 for (i
= 0; i
< count
; i
++) {
1651 unsigned int idx
= event
.freq_range
.num
;
1652 range
[idx
].min
= freq_range
->range
[i
].start_freq
;
1653 range
[idx
].max
= freq_range
->range
[i
].end_freq
;
1654 wpa_printf(MSG_DEBUG
, "nl80211: Avoid frequency range: %u-%u",
1655 range
[idx
].min
, range
[idx
].max
);
1656 if (range
[idx
].min
> range
[idx
].max
) {
1657 wpa_printf(MSG_DEBUG
, "nl80211: Ignore invalid frequency range");
1660 event
.freq_range
.num
++;
1662 event
.freq_range
.range
= range
;
1664 wpa_supplicant_event(drv
->ctx
, EVENT_AVOID_FREQUENCIES
, &event
);
1670 static enum hostapd_hw_mode
get_qca_hw_mode(u8 hw_mode
)
1673 case QCA_ACS_MODE_IEEE80211B
:
1674 return HOSTAPD_MODE_IEEE80211B
;
1675 case QCA_ACS_MODE_IEEE80211G
:
1676 return HOSTAPD_MODE_IEEE80211G
;
1677 case QCA_ACS_MODE_IEEE80211A
:
1678 return HOSTAPD_MODE_IEEE80211A
;
1679 case QCA_ACS_MODE_IEEE80211AD
:
1680 return HOSTAPD_MODE_IEEE80211AD
;
1681 case QCA_ACS_MODE_IEEE80211ANY
:
1682 return HOSTAPD_MODE_IEEE80211ANY
;
1684 return NUM_HOSTAPD_MODES
;
1689 static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data
*drv
,
1690 const u8
*data
, size_t len
)
1692 struct nlattr
*tb
[QCA_WLAN_VENDOR_ATTR_ACS_MAX
+ 1];
1693 union wpa_event_data event
;
1695 wpa_printf(MSG_DEBUG
,
1696 "nl80211: ACS channel selection vendor event received");
1698 if (nla_parse(tb
, QCA_WLAN_VENDOR_ATTR_ACS_MAX
,
1699 (struct nlattr
*) data
, len
, NULL
) ||
1700 !tb
[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL
] ||
1701 !tb
[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL
])
1704 os_memset(&event
, 0, sizeof(event
));
1705 event
.acs_selected_channels
.pri_channel
=
1706 nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL
]);
1707 event
.acs_selected_channels
.sec_channel
=
1708 nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL
]);
1709 if (tb
[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL
])
1710 event
.acs_selected_channels
.vht_seg0_center_ch
=
1711 nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL
]);
1712 if (tb
[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL
])
1713 event
.acs_selected_channels
.vht_seg1_center_ch
=
1714 nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL
]);
1715 if (tb
[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH
])
1716 event
.acs_selected_channels
.ch_width
=
1717 nla_get_u16(tb
[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH
]);
1718 if (tb
[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE
]) {
1719 u8 hw_mode
= nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE
]);
1721 event
.acs_selected_channels
.hw_mode
= get_qca_hw_mode(hw_mode
);
1722 if (event
.acs_selected_channels
.hw_mode
== NUM_HOSTAPD_MODES
||
1723 event
.acs_selected_channels
.hw_mode
==
1724 HOSTAPD_MODE_IEEE80211ANY
) {
1725 wpa_printf(MSG_DEBUG
,
1726 "nl80211: Invalid hw_mode %d in ACS selection event",
1732 wpa_printf(MSG_INFO
,
1733 "nl80211: ACS Results: PCH: %d SCH: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d",
1734 event
.acs_selected_channels
.pri_channel
,
1735 event
.acs_selected_channels
.sec_channel
,
1736 event
.acs_selected_channels
.ch_width
,
1737 event
.acs_selected_channels
.vht_seg0_center_ch
,
1738 event
.acs_selected_channels
.vht_seg1_center_ch
,
1739 event
.acs_selected_channels
.hw_mode
);
1741 /* Ignore ACS channel list check for backwards compatibility */
1743 wpa_supplicant_event(drv
->ctx
, EVENT_ACS_CHANNEL_SELECTED
, &event
);
1747 static void qca_nl80211_key_mgmt_auth(struct wpa_driver_nl80211_data
*drv
,
1748 const u8
*data
, size_t len
)
1750 struct nlattr
*tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX
+ 1];
1753 wpa_printf(MSG_DEBUG
,
1754 "nl80211: Key management roam+auth vendor event received");
1756 if (nla_parse(tb
, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX
,
1757 (struct nlattr
*) data
, len
, NULL
) ||
1758 !tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID
] ||
1759 nla_len(tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID
]) != ETH_ALEN
||
1760 !tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE
] ||
1761 !tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE
] ||
1762 !tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED
])
1765 bssid
= nla_data(tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID
]);
1766 wpa_printf(MSG_DEBUG
, " * roam BSSID " MACSTR
, MAC2STR(bssid
));
1768 mlme_event_connect(drv
, NL80211_CMD_ROAM
, NULL
,
1769 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID
],
1770 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE
],
1771 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE
],
1773 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED
],
1774 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR
],
1775 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK
],
1776 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK
],
1777 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS
],
1778 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM
],
1779 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK
],
1780 tb
[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID
]);
1784 static void qca_nl80211_dfs_offload_radar_event(
1785 struct wpa_driver_nl80211_data
*drv
, u32 subcmd
, u8
*msg
, int length
)
1787 union wpa_event_data data
;
1788 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
1790 wpa_printf(MSG_DEBUG
,
1791 "nl80211: DFS offload radar vendor event received");
1793 if (nla_parse(tb
, NL80211_ATTR_MAX
,
1794 (struct nlattr
*) msg
, length
, NULL
))
1797 if (!tb
[NL80211_ATTR_WIPHY_FREQ
]) {
1798 wpa_printf(MSG_INFO
,
1799 "nl80211: Error parsing WIPHY_FREQ in FS offload radar vendor event");
1803 os_memset(&data
, 0, sizeof(data
));
1804 data
.dfs_event
.freq
= nla_get_u32(tb
[NL80211_ATTR_WIPHY_FREQ
]);
1806 wpa_printf(MSG_DEBUG
, "nl80211: DFS event on freq %d MHz",
1807 data
.dfs_event
.freq
);
1809 /* Check HT params */
1810 if (tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
]) {
1811 data
.dfs_event
.ht_enabled
= 1;
1812 data
.dfs_event
.chan_offset
= 0;
1814 switch (nla_get_u32(tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
])) {
1815 case NL80211_CHAN_NO_HT
:
1816 data
.dfs_event
.ht_enabled
= 0;
1818 case NL80211_CHAN_HT20
:
1820 case NL80211_CHAN_HT40PLUS
:
1821 data
.dfs_event
.chan_offset
= 1;
1823 case NL80211_CHAN_HT40MINUS
:
1824 data
.dfs_event
.chan_offset
= -1;
1829 /* Get VHT params */
1830 if (tb
[NL80211_ATTR_CHANNEL_WIDTH
])
1831 data
.dfs_event
.chan_width
=
1832 convert2width(nla_get_u32(
1833 tb
[NL80211_ATTR_CHANNEL_WIDTH
]));
1834 if (tb
[NL80211_ATTR_CENTER_FREQ1
])
1835 data
.dfs_event
.cf1
= nla_get_u32(tb
[NL80211_ATTR_CENTER_FREQ1
]);
1836 if (tb
[NL80211_ATTR_CENTER_FREQ2
])
1837 data
.dfs_event
.cf2
= nla_get_u32(tb
[NL80211_ATTR_CENTER_FREQ2
]);
1839 wpa_printf(MSG_DEBUG
, "nl80211: DFS event on freq %d MHz, ht: %d, "
1840 "offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz",
1841 data
.dfs_event
.freq
, data
.dfs_event
.ht_enabled
,
1842 data
.dfs_event
.chan_offset
, data
.dfs_event
.chan_width
,
1843 data
.dfs_event
.cf1
, data
.dfs_event
.cf2
);
1846 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
:
1847 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_RADAR_DETECTED
, &data
);
1849 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
:
1850 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_CAC_STARTED
, &data
);
1852 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
:
1853 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_CAC_FINISHED
, &data
);
1855 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
:
1856 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_CAC_ABORTED
, &data
);
1858 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
:
1859 wpa_supplicant_event(drv
->ctx
, EVENT_DFS_NOP_FINISHED
, &data
);
1862 wpa_printf(MSG_DEBUG
,
1863 "nl80211: Unknown DFS offload radar event %d received",
1870 static void qca_nl80211_scan_trigger_event(struct wpa_driver_nl80211_data
*drv
,
1871 u8
*data
, size_t len
)
1873 struct nlattr
*tb
[QCA_WLAN_VENDOR_ATTR_SCAN_MAX
+ 1];
1875 union wpa_event_data event
;
1876 struct scan_info
*info
;
1878 if (nla_parse(tb
, QCA_WLAN_VENDOR_ATTR_SCAN_MAX
,
1879 (struct nlattr
*) data
, len
, NULL
) ||
1880 !tb
[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE
])
1883 cookie
= nla_get_u64(tb
[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE
]);
1884 if (cookie
!= drv
->vendor_scan_cookie
) {
1885 /* External scan trigger event, ignore */
1889 /* Cookie match, own scan */
1890 os_memset(&event
, 0, sizeof(event
));
1891 info
= &event
.scan_info
;
1892 info
->external_scan
= 0;
1893 info
->nl_scan_event
= 0;
1895 drv
->scan_state
= SCAN_STARTED
;
1896 wpa_supplicant_event(drv
->ctx
, EVENT_SCAN_STARTED
, &event
);
1900 static void send_vendor_scan_event(struct wpa_driver_nl80211_data
*drv
,
1901 int aborted
, struct nlattr
*tb
[],
1904 union wpa_event_data event
;
1907 struct scan_info
*info
;
1908 int freqs
[MAX_REPORT_FREQS
];
1911 os_memset(&event
, 0, sizeof(event
));
1912 info
= &event
.scan_info
;
1913 info
->aborted
= aborted
;
1914 info
->external_scan
= external_scan
;
1916 if (tb
[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS
]) {
1917 nla_for_each_nested(nl
,
1918 tb
[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS
], rem
) {
1919 struct wpa_driver_scan_ssid
*s
=
1920 &info
->ssids
[info
->num_ssids
];
1921 s
->ssid
= nla_data(nl
);
1922 s
->ssid_len
= nla_len(nl
);
1923 wpa_printf(MSG_DEBUG
,
1924 "nl80211: Scan probed for SSID '%s'",
1925 wpa_ssid_txt(s
->ssid
, s
->ssid_len
));
1927 if (info
->num_ssids
== WPAS_MAX_SCAN_SSIDS
)
1932 if (tb
[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES
]) {
1933 char msg
[300], *pos
, *end
;
1937 end
= pos
+ sizeof(msg
);
1940 nla_for_each_nested(nl
,
1941 tb
[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES
],
1943 freqs
[num_freqs
] = nla_get_u32(nl
);
1944 res
= os_snprintf(pos
, end
- pos
, " %d",
1946 if (!os_snprintf_error(end
- pos
, res
))
1949 if (num_freqs
== MAX_REPORT_FREQS
- 1)
1953 info
->freqs
= freqs
;
1954 info
->num_freqs
= num_freqs
;
1955 wpa_printf(MSG_DEBUG
, "nl80211: Scan included frequencies:%s",
1958 wpa_supplicant_event(drv
->ctx
, EVENT_SCAN_RESULTS
, &event
);
1962 static void qca_nl80211_scan_done_event(struct wpa_driver_nl80211_data
*drv
,
1963 u8
*data
, size_t len
)
1965 struct nlattr
*tb
[QCA_WLAN_VENDOR_ATTR_SCAN_MAX
+ 1];
1967 enum scan_status status
;
1970 if (nla_parse(tb
, QCA_WLAN_VENDOR_ATTR_SCAN_MAX
,
1971 (struct nlattr
*) data
, len
, NULL
) ||
1972 !tb
[QCA_WLAN_VENDOR_ATTR_SCAN_STATUS
] ||
1973 !tb
[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE
])
1976 status
= nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_SCAN_STATUS
]);
1977 if (status
>= VENDOR_SCAN_STATUS_MAX
)
1978 return; /* invalid status */
1980 cookie
= nla_get_u64(tb
[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE
]);
1981 if (cookie
!= drv
->vendor_scan_cookie
) {
1982 /* Event from an external scan, get scan results */
1986 if (status
== VENDOR_SCAN_STATUS_NEW_RESULTS
)
1987 drv
->scan_state
= SCAN_COMPLETED
;
1989 drv
->scan_state
= SCAN_ABORTED
;
1991 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout
, drv
,
1993 drv
->vendor_scan_cookie
= 0;
1994 drv
->last_scan_cmd
= 0;
1997 send_vendor_scan_event(drv
, (status
== VENDOR_SCAN_STATUS_ABORTED
), tb
,
2002 static void qca_nl80211_p2p_lo_stop_event(struct wpa_driver_nl80211_data
*drv
,
2003 u8
*data
, size_t len
)
2005 struct nlattr
*tb
[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX
+ 1];
2006 union wpa_event_data event
;
2008 wpa_printf(MSG_DEBUG
,
2009 "nl80211: P2P listen offload stop vendor event received");
2011 if (nla_parse(tb
, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX
,
2012 (struct nlattr
*) data
, len
, NULL
) ||
2013 !tb
[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON
])
2016 os_memset(&event
, 0, sizeof(event
));
2017 event
.p2p_lo_stop
.reason_code
=
2018 nla_get_u8(tb
[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON
]);
2020 wpa_printf(MSG_DEBUG
,
2021 "nl80211: P2P Listen offload stop reason: %d",
2022 event
.p2p_lo_stop
.reason_code
);
2023 wpa_supplicant_event(drv
->ctx
, EVENT_P2P_LO_STOP
, &event
);
2026 #endif /* CONFIG_DRIVER_NL80211_QCA */
2029 static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data
*drv
,
2030 u32 subcmd
, u8
*data
, size_t len
)
2033 case QCA_NL80211_VENDOR_SUBCMD_TEST
:
2034 wpa_hexdump(MSG_DEBUG
, "nl80211: QCA test event", data
, len
);
2036 #ifdef CONFIG_DRIVER_NL80211_QCA
2037 case QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
:
2038 qca_nl80211_avoid_freq(drv
, data
, len
);
2040 case QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
:
2041 qca_nl80211_key_mgmt_auth(drv
, data
, len
);
2043 case QCA_NL80211_VENDOR_SUBCMD_DO_ACS
:
2044 qca_nl80211_acs_select_ch(drv
, data
, len
);
2046 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
:
2047 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
:
2048 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
:
2049 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
:
2050 case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
:
2051 qca_nl80211_dfs_offload_radar_event(drv
, subcmd
, data
, len
);
2053 case QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
:
2054 qca_nl80211_scan_trigger_event(drv
, data
, len
);
2056 case QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
:
2057 qca_nl80211_scan_done_event(drv
, data
, len
);
2059 case QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
:
2060 qca_nl80211_p2p_lo_stop_event(drv
, data
, len
);
2062 #endif /* CONFIG_DRIVER_NL80211_QCA */
2064 wpa_printf(MSG_DEBUG
,
2065 "nl80211: Ignore unsupported QCA vendor event %u",
2072 static void nl80211_vendor_event(struct wpa_driver_nl80211_data
*drv
,
2075 u32 vendor_id
, subcmd
, wiphy
= 0;
2080 if (!tb
[NL80211_ATTR_VENDOR_ID
] ||
2081 !tb
[NL80211_ATTR_VENDOR_SUBCMD
])
2084 vendor_id
= nla_get_u32(tb
[NL80211_ATTR_VENDOR_ID
]);
2085 subcmd
= nla_get_u32(tb
[NL80211_ATTR_VENDOR_SUBCMD
]);
2087 if (tb
[NL80211_ATTR_WIPHY
])
2088 wiphy
= nla_get_u32(tb
[NL80211_ATTR_WIPHY
]);
2090 wpa_printf(MSG_DEBUG
, "nl80211: Vendor event: wiphy=%u vendor_id=0x%x subcmd=%u",
2091 wiphy
, vendor_id
, subcmd
);
2093 if (tb
[NL80211_ATTR_VENDOR_DATA
]) {
2094 data
= nla_data(tb
[NL80211_ATTR_VENDOR_DATA
]);
2095 len
= nla_len(tb
[NL80211_ATTR_VENDOR_DATA
]);
2096 wpa_hexdump(MSG_MSGDUMP
, "nl80211: Vendor data", data
, len
);
2099 wiphy_idx
= nl80211_get_wiphy_index(drv
->first_bss
);
2100 if (wiphy_idx
>= 0 && wiphy_idx
!= (int) wiphy
) {
2101 wpa_printf(MSG_DEBUG
, "nl80211: Ignore vendor event for foreign wiphy %u (own: %d)",
2106 switch (vendor_id
) {
2108 nl80211_vendor_event_qca(drv
, subcmd
, data
, len
);
2111 wpa_printf(MSG_DEBUG
, "nl80211: Ignore unsupported vendor event");
2117 static void nl80211_reg_change_event(struct wpa_driver_nl80211_data
*drv
,
2118 struct nlattr
*tb
[])
2120 union wpa_event_data data
;
2121 enum nl80211_reg_initiator init
;
2123 wpa_printf(MSG_DEBUG
, "nl80211: Regulatory domain change");
2125 if (tb
[NL80211_ATTR_REG_INITIATOR
] == NULL
)
2128 os_memset(&data
, 0, sizeof(data
));
2129 init
= nla_get_u8(tb
[NL80211_ATTR_REG_INITIATOR
]);
2130 wpa_printf(MSG_DEBUG
, " * initiator=%d", init
);
2132 case NL80211_REGDOM_SET_BY_CORE
:
2133 data
.channel_list_changed
.initiator
= REGDOM_SET_BY_CORE
;
2135 case NL80211_REGDOM_SET_BY_USER
:
2136 data
.channel_list_changed
.initiator
= REGDOM_SET_BY_USER
;
2138 case NL80211_REGDOM_SET_BY_DRIVER
:
2139 data
.channel_list_changed
.initiator
= REGDOM_SET_BY_DRIVER
;
2141 case NL80211_REGDOM_SET_BY_COUNTRY_IE
:
2142 data
.channel_list_changed
.initiator
= REGDOM_SET_BY_COUNTRY_IE
;
2146 if (tb
[NL80211_ATTR_REG_TYPE
]) {
2147 enum nl80211_reg_type type
;
2148 type
= nla_get_u8(tb
[NL80211_ATTR_REG_TYPE
]);
2149 wpa_printf(MSG_DEBUG
, " * type=%d", type
);
2151 case NL80211_REGDOM_TYPE_COUNTRY
:
2152 data
.channel_list_changed
.type
= REGDOM_TYPE_COUNTRY
;
2154 case NL80211_REGDOM_TYPE_WORLD
:
2155 data
.channel_list_changed
.type
= REGDOM_TYPE_WORLD
;
2157 case NL80211_REGDOM_TYPE_CUSTOM_WORLD
:
2158 data
.channel_list_changed
.type
=
2159 REGDOM_TYPE_CUSTOM_WORLD
;
2161 case NL80211_REGDOM_TYPE_INTERSECTION
:
2162 data
.channel_list_changed
.type
=
2163 REGDOM_TYPE_INTERSECTION
;
2168 if (tb
[NL80211_ATTR_REG_ALPHA2
]) {
2169 os_strlcpy(data
.channel_list_changed
.alpha2
,
2170 nla_get_string(tb
[NL80211_ATTR_REG_ALPHA2
]),
2171 sizeof(data
.channel_list_changed
.alpha2
));
2172 wpa_printf(MSG_DEBUG
, " * alpha2=%s",
2173 data
.channel_list_changed
.alpha2
);
2176 wpa_supplicant_event(drv
->ctx
, EVENT_CHANNEL_LIST_CHANGED
, &data
);
2180 static void nl80211_external_auth(struct wpa_driver_nl80211_data
*drv
,
2183 union wpa_event_data event
;
2184 enum nl80211_external_auth_action act
;
2186 if (!tb
[NL80211_ATTR_AKM_SUITES
] ||
2187 !tb
[NL80211_ATTR_EXTERNAL_AUTH_ACTION
] ||
2188 !tb
[NL80211_ATTR_BSSID
] ||
2189 !tb
[NL80211_ATTR_SSID
])
2192 os_memset(&event
, 0, sizeof(event
));
2193 act
= nla_get_u32(tb
[NL80211_ATTR_EXTERNAL_AUTH_ACTION
]);
2195 case NL80211_EXTERNAL_AUTH_START
:
2196 event
.external_auth
.action
= EXT_AUTH_START
;
2198 case NL80211_EXTERNAL_AUTH_ABORT
:
2199 event
.external_auth
.action
= EXT_AUTH_ABORT
;
2205 event
.external_auth
.key_mgmt_suite
=
2206 nla_get_u32(tb
[NL80211_ATTR_AKM_SUITES
]);
2208 event
.external_auth
.ssid_len
= nla_len(tb
[NL80211_ATTR_SSID
]);
2209 if (event
.external_auth
.ssid_len
> SSID_MAX_LEN
)
2211 os_memcpy(event
.external_auth
.ssid
, nla_data(tb
[NL80211_ATTR_SSID
]),
2212 event
.external_auth
.ssid_len
);
2214 os_memcpy(event
.external_auth
.bssid
, nla_data(tb
[NL80211_ATTR_BSSID
]),
2217 wpa_printf(MSG_DEBUG
,
2218 "nl80211: External auth action: %u, AKM: 0x%x",
2219 event
.external_auth
.action
,
2220 event
.external_auth
.key_mgmt_suite
);
2221 wpa_supplicant_event(drv
->ctx
, EVENT_EXTERNAL_AUTH
, &event
);
2225 static void nl80211_port_authorized(struct wpa_driver_nl80211_data
*drv
,
2230 if (!tb
[NL80211_ATTR_MAC
] ||
2231 nla_len(tb
[NL80211_ATTR_MAC
]) != ETH_ALEN
) {
2232 wpa_printf(MSG_DEBUG
,
2233 "nl80211: Ignore port authorized event without BSSID");
2237 addr
= nla_data(tb
[NL80211_ATTR_MAC
]);
2238 if (os_memcmp(addr
, drv
->bssid
, ETH_ALEN
) != 0) {
2239 wpa_printf(MSG_DEBUG
,
2240 "nl80211: Ignore port authorized event for " MACSTR
2241 " (not the currently connected BSSID " MACSTR
")",
2242 MAC2STR(addr
), MAC2STR(drv
->bssid
));
2246 wpa_supplicant_event(drv
->ctx
, EVENT_PORT_AUTHORIZED
, NULL
);
2250 static void nl80211_sta_opmode_change_event(struct wpa_driver_nl80211_data
*drv
,
2253 union wpa_event_data ed
;
2254 u8 smps_mode
, max_bw
;
2256 if (!tb
[NL80211_ATTR_MAC
] ||
2257 (!tb
[NL80211_ATTR_CHANNEL_WIDTH
] &&
2258 !tb
[NL80211_ATTR_SMPS_MODE
] &&
2259 !tb
[NL80211_ATTR_NSS
]))
2262 ed
.sta_opmode
.smps_mode
= SMPS_INVALID
;
2263 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_UNKNOWN
;
2264 ed
.sta_opmode
.rx_nss
= 0xff;
2265 ed
.sta_opmode
.addr
= nla_data(tb
[NL80211_ATTR_MAC
]);
2267 if (tb
[NL80211_ATTR_SMPS_MODE
]) {
2268 smps_mode
= nla_get_u32(tb
[NL80211_ATTR_SMPS_MODE
]);
2269 switch (smps_mode
) {
2270 case NL80211_SMPS_OFF
:
2271 ed
.sta_opmode
.smps_mode
= SMPS_OFF
;
2273 case NL80211_SMPS_STATIC
:
2274 ed
.sta_opmode
.smps_mode
= SMPS_STATIC
;
2276 case NL80211_SMPS_DYNAMIC
:
2277 ed
.sta_opmode
.smps_mode
= SMPS_DYNAMIC
;
2280 ed
.sta_opmode
.smps_mode
= SMPS_INVALID
;
2285 if (tb
[NL80211_ATTR_CHANNEL_WIDTH
]) {
2286 max_bw
= nla_get_u32(tb
[NL80211_ATTR_CHANNEL_WIDTH
]);
2288 case NL80211_CHAN_WIDTH_20_NOHT
:
2289 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_20_NOHT
;
2291 case NL80211_CHAN_WIDTH_20
:
2292 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_20
;
2294 case NL80211_CHAN_WIDTH_40
:
2295 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_40
;
2297 case NL80211_CHAN_WIDTH_80
:
2298 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_80
;
2300 case NL80211_CHAN_WIDTH_80P80
:
2301 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_80P80
;
2303 case NL80211_CHAN_WIDTH_160
:
2304 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_160
;
2307 ed
.sta_opmode
.chan_width
= CHAN_WIDTH_UNKNOWN
;
2313 if (tb
[NL80211_ATTR_NSS
])
2314 ed
.sta_opmode
.rx_nss
= nla_get_u8(tb
[NL80211_ATTR_NSS
]);
2316 wpa_supplicant_event(drv
->ctx
, EVENT_STATION_OPMODE_CHANGED
, &ed
);
2320 static void do_process_drv_event(struct i802_bss
*bss
, int cmd
,
2323 struct wpa_driver_nl80211_data
*drv
= bss
->drv
;
2324 union wpa_event_data data
;
2325 int external_scan_event
= 0;
2327 wpa_printf(MSG_DEBUG
, "nl80211: Drv Event %d (%s) received for %s",
2328 cmd
, nl80211_command_to_string(cmd
), bss
->ifname
);
2330 if (cmd
== NL80211_CMD_ROAM
&&
2331 (drv
->capa
.flags
& WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD
)) {
2333 * Device will use roam+auth vendor event to indicate
2334 * roaming, so ignore the regular roam event.
2336 wpa_printf(MSG_DEBUG
,
2337 "nl80211: Ignore roam event (cmd=%d), device will use vendor event roam+auth",
2342 if (drv
->ap_scan_as_station
!= NL80211_IFTYPE_UNSPECIFIED
&&
2343 (cmd
== NL80211_CMD_NEW_SCAN_RESULTS
||
2344 cmd
== NL80211_CMD_SCAN_ABORTED
)) {
2345 wpa_driver_nl80211_set_mode(drv
->first_bss
,
2346 drv
->ap_scan_as_station
);
2347 drv
->ap_scan_as_station
= NL80211_IFTYPE_UNSPECIFIED
;
2351 case NL80211_CMD_TRIGGER_SCAN
:
2352 wpa_dbg(drv
->ctx
, MSG_DEBUG
, "nl80211: Scan trigger");
2353 drv
->scan_state
= SCAN_STARTED
;
2354 if (drv
->scan_for_auth
) {
2356 * Cannot indicate EVENT_SCAN_STARTED here since we skip
2357 * EVENT_SCAN_RESULTS in scan_for_auth case and the
2358 * upper layer implementation could get confused about
2361 wpa_printf(MSG_DEBUG
, "nl80211: Do not indicate scan-start event due to internal scan_for_auth");
2364 wpa_supplicant_event(drv
->ctx
, EVENT_SCAN_STARTED
, NULL
);
2366 case NL80211_CMD_START_SCHED_SCAN
:
2367 wpa_dbg(drv
->ctx
, MSG_DEBUG
, "nl80211: Sched scan started");
2368 drv
->scan_state
= SCHED_SCAN_STARTED
;
2370 case NL80211_CMD_SCHED_SCAN_STOPPED
:
2371 wpa_dbg(drv
->ctx
, MSG_DEBUG
, "nl80211: Sched scan stopped");
2372 drv
->scan_state
= SCHED_SCAN_STOPPED
;
2373 wpa_supplicant_event(drv
->ctx
, EVENT_SCHED_SCAN_STOPPED
, NULL
);
2375 case NL80211_CMD_NEW_SCAN_RESULTS
:
2376 wpa_dbg(drv
->ctx
, MSG_DEBUG
,
2377 "nl80211: New scan results available");
2378 if (drv
->last_scan_cmd
!= NL80211_CMD_VENDOR
)
2379 drv
->scan_state
= SCAN_COMPLETED
;
2380 drv
->scan_complete_events
= 1;
2381 if (drv
->last_scan_cmd
== NL80211_CMD_TRIGGER_SCAN
) {
2382 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout
,
2384 drv
->last_scan_cmd
= 0;
2386 external_scan_event
= 1;
2388 send_scan_event(drv
, 0, tb
, external_scan_event
);
2390 case NL80211_CMD_SCHED_SCAN_RESULTS
:
2391 wpa_dbg(drv
->ctx
, MSG_DEBUG
,
2392 "nl80211: New sched scan results available");
2393 drv
->scan_state
= SCHED_SCAN_RESULTS
;
2394 send_scan_event(drv
, 0, tb
, 0);
2396 case NL80211_CMD_SCAN_ABORTED
:
2397 wpa_dbg(drv
->ctx
, MSG_DEBUG
, "nl80211: Scan aborted");
2398 if (drv
->last_scan_cmd
!= NL80211_CMD_VENDOR
)
2399 drv
->scan_state
= SCAN_ABORTED
;
2400 if (drv
->last_scan_cmd
== NL80211_CMD_TRIGGER_SCAN
) {
2402 * Need to indicate that scan results are available in
2403 * order not to make wpa_supplicant stop its scanning.
2405 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout
,
2407 drv
->last_scan_cmd
= 0;
2409 external_scan_event
= 1;
2411 send_scan_event(drv
, 1, tb
, external_scan_event
);
2413 case NL80211_CMD_AUTHENTICATE
:
2414 case NL80211_CMD_ASSOCIATE
:
2415 case NL80211_CMD_DEAUTHENTICATE
:
2416 case NL80211_CMD_DISASSOCIATE
:
2417 case NL80211_CMD_FRAME_TX_STATUS
:
2418 case NL80211_CMD_UNPROT_DEAUTHENTICATE
:
2419 case NL80211_CMD_UNPROT_DISASSOCIATE
:
2420 mlme_event(bss
, cmd
, tb
[NL80211_ATTR_FRAME
],
2421 tb
[NL80211_ATTR_MAC
], tb
[NL80211_ATTR_TIMED_OUT
],
2422 tb
[NL80211_ATTR_WIPHY_FREQ
], tb
[NL80211_ATTR_ACK
],
2423 tb
[NL80211_ATTR_COOKIE
],
2424 tb
[NL80211_ATTR_RX_SIGNAL_DBM
],
2425 tb
[NL80211_ATTR_STA_WME
]);
2427 case NL80211_CMD_CONNECT
:
2428 case NL80211_CMD_ROAM
:
2429 mlme_event_connect(drv
, cmd
,
2430 tb
[NL80211_ATTR_STATUS_CODE
],
2431 tb
[NL80211_ATTR_MAC
],
2432 tb
[NL80211_ATTR_REQ_IE
],
2433 tb
[NL80211_ATTR_RESP_IE
],
2434 tb
[NL80211_ATTR_TIMED_OUT
],
2435 tb
[NL80211_ATTR_TIMEOUT_REASON
],
2437 tb
[NL80211_ATTR_FILS_KEK
],
2439 tb
[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM
],
2440 tb
[NL80211_ATTR_PMK
],
2441 tb
[NL80211_ATTR_PMKID
]);
2443 case NL80211_CMD_CH_SWITCH_NOTIFY
:
2444 mlme_event_ch_switch(drv
,
2445 tb
[NL80211_ATTR_IFINDEX
],
2446 tb
[NL80211_ATTR_WIPHY_FREQ
],
2447 tb
[NL80211_ATTR_WIPHY_CHANNEL_TYPE
],
2448 tb
[NL80211_ATTR_CHANNEL_WIDTH
],
2449 tb
[NL80211_ATTR_CENTER_FREQ1
],
2450 tb
[NL80211_ATTR_CENTER_FREQ2
]);
2452 case NL80211_CMD_DISCONNECT
:
2453 mlme_event_disconnect(drv
, tb
[NL80211_ATTR_REASON_CODE
],
2454 tb
[NL80211_ATTR_MAC
],
2455 tb
[NL80211_ATTR_DISCONNECTED_BY_AP
]);
2457 case NL80211_CMD_MICHAEL_MIC_FAILURE
:
2458 mlme_event_michael_mic_failure(bss
, tb
);
2460 case NL80211_CMD_JOIN_IBSS
:
2461 mlme_event_join_ibss(drv
, tb
);
2463 case NL80211_CMD_REMAIN_ON_CHANNEL
:
2464 mlme_event_remain_on_channel(drv
, 0, tb
);
2466 case NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL
:
2467 mlme_event_remain_on_channel(drv
, 1, tb
);
2469 case NL80211_CMD_NOTIFY_CQM
:
2470 nl80211_cqm_event(drv
, tb
);
2472 case NL80211_CMD_REG_CHANGE
:
2473 nl80211_reg_change_event(drv
, tb
);
2475 case NL80211_CMD_REG_BEACON_HINT
:
2476 wpa_printf(MSG_DEBUG
, "nl80211: Regulatory beacon hint");
2477 os_memset(&data
, 0, sizeof(data
));
2478 data
.channel_list_changed
.initiator
= REGDOM_BEACON_HINT
;
2479 wpa_supplicant_event(drv
->ctx
, EVENT_CHANNEL_LIST_CHANGED
,
2482 case NL80211_CMD_NEW_STATION
:
2483 nl80211_new_station_event(drv
, bss
, tb
);
2485 case NL80211_CMD_DEL_STATION
:
2486 nl80211_del_station_event(drv
, bss
, tb
);
2488 case NL80211_CMD_SET_REKEY_OFFLOAD
:
2489 nl80211_rekey_offload_event(drv
, tb
);
2491 case NL80211_CMD_PMKSA_CANDIDATE
:
2492 nl80211_pmksa_candidate_event(drv
, tb
);
2494 case NL80211_CMD_PROBE_CLIENT
:
2495 nl80211_client_probe_event(drv
, tb
);
2497 case NL80211_CMD_TDLS_OPER
:
2498 nl80211_tdls_oper_event(drv
, tb
);
2500 case NL80211_CMD_CONN_FAILED
:
2501 nl80211_connect_failed_event(drv
, tb
);
2503 case NL80211_CMD_FT_EVENT
:
2504 mlme_event_ft_event(drv
, tb
);
2506 case NL80211_CMD_RADAR_DETECT
:
2507 nl80211_radar_event(drv
, tb
);
2509 case NL80211_CMD_STOP_AP
:
2510 nl80211_stop_ap(drv
, tb
);
2512 case NL80211_CMD_VENDOR
:
2513 nl80211_vendor_event(drv
, tb
);
2515 case NL80211_CMD_NEW_PEER_CANDIDATE
:
2516 nl80211_new_peer_candidate(drv
, tb
);
2518 case NL80211_CMD_PORT_AUTHORIZED
:
2519 nl80211_port_authorized(drv
, tb
);
2521 case NL80211_CMD_STA_OPMODE_CHANGED
:
2522 nl80211_sta_opmode_change_event(drv
, tb
);
2525 wpa_dbg(drv
->ctx
, MSG_DEBUG
, "nl80211: Ignored unknown event "
2532 int process_global_event(struct nl_msg
*msg
, void *arg
)
2534 struct nl80211_global
*global
= arg
;
2535 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
2536 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
2537 struct wpa_driver_nl80211_data
*drv
, *tmp
;
2538 int ifidx
= -1, wiphy_idx
= -1, wiphy_idx_rx
= -1;
2539 struct i802_bss
*bss
;
2541 int wdev_id_set
= 0;
2542 int wiphy_idx_set
= 0;
2544 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
2545 genlmsg_attrlen(gnlh
, 0), NULL
);
2547 if (tb
[NL80211_ATTR_IFINDEX
])
2548 ifidx
= nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]);
2549 else if (tb
[NL80211_ATTR_WDEV
]) {
2550 wdev_id
= nla_get_u64(tb
[NL80211_ATTR_WDEV
]);
2552 } else if (tb
[NL80211_ATTR_WIPHY
]) {
2553 wiphy_idx_rx
= nla_get_u32(tb
[NL80211_ATTR_WIPHY
]);
2557 dl_list_for_each_safe(drv
, tmp
, &global
->interfaces
,
2558 struct wpa_driver_nl80211_data
, list
) {
2559 for (bss
= drv
->first_bss
; bss
; bss
= bss
->next
) {
2561 wiphy_idx
= nl80211_get_wiphy_index(bss
);
2562 if ((ifidx
== -1 && !wiphy_idx_set
&& !wdev_id_set
) ||
2563 ifidx
== bss
->ifindex
||
2564 (wiphy_idx_set
&& wiphy_idx
== wiphy_idx_rx
) ||
2565 (wdev_id_set
&& bss
->wdev_id_set
&&
2566 wdev_id
== bss
->wdev_id
)) {
2567 do_process_drv_event(bss
, gnlh
->cmd
, tb
);
2571 wpa_printf(MSG_DEBUG
,
2572 "nl80211: Ignored event (cmd=%d) for foreign interface (ifindex %d wdev 0x%llx)",
2573 gnlh
->cmd
, ifidx
, (long long unsigned int) wdev_id
);
2580 int process_bss_event(struct nl_msg
*msg
, void *arg
)
2582 struct i802_bss
*bss
= arg
;
2583 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
2584 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
2586 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
2587 genlmsg_attrlen(gnlh
, 0), NULL
);
2589 wpa_printf(MSG_DEBUG
, "nl80211: BSS Event %d (%s) received for %s",
2590 gnlh
->cmd
, nl80211_command_to_string(gnlh
->cmd
),
2593 switch (gnlh
->cmd
) {
2594 case NL80211_CMD_FRAME
:
2595 case NL80211_CMD_FRAME_TX_STATUS
:
2596 mlme_event(bss
, gnlh
->cmd
, tb
[NL80211_ATTR_FRAME
],
2597 tb
[NL80211_ATTR_MAC
], tb
[NL80211_ATTR_TIMED_OUT
],
2598 tb
[NL80211_ATTR_WIPHY_FREQ
], tb
[NL80211_ATTR_ACK
],
2599 tb
[NL80211_ATTR_COOKIE
],
2600 tb
[NL80211_ATTR_RX_SIGNAL_DBM
],
2601 tb
[NL80211_ATTR_STA_WME
]);
2603 case NL80211_CMD_UNEXPECTED_FRAME
:
2604 nl80211_spurious_frame(bss
, tb
, 0);
2606 case NL80211_CMD_UNEXPECTED_4ADDR_FRAME
:
2607 nl80211_spurious_frame(bss
, tb
, 1);
2609 case NL80211_CMD_EXTERNAL_AUTH
:
2610 nl80211_external_auth(bss
->drv
, tb
);
2613 wpa_printf(MSG_DEBUG
, "nl80211: Ignored unknown event "
2614 "(cmd=%d)", gnlh
->cmd
);