LCOV - code coverage report
Current view: top level - src/drivers - driver_nl80211_event.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1422976643 Lines: 688 1062 64.8 %
Date: 2015-02-03 Functions: 30 40 75.0 %

          Line data    Source code
       1             : /*
       2             :  * Driver interaction with Linux nl80211/cfg80211 - Event processing
       3             :  * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
       4             :  * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
       5             :  * Copyright (c) 2009-2010, Atheros Communications
       6             :  *
       7             :  * This software may be distributed under the terms of the BSD license.
       8             :  * See README for more details.
       9             :  */
      10             : 
      11             : #include "includes.h"
      12             : #include <netlink/genl/genl.h>
      13             : 
      14             : #include "utils/common.h"
      15             : #include "utils/eloop.h"
      16             : #include "common/qca-vendor.h"
      17             : #include "common/qca-vendor-attr.h"
      18             : #include "common/ieee802_11_defs.h"
      19             : #include "common/ieee802_11_common.h"
      20             : #include "driver_nl80211.h"
      21             : 
      22             : 
      23       88593 : static const char * nl80211_command_to_string(enum nl80211_commands cmd)
      24             : {
      25             : #define C2S(x) case x: return #x;
      26       88593 :         switch (cmd) {
      27           0 :         C2S(NL80211_CMD_UNSPEC)
      28           0 :         C2S(NL80211_CMD_GET_WIPHY)
      29           0 :         C2S(NL80211_CMD_SET_WIPHY)
      30           0 :         C2S(NL80211_CMD_NEW_WIPHY)
      31           0 :         C2S(NL80211_CMD_DEL_WIPHY)
      32           0 :         C2S(NL80211_CMD_GET_INTERFACE)
      33           0 :         C2S(NL80211_CMD_SET_INTERFACE)
      34           0 :         C2S(NL80211_CMD_NEW_INTERFACE)
      35           0 :         C2S(NL80211_CMD_DEL_INTERFACE)
      36           0 :         C2S(NL80211_CMD_GET_KEY)
      37           0 :         C2S(NL80211_CMD_SET_KEY)
      38           0 :         C2S(NL80211_CMD_NEW_KEY)
      39           0 :         C2S(NL80211_CMD_DEL_KEY)
      40           0 :         C2S(NL80211_CMD_GET_BEACON)
      41           0 :         C2S(NL80211_CMD_SET_BEACON)
      42           0 :         C2S(NL80211_CMD_START_AP)
      43           6 :         C2S(NL80211_CMD_STOP_AP)
      44           0 :         C2S(NL80211_CMD_GET_STATION)
      45           0 :         C2S(NL80211_CMD_SET_STATION)
      46        5116 :         C2S(NL80211_CMD_NEW_STATION)
      47        5000 :         C2S(NL80211_CMD_DEL_STATION)
      48           0 :         C2S(NL80211_CMD_GET_MPATH)
      49           0 :         C2S(NL80211_CMD_SET_MPATH)
      50           0 :         C2S(NL80211_CMD_NEW_MPATH)
      51           0 :         C2S(NL80211_CMD_DEL_MPATH)
      52           0 :         C2S(NL80211_CMD_SET_BSS)
      53           0 :         C2S(NL80211_CMD_SET_REG)
      54           0 :         C2S(NL80211_CMD_REQ_SET_REG)
      55           0 :         C2S(NL80211_CMD_GET_MESH_CONFIG)
      56           0 :         C2S(NL80211_CMD_SET_MESH_CONFIG)
      57           0 :         C2S(NL80211_CMD_SET_MGMT_EXTRA_IE)
      58           0 :         C2S(NL80211_CMD_GET_REG)
      59           0 :         C2S(NL80211_CMD_GET_SCAN)
      60        2826 :         C2S(NL80211_CMD_TRIGGER_SCAN)
      61        2817 :         C2S(NL80211_CMD_NEW_SCAN_RESULTS)
      62           3 :         C2S(NL80211_CMD_SCAN_ABORTED)
      63        8320 :         C2S(NL80211_CMD_REG_CHANGE)
      64        4828 :         C2S(NL80211_CMD_AUTHENTICATE)
      65        4915 :         C2S(NL80211_CMD_ASSOCIATE)
      66        4828 :         C2S(NL80211_CMD_DEAUTHENTICATE)
      67           8 :         C2S(NL80211_CMD_DISASSOCIATE)
      68           4 :         C2S(NL80211_CMD_MICHAEL_MIC_FAILURE)
      69          42 :         C2S(NL80211_CMD_REG_BEACON_HINT)
      70          15 :         C2S(NL80211_CMD_JOIN_IBSS)
      71           0 :         C2S(NL80211_CMD_LEAVE_IBSS)
      72           0 :         C2S(NL80211_CMD_TESTMODE)
      73        2461 :         C2S(NL80211_CMD_CONNECT)
      74           0 :         C2S(NL80211_CMD_ROAM)
      75        2402 :         C2S(NL80211_CMD_DISCONNECT)
      76           0 :         C2S(NL80211_CMD_SET_WIPHY_NETNS)
      77           0 :         C2S(NL80211_CMD_GET_SURVEY)
      78           0 :         C2S(NL80211_CMD_NEW_SURVEY_RESULTS)
      79           0 :         C2S(NL80211_CMD_SET_PMKSA)
      80           0 :         C2S(NL80211_CMD_DEL_PMKSA)
      81           0 :         C2S(NL80211_CMD_FLUSH_PMKSA)
      82        1520 :         C2S(NL80211_CMD_REMAIN_ON_CHANNEL)
      83        1518 :         C2S(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL)
      84           0 :         C2S(NL80211_CMD_SET_TX_BITRATE_MASK)
      85           0 :         C2S(NL80211_CMD_REGISTER_FRAME)
      86       24618 :         C2S(NL80211_CMD_FRAME)
      87       17064 :         C2S(NL80211_CMD_FRAME_TX_STATUS)
      88           0 :         C2S(NL80211_CMD_SET_POWER_SAVE)
      89           0 :         C2S(NL80211_CMD_GET_POWER_SAVE)
      90           0 :         C2S(NL80211_CMD_SET_CQM)
      91           6 :         C2S(NL80211_CMD_NOTIFY_CQM)
      92           0 :         C2S(NL80211_CMD_SET_CHANNEL)
      93           0 :         C2S(NL80211_CMD_SET_WDS_PEER)
      94           0 :         C2S(NL80211_CMD_FRAME_WAIT_CANCEL)
      95           0 :         C2S(NL80211_CMD_JOIN_MESH)
      96           0 :         C2S(NL80211_CMD_LEAVE_MESH)
      97          44 :         C2S(NL80211_CMD_UNPROT_DEAUTHENTICATE)
      98          38 :         C2S(NL80211_CMD_UNPROT_DISASSOCIATE)
      99          50 :         C2S(NL80211_CMD_NEW_PEER_CANDIDATE)
     100           0 :         C2S(NL80211_CMD_GET_WOWLAN)
     101           0 :         C2S(NL80211_CMD_SET_WOWLAN)
     102           0 :         C2S(NL80211_CMD_START_SCHED_SCAN)
     103           0 :         C2S(NL80211_CMD_STOP_SCHED_SCAN)
     104           0 :         C2S(NL80211_CMD_SCHED_SCAN_RESULTS)
     105           0 :         C2S(NL80211_CMD_SCHED_SCAN_STOPPED)
     106           0 :         C2S(NL80211_CMD_SET_REKEY_OFFLOAD)
     107           0 :         C2S(NL80211_CMD_PMKSA_CANDIDATE)
     108           0 :         C2S(NL80211_CMD_TDLS_OPER)
     109           0 :         C2S(NL80211_CMD_TDLS_MGMT)
     110          24 :         C2S(NL80211_CMD_UNEXPECTED_FRAME)
     111           4 :         C2S(NL80211_CMD_PROBE_CLIENT)
     112           0 :         C2S(NL80211_CMD_REGISTER_BEACONS)
     113           7 :         C2S(NL80211_CMD_UNEXPECTED_4ADDR_FRAME)
     114           0 :         C2S(NL80211_CMD_SET_NOACK_MAP)
     115          35 :         C2S(NL80211_CMD_CH_SWITCH_NOTIFY)
     116           0 :         C2S(NL80211_CMD_START_P2P_DEVICE)
     117           0 :         C2S(NL80211_CMD_STOP_P2P_DEVICE)
     118           0 :         C2S(NL80211_CMD_CONN_FAILED)
     119           0 :         C2S(NL80211_CMD_SET_MCAST_RATE)
     120           0 :         C2S(NL80211_CMD_SET_MAC_ACL)
     121          39 :         C2S(NL80211_CMD_RADAR_DETECT)
     122           0 :         C2S(NL80211_CMD_GET_PROTOCOL_FEATURES)
     123           0 :         C2S(NL80211_CMD_UPDATE_FT_IES)
     124           0 :         C2S(NL80211_CMD_FT_EVENT)
     125           0 :         C2S(NL80211_CMD_CRIT_PROTOCOL_START)
     126           0 :         C2S(NL80211_CMD_CRIT_PROTOCOL_STOP)
     127           0 :         C2S(NL80211_CMD_GET_COALESCE)
     128           0 :         C2S(NL80211_CMD_SET_COALESCE)
     129           0 :         C2S(NL80211_CMD_CHANNEL_SWITCH)
     130           0 :         C2S(NL80211_CMD_VENDOR)
     131           0 :         C2S(NL80211_CMD_SET_QOS_MAP)
     132           0 :         C2S(NL80211_CMD_ADD_TX_TS)
     133           0 :         C2S(NL80211_CMD_DEL_TX_TS)
     134             :         default:
     135          35 :                 return "NL80211_CMD_UNKNOWN";
     136             :         }
     137             : #undef C2S
     138             : }
     139             : 
     140             : 
     141        2405 : static void mlme_event_auth(struct wpa_driver_nl80211_data *drv,
     142             :                             const u8 *frame, size_t len)
     143             : {
     144             :         const struct ieee80211_mgmt *mgmt;
     145             :         union wpa_event_data event;
     146             : 
     147        2405 :         if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
     148             :             drv->force_connect_cmd) {
     149             :                 /*
     150             :                  * Avoid reporting two association events that would confuse
     151             :                  * the core code.
     152             :                  */
     153          25 :                 wpa_printf(MSG_DEBUG,
     154             :                            "nl80211: Ignore auth event when using driver SME");
     155          25 :                 return;
     156             :         }
     157             : 
     158        2380 :         wpa_printf(MSG_DEBUG, "nl80211: Authenticate event");
     159        2380 :         mgmt = (const struct ieee80211_mgmt *) frame;
     160        2380 :         if (len < 24 + sizeof(mgmt->u.auth)) {
     161           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
     162             :                            "frame");
     163           0 :                 return;
     164             :         }
     165             : 
     166        2380 :         os_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN);
     167        2380 :         os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
     168        2380 :         os_memset(&event, 0, sizeof(event));
     169        2380 :         os_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN);
     170        2380 :         event.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg);
     171        2380 :         event.auth.auth_transaction =
     172        2380 :                 le_to_host16(mgmt->u.auth.auth_transaction);
     173        2380 :         event.auth.status_code = le_to_host16(mgmt->u.auth.status_code);
     174        2380 :         if (len > 24 + sizeof(mgmt->u.auth)) {
     175         172 :                 event.auth.ies = mgmt->u.auth.variable;
     176         172 :                 event.auth.ies_len = len - 24 - sizeof(mgmt->u.auth);
     177             :         }
     178             : 
     179        2380 :         wpa_supplicant_event(drv->ctx, EVENT_AUTH, &event);
     180             : }
     181             : 
     182             : 
     183        2424 : static void nl80211_parse_wmm_params(struct nlattr *wmm_attr,
     184             :                                      struct wmm_params *wmm_params)
     185             : {
     186             :         struct nlattr *wmm_info[NL80211_STA_WME_MAX + 1];
     187             :         static struct nla_policy wme_policy[NL80211_STA_WME_MAX + 1] = {
     188             :                 [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
     189             :         };
     190             : 
     191        4848 :         if (!wmm_attr ||
     192        2424 :             nla_parse_nested(wmm_info, NL80211_STA_WME_MAX, wmm_attr,
     193        2424 :                              wme_policy) ||
     194        2424 :             !wmm_info[NL80211_STA_WME_UAPSD_QUEUES])
     195        2424 :                 return;
     196             : 
     197        2424 :         wmm_params->uapsd_queues =
     198        2424 :                 nla_get_u8(wmm_info[NL80211_STA_WME_UAPSD_QUEUES]);
     199        2424 :         wmm_params->info_bitmap |= WMM_PARAMS_UAPSD_QUEUES_INFO;
     200             : }
     201             : 
     202             : 
     203        2457 : static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
     204             :                             const u8 *frame, size_t len, struct nlattr *wmm)
     205             : {
     206             :         const struct ieee80211_mgmt *mgmt;
     207             :         union wpa_event_data event;
     208             :         u16 status;
     209             : 
     210        2457 :         if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
     211             :             drv->force_connect_cmd) {
     212             :                 /*
     213             :                  * Avoid reporting two association events that would confuse
     214             :                  * the core code.
     215             :                  */
     216          24 :                 wpa_printf(MSG_DEBUG,
     217             :                            "nl80211: Ignore assoc event when using driver SME");
     218          24 :                 return;
     219             :         }
     220             : 
     221        2433 :         wpa_printf(MSG_DEBUG, "nl80211: Associate event");
     222        2433 :         mgmt = (const struct ieee80211_mgmt *) frame;
     223        2433 :         if (len < 24 + sizeof(mgmt->u.assoc_resp)) {
     224           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
     225             :                            "frame");
     226           0 :                 return;
     227             :         }
     228             : 
     229        2433 :         status = le_to_host16(mgmt->u.assoc_resp.status_code);
     230        2433 :         if (status != WLAN_STATUS_SUCCESS) {
     231           9 :                 os_memset(&event, 0, sizeof(event));
     232           9 :                 event.assoc_reject.bssid = mgmt->bssid;
     233           9 :                 if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
     234           9 :                         event.assoc_reject.resp_ies =
     235           9 :                                 (u8 *) mgmt->u.assoc_resp.variable;
     236           9 :                         event.assoc_reject.resp_ies_len =
     237           9 :                                 len - 24 - sizeof(mgmt->u.assoc_resp);
     238             :                 }
     239           9 :                 event.assoc_reject.status_code = status;
     240             : 
     241           9 :                 wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
     242           9 :                 return;
     243             :         }
     244             : 
     245        2424 :         drv->associated = 1;
     246        2424 :         os_memcpy(drv->bssid, mgmt->sa, ETH_ALEN);
     247        2424 :         os_memcpy(drv->prev_bssid, mgmt->sa, ETH_ALEN);
     248             : 
     249        2424 :         os_memset(&event, 0, sizeof(event));
     250        2424 :         if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
     251        2424 :                 event.assoc_info.resp_ies = (u8 *) mgmt->u.assoc_resp.variable;
     252        2424 :                 event.assoc_info.resp_ies_len =
     253        2424 :                         len - 24 - sizeof(mgmt->u.assoc_resp);
     254             :         }
     255             : 
     256        2424 :         event.assoc_info.freq = drv->assoc_freq;
     257             : 
     258        2424 :         nl80211_parse_wmm_params(wmm, &event.assoc_info.wmm_params);
     259             : 
     260        2424 :         wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
     261             : }
     262             : 
     263             : 
     264        2461 : static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
     265             :                                enum nl80211_commands cmd, struct nlattr *status,
     266             :                                struct nlattr *addr, struct nlattr *req_ie,
     267             :                                struct nlattr *resp_ie,
     268             :                                struct nlattr *authorized,
     269             :                                struct nlattr *key_replay_ctr,
     270             :                                struct nlattr *ptk_kck,
     271             :                                struct nlattr *ptk_kek)
     272             : {
     273             :         union wpa_event_data event;
     274             :         u16 status_code;
     275             : 
     276        2461 :         if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
     277             :                 /*
     278             :                  * Avoid reporting two association events that would confuse
     279             :                  * the core code.
     280             :                  */
     281        2433 :                 wpa_printf(MSG_DEBUG, "nl80211: Ignore connect event (cmd=%d) "
     282             :                            "when using userspace SME", cmd);
     283        2433 :                 return;
     284             :         }
     285             : 
     286          28 :         status_code = status ? nla_get_u16(status) : WLAN_STATUS_SUCCESS;
     287             : 
     288          28 :         if (cmd == NL80211_CMD_CONNECT) {
     289          28 :                 wpa_printf(MSG_DEBUG,
     290             :                            "nl80211: Connect event (status=%u ignore_next_local_disconnect=%d)",
     291          28 :                            status_code, drv->ignore_next_local_disconnect);
     292           0 :         } else if (cmd == NL80211_CMD_ROAM) {
     293           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Roam event");
     294             :         }
     295             : 
     296          28 :         os_memset(&event, 0, sizeof(event));
     297          28 :         if (cmd == NL80211_CMD_CONNECT && status_code != WLAN_STATUS_SUCCESS) {
     298           6 :                 if (addr)
     299           3 :                         event.assoc_reject.bssid = nla_data(addr);
     300           6 :                 if (drv->ignore_next_local_disconnect) {
     301           0 :                         drv->ignore_next_local_disconnect = 0;
     302           0 :                         if (!event.assoc_reject.bssid ||
     303           0 :                             (os_memcmp(event.assoc_reject.bssid,
     304             :                                        drv->auth_attempt_bssid,
     305             :                                        ETH_ALEN) != 0)) {
     306             :                                 /*
     307             :                                  * Ignore the event that came without a BSSID or
     308             :                                  * for the old connection since this is likely
     309             :                                  * not relevant to the new Connect command.
     310             :                                  */
     311           0 :                                 wpa_printf(MSG_DEBUG,
     312             :                                            "nl80211: Ignore connection failure event triggered during reassociation");
     313           0 :                                 return;
     314             :                         }
     315             :                 }
     316           6 :                 if (resp_ie) {
     317           2 :                         event.assoc_reject.resp_ies = nla_data(resp_ie);
     318           2 :                         event.assoc_reject.resp_ies_len = nla_len(resp_ie);
     319             :                 }
     320           6 :                 event.assoc_reject.status_code = status_code;
     321           6 :                 wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
     322           6 :                 return;
     323             :         }
     324             : 
     325          22 :         drv->associated = 1;
     326          22 :         if (addr) {
     327          22 :                 os_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);
     328          22 :                 os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
     329             :         }
     330             : 
     331          22 :         if (req_ie) {
     332           0 :                 event.assoc_info.req_ies = nla_data(req_ie);
     333           0 :                 event.assoc_info.req_ies_len = nla_len(req_ie);
     334             :         }
     335          22 :         if (resp_ie) {
     336          22 :                 event.assoc_info.resp_ies = nla_data(resp_ie);
     337          22 :                 event.assoc_info.resp_ies_len = nla_len(resp_ie);
     338             :         }
     339             : 
     340          22 :         event.assoc_info.freq = nl80211_get_assoc_freq(drv);
     341             : 
     342          22 :         if (authorized && nla_get_u8(authorized)) {
     343           0 :                 event.assoc_info.authorized = 1;
     344           0 :                 wpa_printf(MSG_DEBUG, "nl80211: connection authorized");
     345             :         }
     346          22 :         if (key_replay_ctr) {
     347           0 :                 event.assoc_info.key_replay_ctr = nla_data(key_replay_ctr);
     348           0 :                 event.assoc_info.key_replay_ctr_len = nla_len(key_replay_ctr);
     349             :         }
     350          22 :         if (ptk_kck) {
     351           0 :                 event.assoc_info.ptk_kck = nla_data(ptk_kck);
     352           0 :                 event.assoc_info.ptk_kck_len = nla_len(ptk_kck);
     353             :         }
     354          22 :         if (ptk_kek) {
     355           0 :                 event.assoc_info.ptk_kek = nla_data(ptk_kek);
     356           0 :                 event.assoc_info.ptk_kek_len = nla_len(ptk_kek);
     357             :         }
     358             : 
     359          22 :         wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
     360             : }
     361             : 
     362             : 
     363        2402 : static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv,
     364             :                                   struct nlattr *reason, struct nlattr *addr,
     365             :                                   struct nlattr *by_ap)
     366             : {
     367             :         union wpa_event_data data;
     368        2402 :         unsigned int locally_generated = by_ap == NULL;
     369             : 
     370        2402 :         if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
     371             :                 /*
     372             :                  * Avoid reporting two disassociation events that could
     373             :                  * confuse the core code.
     374             :                  */
     375        2388 :                 wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
     376             :                            "event when using userspace SME");
     377        2388 :                 return;
     378             :         }
     379             : 
     380          14 :         if (drv->ignore_next_local_disconnect) {
     381          13 :                 drv->ignore_next_local_disconnect = 0;
     382          13 :                 if (locally_generated) {
     383          13 :                         wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
     384             :                                    "event triggered during reassociation");
     385          13 :                         return;
     386             :                 }
     387           0 :                 wpa_printf(MSG_WARNING, "nl80211: Was expecting local "
     388             :                            "disconnect but got another disconnect "
     389             :                            "event first");
     390             :         }
     391             : 
     392           1 :         wpa_printf(MSG_DEBUG, "nl80211: Disconnect event");
     393           1 :         nl80211_mark_disconnected(drv);
     394           1 :         os_memset(&data, 0, sizeof(data));
     395           1 :         if (reason)
     396           1 :                 data.deauth_info.reason_code = nla_get_u16(reason);
     397           1 :         data.deauth_info.locally_generated = by_ap == NULL;
     398           1 :         wpa_supplicant_event(drv->ctx, EVENT_DEAUTH, &data);
     399             : }
     400             : 
     401             : 
     402           1 : static int calculate_chan_offset(int width, int freq, int cf1, int cf2)
     403             : {
     404           1 :         int freq1 = 0;
     405             : 
     406           1 :         switch (convert2width(width)) {
     407             :         case CHAN_WIDTH_20_NOHT:
     408             :         case CHAN_WIDTH_20:
     409           0 :                 return 0;
     410             :         case CHAN_WIDTH_40:
     411           0 :                 freq1 = cf1 - 10;
     412           0 :                 break;
     413             :         case CHAN_WIDTH_80:
     414           1 :                 freq1 = cf1 - 30;
     415           1 :                 break;
     416             :         case CHAN_WIDTH_160:
     417           0 :                 freq1 = cf1 - 70;
     418           0 :                 break;
     419             :         case CHAN_WIDTH_UNKNOWN:
     420             :         case CHAN_WIDTH_80P80:
     421             :                 /* FIXME: implement this */
     422           0 :                 return 0;
     423             :         }
     424             : 
     425           1 :         return (abs(freq - freq1) / 20) % 2 == 0 ? 1 : -1;
     426             : }
     427             : 
     428             : 
     429          35 : static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
     430             :                                  struct nlattr *ifindex, struct nlattr *freq,
     431             :                                  struct nlattr *type, struct nlattr *bw,
     432             :                                  struct nlattr *cf1, struct nlattr *cf2)
     433             : {
     434             :         struct i802_bss *bss;
     435             :         union wpa_event_data data;
     436          35 :         int ht_enabled = 1;
     437          35 :         int chan_offset = 0;
     438             :         int ifidx;
     439             : 
     440          35 :         wpa_printf(MSG_DEBUG, "nl80211: Channel switch event");
     441             : 
     442          35 :         if (!freq)
     443           0 :                 return;
     444             : 
     445          35 :         ifidx = nla_get_u32(ifindex);
     446          35 :         bss = get_bss_ifindex(drv, ifidx);
     447          35 :         if (bss == NULL) {
     448           0 :                 wpa_printf(MSG_WARNING, "nl80211: Unknown ifindex (%d) for channel switch, ignoring",
     449             :                            ifidx);
     450           0 :                 return;
     451             :         }
     452             : 
     453          35 :         if (type) {
     454          34 :                 enum nl80211_channel_type ch_type = nla_get_u32(type);
     455             : 
     456          34 :                 wpa_printf(MSG_DEBUG, "nl80211: Channel type: %d", ch_type);
     457          34 :                 switch (ch_type) {
     458             :                 case NL80211_CHAN_NO_HT:
     459          12 :                         ht_enabled = 0;
     460          12 :                         break;
     461             :                 case NL80211_CHAN_HT20:
     462           8 :                         break;
     463             :                 case NL80211_CHAN_HT40PLUS:
     464          10 :                         chan_offset = 1;
     465          10 :                         break;
     466             :                 case NL80211_CHAN_HT40MINUS:
     467           4 :                         chan_offset = -1;
     468           4 :                         break;
     469             :                 }
     470           1 :         } else if (bw && cf1) {
     471             :                 /* This can happen for example with VHT80 ch switch */
     472           3 :                 chan_offset = calculate_chan_offset(nla_get_u32(bw),
     473           1 :                                                     nla_get_u32(freq),
     474           1 :                                                     nla_get_u32(cf1),
     475           0 :                                                     cf2 ? nla_get_u32(cf2) : 0);
     476             :         } else {
     477           0 :                 wpa_printf(MSG_WARNING, "nl80211: Unknown secondary channel information - following channel definition calculations may fail");
     478             :         }
     479             : 
     480          35 :         os_memset(&data, 0, sizeof(data));
     481          35 :         data.ch_switch.freq = nla_get_u32(freq);
     482          35 :         data.ch_switch.ht_enabled = ht_enabled;
     483          35 :         data.ch_switch.ch_offset = chan_offset;
     484          35 :         if (bw)
     485          35 :                 data.ch_switch.ch_width = convert2width(nla_get_u32(bw));
     486          35 :         if (cf1)
     487          35 :                 data.ch_switch.cf1 = nla_get_u32(cf1);
     488          35 :         if (cf2)
     489           0 :                 data.ch_switch.cf2 = nla_get_u32(cf2);
     490             : 
     491          35 :         bss->freq = data.ch_switch.freq;
     492             : 
     493          35 :         wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH, &data);
     494             : }
     495             : 
     496             : 
     497          19 : static void mlme_timeout_event(struct wpa_driver_nl80211_data *drv,
     498             :                                enum nl80211_commands cmd, struct nlattr *addr)
     499             : {
     500             :         union wpa_event_data event;
     501             :         enum wpa_event_type ev;
     502             : 
     503          19 :         if (nla_len(addr) != ETH_ALEN)
     504           0 :                 return;
     505             : 
     506         114 :         wpa_printf(MSG_DEBUG, "nl80211: MLME event %d; timeout with " MACSTR,
     507         114 :                    cmd, MAC2STR((u8 *) nla_data(addr)));
     508             : 
     509          19 :         if (cmd == NL80211_CMD_AUTHENTICATE)
     510          18 :                 ev = EVENT_AUTH_TIMED_OUT;
     511           1 :         else if (cmd == NL80211_CMD_ASSOCIATE)
     512           1 :                 ev = EVENT_ASSOC_TIMED_OUT;
     513             :         else
     514           0 :                 return;
     515             : 
     516          19 :         os_memset(&event, 0, sizeof(event));
     517          19 :         os_memcpy(event.timeout_event.addr, nla_data(addr), ETH_ALEN);
     518          19 :         wpa_supplicant_event(drv->ctx, ev, &event);
     519             : }
     520             : 
     521             : 
     522       12309 : static void mlme_event_mgmt(struct i802_bss *bss,
     523             :                             struct nlattr *freq, struct nlattr *sig,
     524             :                             const u8 *frame, size_t len)
     525             : {
     526       12309 :         struct wpa_driver_nl80211_data *drv = bss->drv;
     527             :         const struct ieee80211_mgmt *mgmt;
     528             :         union wpa_event_data event;
     529             :         u16 fc, stype;
     530       12309 :         int ssi_signal = 0;
     531       12309 :         int rx_freq = 0;
     532             : 
     533       12309 :         wpa_printf(MSG_MSGDUMP, "nl80211: Frame event");
     534       12309 :         mgmt = (const struct ieee80211_mgmt *) frame;
     535       12309 :         if (len < 24) {
     536           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Too short management frame");
     537       12309 :                 return;
     538             :         }
     539             : 
     540       12309 :         fc = le_to_host16(mgmt->frame_control);
     541       12309 :         stype = WLAN_FC_GET_STYPE(fc);
     542             : 
     543       12309 :         if (sig)
     544       12309 :                 ssi_signal = (s32) nla_get_u32(sig);
     545             : 
     546       12309 :         os_memset(&event, 0, sizeof(event));
     547       12309 :         if (freq) {
     548       12309 :                 event.rx_mgmt.freq = nla_get_u32(freq);
     549       12309 :                 rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
     550             :         }
     551       98472 :         wpa_printf(MSG_DEBUG,
     552             :                    "nl80211: RX frame sa=" MACSTR
     553             :                    " freq=%d ssi_signal=%d fc=0x%x seq_ctrl=0x%x stype=%u (%s) len=%u",
     554       73854 :                    MAC2STR(mgmt->sa), rx_freq, ssi_signal, fc,
     555       12309 :                    le_to_host16(mgmt->seq_ctrl), stype, fc2str(fc),
     556             :                    (unsigned int) len);
     557       12309 :         event.rx_mgmt.frame = frame;
     558       12309 :         event.rx_mgmt.frame_len = len;
     559       12309 :         event.rx_mgmt.ssi_signal = ssi_signal;
     560       12309 :         event.rx_mgmt.drv_priv = bss;
     561       12309 :         wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
     562             : }
     563             : 
     564             : 
     565        8532 : static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv,
     566             :                                       struct nlattr *cookie, const u8 *frame,
     567             :                                       size_t len, struct nlattr *ack)
     568             : {
     569             :         union wpa_event_data event;
     570             :         const struct ieee80211_hdr *hdr;
     571             :         u16 fc;
     572             : 
     573        8532 :         wpa_printf(MSG_DEBUG, "nl80211: Frame TX status event");
     574        8532 :         if (!is_ap_interface(drv->nlmode)) {
     575             :                 u64 cookie_val;
     576             : 
     577        2058 :                 if (!cookie)
     578         388 :                         return;
     579             : 
     580        2058 :                 cookie_val = nla_get_u64(cookie);
     581        4116 :                 wpa_printf(MSG_DEBUG, "nl80211: Action TX status:"
     582             :                            " cookie=0%llx%s (ack=%d)",
     583             :                            (long long unsigned int) cookie_val,
     584        2058 :                            cookie_val == drv->send_action_cookie ?
     585             :                            " (match)" : " (unknown)", ack != NULL);
     586        2058 :                 if (cookie_val != drv->send_action_cookie)
     587         388 :                         return;
     588             :         }
     589             : 
     590        8144 :         hdr = (const struct ieee80211_hdr *) frame;
     591        8144 :         fc = le_to_host16(hdr->frame_control);
     592             : 
     593        8144 :         os_memset(&event, 0, sizeof(event));
     594        8144 :         event.tx_status.type = WLAN_FC_GET_TYPE(fc);
     595        8144 :         event.tx_status.stype = WLAN_FC_GET_STYPE(fc);
     596        8144 :         event.tx_status.dst = hdr->addr1;
     597        8144 :         event.tx_status.data = frame;
     598        8144 :         event.tx_status.data_len = len;
     599        8144 :         event.tx_status.ack = ack != NULL;
     600        8144 :         wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);
     601             : }
     602             : 
     603             : 
     604        2418 : static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
     605             :                                        enum wpa_event_type type,
     606             :                                        const u8 *frame, size_t len)
     607             : {
     608             :         const struct ieee80211_mgmt *mgmt;
     609             :         union wpa_event_data event;
     610        2418 :         const u8 *bssid = NULL;
     611        2418 :         u16 reason_code = 0;
     612             : 
     613        2418 :         if (type == EVENT_DEAUTH)
     614        2414 :                 wpa_printf(MSG_DEBUG, "nl80211: Deauthenticate event");
     615             :         else
     616           4 :                 wpa_printf(MSG_DEBUG, "nl80211: Disassociate event");
     617             : 
     618        2418 :         mgmt = (const struct ieee80211_mgmt *) frame;
     619        2418 :         if (len >= 24) {
     620        2418 :                 bssid = mgmt->bssid;
     621             : 
     622        4822 :                 if ((drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
     623        4566 :                     !drv->associated &&
     624        2494 :                     os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0 &&
     625         594 :                     os_memcmp(bssid, drv->auth_attempt_bssid, ETH_ALEN) != 0 &&
     626         262 :                     os_memcmp(bssid, drv->prev_bssid, ETH_ALEN) == 0) {
     627             :                         /*
     628             :                          * Avoid issues with some roaming cases where
     629             :                          * disconnection event for the old AP may show up after
     630             :                          * we have started connection with the new AP.
     631             :                          */
     632        3144 :                         wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth/disassoc event from old AP " MACSTR " when already authenticating with " MACSTR,
     633        1572 :                                    MAC2STR(bssid),
     634        1572 :                                    MAC2STR(drv->auth_attempt_bssid));
     635         262 :                         return;
     636             :                 }
     637             : 
     638        2399 :                 if (drv->associated != 0 &&
     639         243 :                     os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&
     640           0 :                     os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {
     641             :                         /*
     642             :                          * We have presumably received this deauth as a
     643             :                          * response to a clear_state_mismatch() outgoing
     644             :                          * deauth.  Don't let it take us offline!
     645             :                          */
     646           0 :                         wpa_printf(MSG_DEBUG, "nl80211: Deauth received "
     647             :                                    "from Unknown BSSID " MACSTR " -- ignoring",
     648           0 :                                    MAC2STR(bssid));
     649           0 :                         return;
     650             :                 }
     651             :         }
     652             : 
     653        2156 :         nl80211_mark_disconnected(drv);
     654        2156 :         os_memset(&event, 0, sizeof(event));
     655             : 
     656             :         /* Note: Same offset for Reason Code in both frame subtypes */
     657        2156 :         if (len >= 24 + sizeof(mgmt->u.deauth))
     658        2156 :                 reason_code = le_to_host16(mgmt->u.deauth.reason_code);
     659             : 
     660        2156 :         if (type == EVENT_DISASSOC) {
     661           4 :                 event.disassoc_info.locally_generated =
     662           4 :                         !os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
     663           4 :                 event.disassoc_info.addr = bssid;
     664           4 :                 event.disassoc_info.reason_code = reason_code;
     665           4 :                 if (frame + len > mgmt->u.disassoc.variable) {
     666           1 :                         event.disassoc_info.ie = mgmt->u.disassoc.variable;
     667           1 :                         event.disassoc_info.ie_len = frame + len -
     668             :                                 mgmt->u.disassoc.variable;
     669             :                 }
     670             :         } else {
     671        2152 :                 if (drv->ignore_deauth_event) {
     672          44 :                         wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth event due to previous forced deauth-during-auth");
     673          44 :                         drv->ignore_deauth_event = 0;
     674          44 :                         return;
     675             :                 }
     676        2108 :                 event.deauth_info.locally_generated =
     677        2108 :                         !os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
     678        2108 :                 if (drv->ignore_next_local_deauth) {
     679        1808 :                         drv->ignore_next_local_deauth = 0;
     680        1808 :                         if (event.deauth_info.locally_generated) {
     681        1808 :                                 wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth event triggered due to own deauth request");
     682        1808 :                                 return;
     683             :                         }
     684           0 :                         wpa_printf(MSG_WARNING, "nl80211: Was expecting local deauth but got another disconnect event first");
     685             :                 }
     686         300 :                 event.deauth_info.addr = bssid;
     687         300 :                 event.deauth_info.reason_code = reason_code;
     688         300 :                 if (frame + len > mgmt->u.deauth.variable) {
     689           1 :                         event.deauth_info.ie = mgmt->u.deauth.variable;
     690           1 :                         event.deauth_info.ie_len = frame + len -
     691             :                                 mgmt->u.deauth.variable;
     692             :                 }
     693             :         }
     694             : 
     695         304 :         wpa_supplicant_event(drv->ctx, type, &event);
     696             : }
     697             : 
     698             : 
     699          41 : static void mlme_event_unprot_disconnect(struct wpa_driver_nl80211_data *drv,
     700             :                                          enum wpa_event_type type,
     701             :                                          const u8 *frame, size_t len)
     702             : {
     703             :         const struct ieee80211_mgmt *mgmt;
     704             :         union wpa_event_data event;
     705          41 :         u16 reason_code = 0;
     706             : 
     707          41 :         if (type == EVENT_UNPROT_DEAUTH)
     708          22 :                 wpa_printf(MSG_DEBUG, "nl80211: Unprot Deauthenticate event");
     709             :         else
     710          19 :                 wpa_printf(MSG_DEBUG, "nl80211: Unprot Disassociate event");
     711             : 
     712          41 :         if (len < 24)
     713          41 :                 return;
     714             : 
     715          41 :         mgmt = (const struct ieee80211_mgmt *) frame;
     716             : 
     717          41 :         os_memset(&event, 0, sizeof(event));
     718             :         /* Note: Same offset for Reason Code in both frame subtypes */
     719          41 :         if (len >= 24 + sizeof(mgmt->u.deauth))
     720          41 :                 reason_code = le_to_host16(mgmt->u.deauth.reason_code);
     721             : 
     722          41 :         if (type == EVENT_UNPROT_DISASSOC) {
     723          19 :                 event.unprot_disassoc.sa = mgmt->sa;
     724          19 :                 event.unprot_disassoc.da = mgmt->da;
     725          19 :                 event.unprot_disassoc.reason_code = reason_code;
     726             :         } else {
     727          22 :                 event.unprot_deauth.sa = mgmt->sa;
     728          22 :                 event.unprot_deauth.da = mgmt->da;
     729          22 :                 event.unprot_deauth.reason_code = reason_code;
     730             :         }
     731             : 
     732          41 :         wpa_supplicant_event(drv->ctx, type, &event);
     733             : }
     734             : 
     735             : 
     736       28181 : static void mlme_event(struct i802_bss *bss,
     737             :                        enum nl80211_commands cmd, struct nlattr *frame,
     738             :                        struct nlattr *addr, struct nlattr *timed_out,
     739             :                        struct nlattr *freq, struct nlattr *ack,
     740             :                        struct nlattr *cookie, struct nlattr *sig,
     741             :                        struct nlattr *wmm)
     742             : {
     743       28181 :         struct wpa_driver_nl80211_data *drv = bss->drv;
     744             :         const u8 *data;
     745             :         size_t len;
     746             : 
     747       28181 :         if (timed_out && addr) {
     748          19 :                 mlme_timeout_event(drv, cmd, addr);
     749          19 :                 return;
     750             :         }
     751             : 
     752       28162 :         if (frame == NULL) {
     753           0 :                 wpa_printf(MSG_DEBUG,
     754             :                            "nl80211: MLME event %d (%s) without frame data",
     755             :                            cmd, nl80211_command_to_string(cmd));
     756           0 :                 return;
     757             :         }
     758             : 
     759       28162 :         data = nla_data(frame);
     760       28162 :         len = nla_len(frame);
     761       28162 :         if (len < 4 + 2 * ETH_ALEN) {
     762           0 :                 wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d (%s) on %s("
     763             :                            MACSTR ") - too short",
     764           0 :                            cmd, nl80211_command_to_string(cmd), bss->ifname,
     765           0 :                            MAC2STR(bss->addr));
     766           0 :                 return;
     767             :         }
     768      535078 :         wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d (%s) on %s(" MACSTR
     769             :                    ") A1=" MACSTR " A2=" MACSTR, cmd,
     770       28162 :                    nl80211_command_to_string(cmd), bss->ifname,
     771      337944 :                    MAC2STR(bss->addr), MAC2STR(data + 4),
     772      168972 :                    MAC2STR(data + 4 + ETH_ALEN));
     773       44509 :         if (cmd != NL80211_CMD_FRAME_TX_STATUS && !(data[4] & 0x01) &&
     774       18487 :             os_memcmp(bss->addr, data + 4, ETH_ALEN) != 0 &&
     775        2140 :             os_memcmp(bss->addr, data + 4 + ETH_ALEN, ETH_ALEN) != 0) {
     776           0 :                 wpa_printf(MSG_MSGDUMP, "nl80211: %s: Ignore MLME frame event "
     777           0 :                            "for foreign address", bss->ifname);
     778           0 :                 return;
     779             :         }
     780       56324 :         wpa_hexdump(MSG_MSGDUMP, "nl80211: MLME event frame",
     781       56324 :                     nla_data(frame), nla_len(frame));
     782             : 
     783       28162 :         switch (cmd) {
     784             :         case NL80211_CMD_AUTHENTICATE:
     785        2405 :                 mlme_event_auth(drv, nla_data(frame), nla_len(frame));
     786        2405 :                 break;
     787             :         case NL80211_CMD_ASSOCIATE:
     788        2457 :                 mlme_event_assoc(drv, nla_data(frame), nla_len(frame), wmm);
     789        2457 :                 break;
     790             :         case NL80211_CMD_DEAUTHENTICATE:
     791        4828 :                 mlme_event_deauth_disassoc(drv, EVENT_DEAUTH,
     792        4828 :                                            nla_data(frame), nla_len(frame));
     793        2414 :                 break;
     794             :         case NL80211_CMD_DISASSOCIATE:
     795           8 :                 mlme_event_deauth_disassoc(drv, EVENT_DISASSOC,
     796           8 :                                            nla_data(frame), nla_len(frame));
     797           4 :                 break;
     798             :         case NL80211_CMD_FRAME:
     799       12309 :                 mlme_event_mgmt(bss, freq, sig, nla_data(frame),
     800       12309 :                                 nla_len(frame));
     801       12309 :                 break;
     802             :         case NL80211_CMD_FRAME_TX_STATUS:
     803        8532 :                 mlme_event_mgmt_tx_status(drv, cookie, nla_data(frame),
     804        8532 :                                           nla_len(frame), ack);
     805        8532 :                 break;
     806             :         case NL80211_CMD_UNPROT_DEAUTHENTICATE:
     807          44 :                 mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DEAUTH,
     808          44 :                                              nla_data(frame), nla_len(frame));
     809          22 :                 break;
     810             :         case NL80211_CMD_UNPROT_DISASSOCIATE:
     811          38 :                 mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC,
     812          38 :                                              nla_data(frame), nla_len(frame));
     813          19 :                 break;
     814             :         default:
     815           0 :                 break;
     816             :         }
     817             : }
     818             : 
     819             : 
     820           4 : static void mlme_event_michael_mic_failure(struct i802_bss *bss,
     821             :                                            struct nlattr *tb[])
     822             : {
     823             :         union wpa_event_data data;
     824             : 
     825           4 :         wpa_printf(MSG_DEBUG, "nl80211: MLME event Michael MIC failure");
     826           4 :         os_memset(&data, 0, sizeof(data));
     827           4 :         if (tb[NL80211_ATTR_MAC]) {
     828           8 :                 wpa_hexdump(MSG_DEBUG, "nl80211: Source MAC address",
     829           4 :                             nla_data(tb[NL80211_ATTR_MAC]),
     830           4 :                             nla_len(tb[NL80211_ATTR_MAC]));
     831           4 :                 data.michael_mic_failure.src = nla_data(tb[NL80211_ATTR_MAC]);
     832             :         }
     833           4 :         if (tb[NL80211_ATTR_KEY_SEQ]) {
     834           0 :                 wpa_hexdump(MSG_DEBUG, "nl80211: TSC",
     835           0 :                             nla_data(tb[NL80211_ATTR_KEY_SEQ]),
     836           0 :                             nla_len(tb[NL80211_ATTR_KEY_SEQ]));
     837             :         }
     838           4 :         if (tb[NL80211_ATTR_KEY_TYPE]) {
     839           4 :                 enum nl80211_key_type key_type =
     840           4 :                         nla_get_u32(tb[NL80211_ATTR_KEY_TYPE]);
     841           4 :                 wpa_printf(MSG_DEBUG, "nl80211: Key Type %d", key_type);
     842           4 :                 if (key_type == NL80211_KEYTYPE_PAIRWISE)
     843           3 :                         data.michael_mic_failure.unicast = 1;
     844             :         } else
     845           0 :                 data.michael_mic_failure.unicast = 1;
     846             : 
     847           4 :         if (tb[NL80211_ATTR_KEY_IDX]) {
     848           4 :                 u8 key_id = nla_get_u8(tb[NL80211_ATTR_KEY_IDX]);
     849           4 :                 wpa_printf(MSG_DEBUG, "nl80211: Key Id %d", key_id);
     850             :         }
     851             : 
     852           4 :         wpa_supplicant_event(bss->ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
     853           4 : }
     854             : 
     855             : 
     856          15 : static void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv,
     857             :                                  struct nlattr *tb[])
     858             : {
     859             :         unsigned int freq;
     860             : 
     861          15 :         if (tb[NL80211_ATTR_MAC] == NULL) {
     862           0 :                 wpa_printf(MSG_DEBUG, "nl80211: No address in IBSS joined "
     863             :                            "event");
     864          15 :                 return;
     865             :         }
     866          15 :         os_memcpy(drv->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
     867             : 
     868          15 :         drv->associated = 1;
     869          90 :         wpa_printf(MSG_DEBUG, "nl80211: IBSS " MACSTR " joined",
     870          90 :                    MAC2STR(drv->bssid));
     871             : 
     872          15 :         freq = nl80211_get_assoc_freq(drv);
     873          15 :         if (freq) {
     874          15 :                 wpa_printf(MSG_DEBUG, "nl80211: IBSS on frequency %u MHz",
     875             :                            freq);
     876          15 :                 drv->first_bss->freq = freq;
     877             :         }
     878             : 
     879          15 :         wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
     880             : }
     881             : 
     882             : 
     883        3038 : static void mlme_event_remain_on_channel(struct wpa_driver_nl80211_data *drv,
     884             :                                          int cancel_event, struct nlattr *tb[])
     885             : {
     886             :         unsigned int freq, chan_type, duration;
     887             :         union wpa_event_data data;
     888             :         u64 cookie;
     889             : 
     890        3038 :         if (tb[NL80211_ATTR_WIPHY_FREQ])
     891        3038 :                 freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
     892             :         else
     893           0 :                 freq = 0;
     894             : 
     895        3038 :         if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
     896        3038 :                 chan_type = nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
     897             :         else
     898           0 :                 chan_type = 0;
     899             : 
     900        3038 :         if (tb[NL80211_ATTR_DURATION])
     901        1520 :                 duration = nla_get_u32(tb[NL80211_ATTR_DURATION]);
     902             :         else
     903        1518 :                 duration = 0;
     904             : 
     905        3038 :         if (tb[NL80211_ATTR_COOKIE])
     906        3038 :                 cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
     907             :         else
     908           0 :                 cookie = 0;
     909             : 
     910        3038 :         wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel event (cancel=%d "
     911             :                    "freq=%u channel_type=%u duration=%u cookie=0x%llx (%s))",
     912             :                    cancel_event, freq, chan_type, duration,
     913             :                    (long long unsigned int) cookie,
     914        3038 :                    cookie == drv->remain_on_chan_cookie ? "match" : "unknown");
     915             : 
     916        3038 :         if (cookie != drv->remain_on_chan_cookie)
     917        3131 :                 return; /* not for us */
     918             : 
     919        2945 :         if (cancel_event)
     920        1429 :                 drv->pending_remain_on_chan = 0;
     921             : 
     922        2945 :         os_memset(&data, 0, sizeof(data));
     923        2945 :         data.remain_on_channel.freq = freq;
     924        2945 :         data.remain_on_channel.duration = duration;
     925        2945 :         wpa_supplicant_event(drv->ctx, cancel_event ?
     926             :                              EVENT_CANCEL_REMAIN_ON_CHANNEL :
     927             :                              EVENT_REMAIN_ON_CHANNEL, &data);
     928             : }
     929             : 
     930             : 
     931           0 : static void mlme_event_ft_event(struct wpa_driver_nl80211_data *drv,
     932             :                                 struct nlattr *tb[])
     933             : {
     934             :         union wpa_event_data data;
     935             : 
     936           0 :         os_memset(&data, 0, sizeof(data));
     937             : 
     938           0 :         if (tb[NL80211_ATTR_IE]) {
     939           0 :                 data.ft_ies.ies = nla_data(tb[NL80211_ATTR_IE]);
     940           0 :                 data.ft_ies.ies_len = nla_len(tb[NL80211_ATTR_IE]);
     941             :         }
     942             : 
     943           0 :         if (tb[NL80211_ATTR_IE_RIC]) {
     944           0 :                 data.ft_ies.ric_ies = nla_data(tb[NL80211_ATTR_IE_RIC]);
     945           0 :                 data.ft_ies.ric_ies_len = nla_len(tb[NL80211_ATTR_IE_RIC]);
     946             :         }
     947             : 
     948           0 :         if (tb[NL80211_ATTR_MAC])
     949           0 :                 os_memcpy(data.ft_ies.target_ap,
     950             :                           nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
     951             : 
     952           0 :         wpa_printf(MSG_DEBUG, "nl80211: FT event target_ap " MACSTR,
     953           0 :                    MAC2STR(data.ft_ies.target_ap));
     954             : 
     955           0 :         wpa_supplicant_event(drv->ctx, EVENT_FT_RESPONSE, &data);
     956           0 : }
     957             : 
     958             : 
     959        2820 : static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
     960             :                             struct nlattr *tb[])
     961             : {
     962             :         union wpa_event_data event;
     963             :         struct nlattr *nl;
     964             :         int rem;
     965             :         struct scan_info *info;
     966             : #define MAX_REPORT_FREQS 50
     967             :         int freqs[MAX_REPORT_FREQS];
     968        2820 :         int num_freqs = 0;
     969             : 
     970        2820 :         if (drv->scan_for_auth) {
     971           6 :                 drv->scan_for_auth = 0;
     972           6 :                 wpa_printf(MSG_DEBUG, "nl80211: Scan results for missing "
     973             :                            "cfg80211 BSS entry");
     974           6 :                 wpa_driver_nl80211_authenticate_retry(drv);
     975        2826 :                 return;
     976             :         }
     977             : 
     978        2814 :         os_memset(&event, 0, sizeof(event));
     979        2814 :         info = &event.scan_info;
     980        2814 :         info->aborted = aborted;
     981             : 
     982        2814 :         if (tb[NL80211_ATTR_SCAN_SSIDS]) {
     983        5543 :                 nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_SSIDS], rem) {
     984        2729 :                         struct wpa_driver_scan_ssid *s =
     985        2729 :                                 &info->ssids[info->num_ssids];
     986        2729 :                         s->ssid = nla_data(nl);
     987        2729 :                         s->ssid_len = nla_len(nl);
     988        2729 :                         wpa_printf(MSG_DEBUG, "nl80211: Scan probed for SSID '%s'",
     989             :                                    wpa_ssid_txt(s->ssid, s->ssid_len));
     990        2729 :                         info->num_ssids++;
     991        2729 :                         if (info->num_ssids == WPAS_MAX_SCAN_SSIDS)
     992           0 :                                 break;
     993             :                 }
     994             :         }
     995        2814 :         if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {
     996             :                 char msg[200], *pos, *end;
     997             :                 int res;
     998             : 
     999        2814 :                 pos = msg;
    1000        2814 :                 end = pos + sizeof(msg);
    1001        2814 :                 *pos = '\0';
    1002             : 
    1003       15312 :                 nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem)
    1004             :                 {
    1005       12498 :                         freqs[num_freqs] = nla_get_u32(nl);
    1006       12498 :                         res = os_snprintf(pos, end - pos, " %d",
    1007             :                                           freqs[num_freqs]);
    1008       12498 :                         if (!os_snprintf_error(end - pos, res))
    1009       12498 :                                 pos += res;
    1010       12498 :                         num_freqs++;
    1011       12498 :                         if (num_freqs == MAX_REPORT_FREQS - 1)
    1012           0 :                                 break;
    1013             :                 }
    1014        2814 :                 info->freqs = freqs;
    1015        2814 :                 info->num_freqs = num_freqs;
    1016        2814 :                 wpa_printf(MSG_DEBUG, "nl80211: Scan included frequencies:%s",
    1017             :                            msg);
    1018             :         }
    1019        2814 :         wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
    1020             : }
    1021             : 
    1022             : 
    1023           6 : static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
    1024             :                               struct nlattr *tb[])
    1025             : {
    1026             :         static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
    1027             :                 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
    1028             :                 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },
    1029             :                 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
    1030             :                 [NL80211_ATTR_CQM_PKT_LOSS_EVENT] = { .type = NLA_U32 },
    1031             :         };
    1032             :         struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1];
    1033             :         enum nl80211_cqm_rssi_threshold_event event;
    1034             :         union wpa_event_data ed;
    1035             :         struct wpa_signal_info sig;
    1036             :         int res;
    1037             : 
    1038          12 :         if (tb[NL80211_ATTR_CQM] == NULL ||
    1039           6 :             nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb[NL80211_ATTR_CQM],
    1040             :                              cqm_policy)) {
    1041           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Ignore invalid CQM event");
    1042           0 :                 return;
    1043             :         }
    1044             : 
    1045           6 :         os_memset(&ed, 0, sizeof(ed));
    1046             : 
    1047           6 :         if (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) {
    1048           0 :                 if (!tb[NL80211_ATTR_MAC])
    1049           0 :                         return;
    1050           0 :                 os_memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]),
    1051             :                           ETH_ALEN);
    1052           0 :                 wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);
    1053           0 :                 return;
    1054             :         }
    1055             : 
    1056           6 :         if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL)
    1057           1 :                 return;
    1058           5 :         event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]);
    1059             : 
    1060           5 :         if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) {
    1061           3 :                 wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
    1062             :                            "event: RSSI high");
    1063           3 :                 ed.signal_change.above_threshold = 1;
    1064           2 :         } else if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW) {
    1065           2 :                 wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
    1066             :                            "event: RSSI low");
    1067           2 :                 ed.signal_change.above_threshold = 0;
    1068             :         } else
    1069           0 :                 return;
    1070             : 
    1071           5 :         res = nl80211_get_link_signal(drv, &sig);
    1072           5 :         if (res == 0) {
    1073           5 :                 ed.signal_change.current_signal = sig.current_signal;
    1074           5 :                 ed.signal_change.current_txrate = sig.current_txrate;
    1075           5 :                 wpa_printf(MSG_DEBUG, "nl80211: Signal: %d dBm  txrate: %d",
    1076             :                            sig.current_signal, sig.current_txrate);
    1077             :         }
    1078             : 
    1079           5 :         res = nl80211_get_link_noise(drv, &sig);
    1080           5 :         if (res == 0) {
    1081           5 :                 ed.signal_change.current_noise = sig.current_noise;
    1082           5 :                 wpa_printf(MSG_DEBUG, "nl80211: Noise: %d dBm",
    1083             :                            sig.current_noise);
    1084             :         }
    1085             : 
    1086           5 :         wpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed);
    1087             : }
    1088             : 
    1089             : 
    1090          50 : static void nl80211_new_peer_candidate(struct wpa_driver_nl80211_data *drv,
    1091             :                                        struct nlattr **tb)
    1092             : {
    1093             :         const u8 *addr;
    1094             :         union wpa_event_data data;
    1095             : 
    1096         100 :         if (drv->nlmode != NL80211_IFTYPE_MESH_POINT ||
    1097         100 :             !tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_IE])
    1098          50 :                 return;
    1099             : 
    1100          50 :         addr = nla_data(tb[NL80211_ATTR_MAC]);
    1101         300 :         wpa_printf(MSG_DEBUG, "nl80211: New peer candidate" MACSTR,
    1102         300 :                    MAC2STR(addr));
    1103             : 
    1104          50 :         os_memset(&data, 0, sizeof(data));
    1105          50 :         data.mesh_peer.peer = addr;
    1106          50 :         data.mesh_peer.ies = nla_data(tb[NL80211_ATTR_IE]);
    1107          50 :         data.mesh_peer.ie_len = nla_len(tb[NL80211_ATTR_IE]);
    1108          50 :         wpa_supplicant_event(drv->ctx, EVENT_NEW_PEER_CANDIDATE, &data);
    1109             : }
    1110             : 
    1111             : 
    1112        5116 : static void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv,
    1113             :                                       struct i802_bss *bss,
    1114             :                                       struct nlattr **tb)
    1115             : {
    1116             :         u8 *addr;
    1117             :         union wpa_event_data data;
    1118             : 
    1119        5116 :         if (tb[NL80211_ATTR_MAC] == NULL)
    1120        5095 :                 return;
    1121        5116 :         addr = nla_data(tb[NL80211_ATTR_MAC]);
    1122        5116 :         wpa_printf(MSG_DEBUG, "nl80211: New station " MACSTR, MAC2STR(addr));
    1123             : 
    1124        5116 :         if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
    1125           0 :                 u8 *ies = NULL;
    1126           0 :                 size_t ies_len = 0;
    1127           0 :                 if (tb[NL80211_ATTR_IE]) {
    1128           0 :                         ies = nla_data(tb[NL80211_ATTR_IE]);
    1129           0 :                         ies_len = nla_len(tb[NL80211_ATTR_IE]);
    1130             :                 }
    1131           0 :                 wpa_hexdump(MSG_DEBUG, "nl80211: Assoc Req IEs", ies, ies_len);
    1132           0 :                 drv_event_assoc(bss->ctx, addr, ies, ies_len, 0);
    1133           0 :                 return;
    1134             :         }
    1135             : 
    1136        5116 :         if (drv->nlmode != NL80211_IFTYPE_ADHOC)
    1137        5095 :                 return;
    1138             : 
    1139          21 :         os_memset(&data, 0, sizeof(data));
    1140          21 :         os_memcpy(data.ibss_rsn_start.peer, addr, ETH_ALEN);
    1141          21 :         wpa_supplicant_event(bss->ctx, EVENT_IBSS_RSN_START, &data);
    1142             : }
    1143             : 
    1144             : 
    1145        5000 : static void nl80211_del_station_event(struct wpa_driver_nl80211_data *drv,
    1146             :                                       struct nlattr **tb)
    1147             : {
    1148             :         u8 *addr;
    1149             :         union wpa_event_data data;
    1150             : 
    1151        5000 :         if (tb[NL80211_ATTR_MAC] == NULL)
    1152        4998 :                 return;
    1153        5000 :         addr = nla_data(tb[NL80211_ATTR_MAC]);
    1154       30000 :         wpa_printf(MSG_DEBUG, "nl80211: Delete station " MACSTR,
    1155       30000 :                    MAC2STR(addr));
    1156             : 
    1157        5000 :         if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
    1158           0 :                 drv_event_disassoc(drv->ctx, addr);
    1159           0 :                 return;
    1160             :         }
    1161             : 
    1162        5000 :         if (drv->nlmode != NL80211_IFTYPE_ADHOC)
    1163        4998 :                 return;
    1164             : 
    1165           2 :         os_memset(&data, 0, sizeof(data));
    1166           2 :         os_memcpy(data.ibss_peer_lost.peer, addr, ETH_ALEN);
    1167           2 :         wpa_supplicant_event(drv->ctx, EVENT_IBSS_PEER_LOST, &data);
    1168             : }
    1169             : 
    1170             : 
    1171           0 : static void nl80211_rekey_offload_event(struct wpa_driver_nl80211_data *drv,
    1172             :                                         struct nlattr **tb)
    1173             : {
    1174             :         struct nlattr *rekey_info[NUM_NL80211_REKEY_DATA];
    1175             :         static struct nla_policy rekey_policy[NUM_NL80211_REKEY_DATA] = {
    1176             :                 [NL80211_REKEY_DATA_KEK] = {
    1177             :                         .minlen = NL80211_KEK_LEN,
    1178             :                         .maxlen = NL80211_KEK_LEN,
    1179             :                 },
    1180             :                 [NL80211_REKEY_DATA_KCK] = {
    1181             :                         .minlen = NL80211_KCK_LEN,
    1182             :                         .maxlen = NL80211_KCK_LEN,
    1183             :                 },
    1184             :                 [NL80211_REKEY_DATA_REPLAY_CTR] = {
    1185             :                         .minlen = NL80211_REPLAY_CTR_LEN,
    1186             :                         .maxlen = NL80211_REPLAY_CTR_LEN,
    1187             :                 },
    1188             :         };
    1189             :         union wpa_event_data data;
    1190             : 
    1191           0 :         if (!tb[NL80211_ATTR_MAC] ||
    1192           0 :             !tb[NL80211_ATTR_REKEY_DATA] ||
    1193           0 :             nla_parse_nested(rekey_info, MAX_NL80211_REKEY_DATA,
    1194           0 :                              tb[NL80211_ATTR_REKEY_DATA], rekey_policy) ||
    1195           0 :             !rekey_info[NL80211_REKEY_DATA_REPLAY_CTR])
    1196           0 :                 return;
    1197             : 
    1198           0 :         os_memset(&data, 0, sizeof(data));
    1199           0 :         data.driver_gtk_rekey.bssid = nla_data(tb[NL80211_ATTR_MAC]);
    1200           0 :         wpa_printf(MSG_DEBUG, "nl80211: Rekey offload event for BSSID " MACSTR,
    1201           0 :                    MAC2STR(data.driver_gtk_rekey.bssid));
    1202           0 :         data.driver_gtk_rekey.replay_ctr =
    1203           0 :                 nla_data(rekey_info[NL80211_REKEY_DATA_REPLAY_CTR]);
    1204           0 :         wpa_hexdump(MSG_DEBUG, "nl80211: Rekey offload - Replay Counter",
    1205           0 :                     data.driver_gtk_rekey.replay_ctr, NL80211_REPLAY_CTR_LEN);
    1206           0 :         wpa_supplicant_event(drv->ctx, EVENT_DRIVER_GTK_REKEY, &data);
    1207             : }
    1208             : 
    1209             : 
    1210           0 : static void nl80211_pmksa_candidate_event(struct wpa_driver_nl80211_data *drv,
    1211             :                                           struct nlattr **tb)
    1212             : {
    1213             :         struct nlattr *cand[NUM_NL80211_PMKSA_CANDIDATE];
    1214             :         static struct nla_policy cand_policy[NUM_NL80211_PMKSA_CANDIDATE] = {
    1215             :                 [NL80211_PMKSA_CANDIDATE_INDEX] = { .type = NLA_U32 },
    1216             :                 [NL80211_PMKSA_CANDIDATE_BSSID] = {
    1217             :                         .minlen = ETH_ALEN,
    1218             :                         .maxlen = ETH_ALEN,
    1219             :                 },
    1220             :                 [NL80211_PMKSA_CANDIDATE_PREAUTH] = { .type = NLA_FLAG },
    1221             :         };
    1222             :         union wpa_event_data data;
    1223             : 
    1224           0 :         wpa_printf(MSG_DEBUG, "nl80211: PMKSA candidate event");
    1225             : 
    1226           0 :         if (!tb[NL80211_ATTR_PMKSA_CANDIDATE] ||
    1227           0 :             nla_parse_nested(cand, MAX_NL80211_PMKSA_CANDIDATE,
    1228           0 :                              tb[NL80211_ATTR_PMKSA_CANDIDATE], cand_policy) ||
    1229           0 :             !cand[NL80211_PMKSA_CANDIDATE_INDEX] ||
    1230           0 :             !cand[NL80211_PMKSA_CANDIDATE_BSSID])
    1231           0 :                 return;
    1232             : 
    1233           0 :         os_memset(&data, 0, sizeof(data));
    1234           0 :         os_memcpy(data.pmkid_candidate.bssid,
    1235             :                   nla_data(cand[NL80211_PMKSA_CANDIDATE_BSSID]), ETH_ALEN);
    1236           0 :         data.pmkid_candidate.index =
    1237           0 :                 nla_get_u32(cand[NL80211_PMKSA_CANDIDATE_INDEX]);
    1238           0 :         data.pmkid_candidate.preauth =
    1239           0 :                 cand[NL80211_PMKSA_CANDIDATE_PREAUTH] != NULL;
    1240           0 :         wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);
    1241             : }
    1242             : 
    1243             : 
    1244           4 : static void nl80211_client_probe_event(struct wpa_driver_nl80211_data *drv,
    1245             :                                        struct nlattr **tb)
    1246             : {
    1247             :         union wpa_event_data data;
    1248             : 
    1249           4 :         wpa_printf(MSG_DEBUG, "nl80211: Probe client event");
    1250             : 
    1251           4 :         if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_ACK])
    1252           7 :                 return;
    1253             : 
    1254           1 :         os_memset(&data, 0, sizeof(data));
    1255           1 :         os_memcpy(data.client_poll.addr,
    1256             :                   nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
    1257             : 
    1258           1 :         wpa_supplicant_event(drv->ctx, EVENT_DRIVER_CLIENT_POLL_OK, &data);
    1259             : }
    1260             : 
    1261             : 
    1262           0 : static void nl80211_tdls_oper_event(struct wpa_driver_nl80211_data *drv,
    1263             :                                     struct nlattr **tb)
    1264             : {
    1265             :         union wpa_event_data data;
    1266             : 
    1267           0 :         wpa_printf(MSG_DEBUG, "nl80211: TDLS operation event");
    1268             : 
    1269           0 :         if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_TDLS_OPERATION])
    1270           0 :                 return;
    1271             : 
    1272           0 :         os_memset(&data, 0, sizeof(data));
    1273           0 :         os_memcpy(data.tdls.peer, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
    1274           0 :         switch (nla_get_u8(tb[NL80211_ATTR_TDLS_OPERATION])) {
    1275             :         case NL80211_TDLS_SETUP:
    1276           0 :                 wpa_printf(MSG_DEBUG, "nl80211: TDLS setup request for peer "
    1277           0 :                            MACSTR, MAC2STR(data.tdls.peer));
    1278           0 :                 data.tdls.oper = TDLS_REQUEST_SETUP;
    1279           0 :                 break;
    1280             :         case NL80211_TDLS_TEARDOWN:
    1281           0 :                 wpa_printf(MSG_DEBUG, "nl80211: TDLS teardown request for peer "
    1282           0 :                            MACSTR, MAC2STR(data.tdls.peer));
    1283           0 :                 data.tdls.oper = TDLS_REQUEST_TEARDOWN;
    1284           0 :                 break;
    1285             :         default:
    1286           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Unsupported TDLS operatione "
    1287             :                            "event");
    1288           0 :                 return;
    1289             :         }
    1290           0 :         if (tb[NL80211_ATTR_REASON_CODE]) {
    1291           0 :                 data.tdls.reason_code =
    1292           0 :                         nla_get_u16(tb[NL80211_ATTR_REASON_CODE]);
    1293             :         }
    1294             : 
    1295           0 :         wpa_supplicant_event(drv->ctx, EVENT_TDLS, &data);
    1296             : }
    1297             : 
    1298             : 
    1299           6 : static void nl80211_stop_ap(struct wpa_driver_nl80211_data *drv,
    1300             :                             struct nlattr **tb)
    1301             : {
    1302           6 :         wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_UNAVAILABLE, NULL);
    1303           6 : }
    1304             : 
    1305             : 
    1306           0 : static void nl80211_connect_failed_event(struct wpa_driver_nl80211_data *drv,
    1307             :                                          struct nlattr **tb)
    1308             : {
    1309             :         union wpa_event_data data;
    1310             :         u32 reason;
    1311             : 
    1312           0 :         wpa_printf(MSG_DEBUG, "nl80211: Connect failed event");
    1313             : 
    1314           0 :         if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_CONN_FAILED_REASON])
    1315           0 :                 return;
    1316             : 
    1317           0 :         os_memset(&data, 0, sizeof(data));
    1318           0 :         os_memcpy(data.connect_failed_reason.addr,
    1319             :                   nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
    1320             : 
    1321           0 :         reason = nla_get_u32(tb[NL80211_ATTR_CONN_FAILED_REASON]);
    1322           0 :         switch (reason) {
    1323             :         case NL80211_CONN_FAIL_MAX_CLIENTS:
    1324           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Max client reached");
    1325           0 :                 data.connect_failed_reason.code = MAX_CLIENT_REACHED;
    1326           0 :                 break;
    1327             :         case NL80211_CONN_FAIL_BLOCKED_CLIENT:
    1328           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Blocked client " MACSTR
    1329             :                            " tried to connect",
    1330           0 :                            MAC2STR(data.connect_failed_reason.addr));
    1331           0 :                 data.connect_failed_reason.code = BLOCKED_CLIENT;
    1332           0 :                 break;
    1333             :         default:
    1334           0 :                 wpa_printf(MSG_DEBUG, "nl8021l: Unknown connect failed reason "
    1335             :                            "%u", reason);
    1336           0 :                 return;
    1337             :         }
    1338             : 
    1339           0 :         wpa_supplicant_event(drv->ctx, EVENT_CONNECT_FAILED_REASON, &data);
    1340             : }
    1341             : 
    1342             : 
    1343          39 : static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
    1344             :                                 struct nlattr **tb)
    1345             : {
    1346             :         union wpa_event_data data;
    1347             :         enum nl80211_radar_event event_type;
    1348             : 
    1349          39 :         if (!tb[NL80211_ATTR_WIPHY_FREQ] || !tb[NL80211_ATTR_RADAR_EVENT])
    1350          39 :                 return;
    1351             : 
    1352          39 :         os_memset(&data, 0, sizeof(data));
    1353          39 :         data.dfs_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
    1354          39 :         event_type = nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT]);
    1355             : 
    1356             :         /* Check HT params */
    1357          39 :         if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
    1358          32 :                 data.dfs_event.ht_enabled = 1;
    1359          32 :                 data.dfs_event.chan_offset = 0;
    1360             : 
    1361          32 :                 switch (nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])) {
    1362             :                 case NL80211_CHAN_NO_HT:
    1363           5 :                         data.dfs_event.ht_enabled = 0;
    1364           5 :                         break;
    1365             :                 case NL80211_CHAN_HT20:
    1366          17 :                         break;
    1367             :                 case NL80211_CHAN_HT40PLUS:
    1368           5 :                         data.dfs_event.chan_offset = 1;
    1369           5 :                         break;
    1370             :                 case NL80211_CHAN_HT40MINUS:
    1371           5 :                         data.dfs_event.chan_offset = -1;
    1372           5 :                         break;
    1373             :                 }
    1374             :         }
    1375             : 
    1376             :         /* Get VHT params */
    1377          39 :         if (tb[NL80211_ATTR_CHANNEL_WIDTH])
    1378          39 :                 data.dfs_event.chan_width =
    1379          39 :                         convert2width(nla_get_u32(
    1380          39 :                                               tb[NL80211_ATTR_CHANNEL_WIDTH]));
    1381          39 :         if (tb[NL80211_ATTR_CENTER_FREQ1])
    1382          39 :                 data.dfs_event.cf1 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
    1383          39 :         if (tb[NL80211_ATTR_CENTER_FREQ2])
    1384           0 :                 data.dfs_event.cf2 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
    1385             : 
    1386          78 :         wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz, ht: %d, offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz",
    1387             :                    data.dfs_event.freq, data.dfs_event.ht_enabled,
    1388          39 :                    data.dfs_event.chan_offset, data.dfs_event.chan_width,
    1389             :                    data.dfs_event.cf1, data.dfs_event.cf2);
    1390             : 
    1391          39 :         switch (event_type) {
    1392             :         case NL80211_RADAR_DETECTED:
    1393          28 :                 wpa_supplicant_event(drv->ctx, EVENT_DFS_RADAR_DETECTED, &data);
    1394          28 :                 break;
    1395             :         case NL80211_RADAR_CAC_FINISHED:
    1396           5 :                 wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_FINISHED, &data);
    1397           5 :                 break;
    1398             :         case NL80211_RADAR_CAC_ABORTED:
    1399           6 :                 wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_ABORTED, &data);
    1400           6 :                 break;
    1401             :         case NL80211_RADAR_NOP_FINISHED:
    1402           0 :                 wpa_supplicant_event(drv->ctx, EVENT_DFS_NOP_FINISHED, &data);
    1403           0 :                 break;
    1404             :         default:
    1405           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Unknown radar event %d "
    1406             :                            "received", event_type);
    1407           0 :                 break;
    1408             :         }
    1409             : }
    1410             : 
    1411             : 
    1412          31 : static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb,
    1413             :                                    int wds)
    1414             : {
    1415          31 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    1416             :         union wpa_event_data event;
    1417             : 
    1418          31 :         if (!tb[NL80211_ATTR_MAC])
    1419          31 :                 return;
    1420             : 
    1421          31 :         os_memset(&event, 0, sizeof(event));
    1422          31 :         event.rx_from_unknown.bssid = bss->addr;
    1423          31 :         event.rx_from_unknown.addr = nla_data(tb[NL80211_ATTR_MAC]);
    1424          31 :         event.rx_from_unknown.wds = wds;
    1425             : 
    1426          31 :         wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);
    1427             : }
    1428             : 
    1429             : 
    1430           0 : static void qca_nl80211_avoid_freq(struct wpa_driver_nl80211_data *drv,
    1431             :                                    const u8 *data, size_t len)
    1432             : {
    1433             :         u32 i, count;
    1434             :         union wpa_event_data event;
    1435           0 :         struct wpa_freq_range *range = NULL;
    1436             :         const struct qca_avoid_freq_list *freq_range;
    1437             : 
    1438           0 :         freq_range = (const struct qca_avoid_freq_list *) data;
    1439           0 :         if (len < sizeof(freq_range->count))
    1440           0 :                 return;
    1441             : 
    1442           0 :         count = freq_range->count;
    1443           0 :         if (len < sizeof(freq_range->count) +
    1444           0 :             count * sizeof(struct qca_avoid_freq_range)) {
    1445           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Ignored too short avoid frequency list (len=%u)",
    1446             :                            (unsigned int) len);
    1447           0 :                 return;
    1448             :         }
    1449             : 
    1450           0 :         if (count > 0) {
    1451           0 :                 range = os_calloc(count, sizeof(struct wpa_freq_range));
    1452           0 :                 if (range == NULL)
    1453           0 :                         return;
    1454             :         }
    1455             : 
    1456           0 :         os_memset(&event, 0, sizeof(event));
    1457           0 :         for (i = 0; i < count; i++) {
    1458           0 :                 unsigned int idx = event.freq_range.num;
    1459           0 :                 range[idx].min = freq_range->range[i].start_freq;
    1460           0 :                 range[idx].max = freq_range->range[i].end_freq;
    1461           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Avoid frequency range: %u-%u",
    1462           0 :                            range[idx].min, range[idx].max);
    1463           0 :                 if (range[idx].min > range[idx].max) {
    1464           0 :                         wpa_printf(MSG_DEBUG, "nl80211: Ignore invalid frequency range");
    1465           0 :                         continue;
    1466             :                 }
    1467           0 :                 event.freq_range.num++;
    1468             :         }
    1469           0 :         event.freq_range.range = range;
    1470             : 
    1471           0 :         wpa_supplicant_event(drv->ctx, EVENT_AVOID_FREQUENCIES, &event);
    1472             : 
    1473           0 :         os_free(range);
    1474             : }
    1475             : 
    1476             : 
    1477           0 : static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv,
    1478             :                                    const u8 *data, size_t len)
    1479             : {
    1480             :         struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
    1481             :         union wpa_event_data event;
    1482             : 
    1483           0 :         wpa_printf(MSG_DEBUG,
    1484             :                    "nl80211: ACS channel selection vendor event received");
    1485             : 
    1486           0 :         if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX,
    1487           0 :                       (struct nlattr *) data, len, NULL) ||
    1488           0 :             !tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL] ||
    1489           0 :             !tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL])
    1490           0 :                 return;
    1491             : 
    1492           0 :         os_memset(&event, 0, sizeof(event));
    1493           0 :         event.acs_selected_channels.pri_channel =
    1494           0 :                 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]);
    1495           0 :         event.acs_selected_channels.sec_channel =
    1496           0 :                 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]);
    1497             : 
    1498           0 :         wpa_supplicant_event(drv->ctx, EVENT_ACS_CHANNEL_SELECTED, &event);
    1499             : }
    1500             : 
    1501             : 
    1502           0 : static void qca_nl80211_key_mgmt_auth(struct wpa_driver_nl80211_data *drv,
    1503             :                                       const u8 *data, size_t len)
    1504             : {
    1505             :         struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX + 1];
    1506             :         u8 *bssid;
    1507             : 
    1508           0 :         wpa_printf(MSG_DEBUG,
    1509             :                    "nl80211: Key management roam+auth vendor event received");
    1510             : 
    1511           0 :         if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX,
    1512           0 :                       (struct nlattr *) data, len, NULL) ||
    1513           0 :             !tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID] ||
    1514           0 :             nla_len(tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID]) != ETH_ALEN ||
    1515           0 :             !tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE] ||
    1516           0 :             !tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE] ||
    1517           0 :             !tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED])
    1518           0 :                 return;
    1519             : 
    1520           0 :         bssid = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID]);
    1521           0 :         wpa_printf(MSG_DEBUG, "  * roam BSSID " MACSTR, MAC2STR(bssid));
    1522             : 
    1523           0 :         mlme_event_connect(drv, NL80211_CMD_ROAM, NULL,
    1524             :                            tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID],
    1525             :                            tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE],
    1526             :                            tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE],
    1527             :                            tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED],
    1528             :                            tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR],
    1529             :                            tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK],
    1530             :                            tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK]);
    1531             : }
    1532             : 
    1533             : 
    1534           0 : static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data *drv,
    1535             :                                      u32 subcmd, u8 *data, size_t len)
    1536             : {
    1537           0 :         switch (subcmd) {
    1538             :         case QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY:
    1539           0 :                 qca_nl80211_avoid_freq(drv, data, len);
    1540           0 :                 break;
    1541             :         case QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH:
    1542           0 :                 qca_nl80211_key_mgmt_auth(drv, data, len);
    1543           0 :                 break;
    1544             :         case QCA_NL80211_VENDOR_SUBCMD_DO_ACS:
    1545           0 :                 qca_nl80211_acs_select_ch(drv, data, len);
    1546           0 :                 break;
    1547             :         default:
    1548           0 :                 wpa_printf(MSG_DEBUG,
    1549             :                            "nl80211: Ignore unsupported QCA vendor event %u",
    1550             :                            subcmd);
    1551           0 :                 break;
    1552             :         }
    1553           0 : }
    1554             : 
    1555             : 
    1556           0 : static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
    1557             :                                  struct nlattr **tb)
    1558             : {
    1559           0 :         u32 vendor_id, subcmd, wiphy = 0;
    1560             :         int wiphy_idx;
    1561           0 :         u8 *data = NULL;
    1562           0 :         size_t len = 0;
    1563             : 
    1564           0 :         if (!tb[NL80211_ATTR_VENDOR_ID] ||
    1565           0 :             !tb[NL80211_ATTR_VENDOR_SUBCMD])
    1566           0 :                 return;
    1567             : 
    1568           0 :         vendor_id = nla_get_u32(tb[NL80211_ATTR_VENDOR_ID]);
    1569           0 :         subcmd = nla_get_u32(tb[NL80211_ATTR_VENDOR_SUBCMD]);
    1570             : 
    1571           0 :         if (tb[NL80211_ATTR_WIPHY])
    1572           0 :                 wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
    1573             : 
    1574           0 :         wpa_printf(MSG_DEBUG, "nl80211: Vendor event: wiphy=%u vendor_id=0x%x subcmd=%u",
    1575             :                    wiphy, vendor_id, subcmd);
    1576             : 
    1577           0 :         if (tb[NL80211_ATTR_VENDOR_DATA]) {
    1578           0 :                 data = nla_data(tb[NL80211_ATTR_VENDOR_DATA]);
    1579           0 :                 len = nla_len(tb[NL80211_ATTR_VENDOR_DATA]);
    1580           0 :                 wpa_hexdump(MSG_MSGDUMP, "nl80211: Vendor data", data, len);
    1581             :         }
    1582             : 
    1583           0 :         wiphy_idx = nl80211_get_wiphy_index(drv->first_bss);
    1584           0 :         if (wiphy_idx >= 0 && wiphy_idx != (int) wiphy) {
    1585           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Ignore vendor event for foreign wiphy %u (own: %d)",
    1586             :                            wiphy, wiphy_idx);
    1587           0 :                 return;
    1588             :         }
    1589             : 
    1590           0 :         switch (vendor_id) {
    1591             :         case OUI_QCA:
    1592           0 :                 nl80211_vendor_event_qca(drv, subcmd, data, len);
    1593           0 :                 break;
    1594             :         default:
    1595           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Ignore unsupported vendor event");
    1596           0 :                 break;
    1597             :         }
    1598             : }
    1599             : 
    1600             : 
    1601        8320 : static void nl80211_reg_change_event(struct wpa_driver_nl80211_data *drv,
    1602             :                                      struct nlattr *tb[])
    1603             : {
    1604             :         union wpa_event_data data;
    1605             :         enum nl80211_reg_initiator init;
    1606             : 
    1607        8320 :         wpa_printf(MSG_DEBUG, "nl80211: Regulatory domain change");
    1608             : 
    1609        8320 :         if (tb[NL80211_ATTR_REG_INITIATOR] == NULL)
    1610        8320 :                 return;
    1611             : 
    1612        8320 :         os_memset(&data, 0, sizeof(data));
    1613        8320 :         init = nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR]);
    1614        8320 :         wpa_printf(MSG_DEBUG, " * initiator=%d", init);
    1615        8320 :         switch (init) {
    1616             :         case NL80211_REGDOM_SET_BY_CORE:
    1617        7986 :                 data.channel_list_changed.initiator = REGDOM_SET_BY_CORE;
    1618        7986 :                 break;
    1619             :         case NL80211_REGDOM_SET_BY_USER:
    1620         310 :                 data.channel_list_changed.initiator = REGDOM_SET_BY_USER;
    1621         310 :                 break;
    1622             :         case NL80211_REGDOM_SET_BY_DRIVER:
    1623           0 :                 data.channel_list_changed.initiator = REGDOM_SET_BY_DRIVER;
    1624           0 :                 break;
    1625             :         case NL80211_REGDOM_SET_BY_COUNTRY_IE:
    1626          24 :                 data.channel_list_changed.initiator = REGDOM_SET_BY_COUNTRY_IE;
    1627          24 :                 break;
    1628             :         }
    1629             : 
    1630        8320 :         if (tb[NL80211_ATTR_REG_TYPE]) {
    1631             :                 enum nl80211_reg_type type;
    1632        8320 :                 type = nla_get_u8(tb[NL80211_ATTR_REG_TYPE]);
    1633        8320 :                 wpa_printf(MSG_DEBUG, " * type=%d", type);
    1634        8320 :                 switch (type) {
    1635             :                 case NL80211_REGDOM_TYPE_COUNTRY:
    1636         334 :                         data.channel_list_changed.type = REGDOM_TYPE_COUNTRY;
    1637         334 :                         break;
    1638             :                 case NL80211_REGDOM_TYPE_WORLD:
    1639        7986 :                         data.channel_list_changed.type = REGDOM_TYPE_WORLD;
    1640        7986 :                         break;
    1641             :                 case NL80211_REGDOM_TYPE_CUSTOM_WORLD:
    1642           0 :                         data.channel_list_changed.type =
    1643             :                                 REGDOM_TYPE_CUSTOM_WORLD;
    1644           0 :                         break;
    1645             :                 case NL80211_REGDOM_TYPE_INTERSECTION:
    1646           0 :                         data.channel_list_changed.type =
    1647             :                                 REGDOM_TYPE_INTERSECTION;
    1648           0 :                         break;
    1649             :                 }
    1650             :         }
    1651             : 
    1652        8320 :         if (tb[NL80211_ATTR_REG_ALPHA2]) {
    1653         334 :                 os_strlcpy(data.channel_list_changed.alpha2,
    1654         334 :                            nla_get_string(tb[NL80211_ATTR_REG_ALPHA2]),
    1655             :                            sizeof(data.channel_list_changed.alpha2));
    1656         334 :                 wpa_printf(MSG_DEBUG, " * alpha2=%s",
    1657             :                            data.channel_list_changed.alpha2);
    1658             :         }
    1659             : 
    1660        8320 :         wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED, &data);
    1661             : }
    1662             : 
    1663             : 
    1664       48091 : static void do_process_drv_event(struct i802_bss *bss, int cmd,
    1665             :                                  struct nlattr **tb)
    1666             : {
    1667       48091 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    1668             :         union wpa_event_data data;
    1669             : 
    1670       48091 :         wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s",
    1671       48091 :                    cmd, nl80211_command_to_string(cmd), bss->ifname);
    1672             : 
    1673       48091 :         if (cmd == NL80211_CMD_ROAM &&
    1674           0 :             (drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) {
    1675             :                 /*
    1676             :                  * Device will use roam+auth vendor event to indicate
    1677             :                  * roaming, so ignore the regular roam event.
    1678             :                  */
    1679           0 :                 wpa_printf(MSG_DEBUG,
    1680             :                            "nl80211: Ignore roam event (cmd=%d), device will use vendor event roam+auth",
    1681             :                            cmd);
    1682       48091 :                 return;
    1683             :         }
    1684             : 
    1685       48091 :         if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&
    1686           0 :             (cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
    1687             :              cmd == NL80211_CMD_SCAN_ABORTED)) {
    1688           0 :                 wpa_driver_nl80211_set_mode(drv->first_bss,
    1689             :                                             drv->ap_scan_as_station);
    1690           0 :                 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
    1691             :         }
    1692             : 
    1693       48091 :         switch (cmd) {
    1694             :         case NL80211_CMD_TRIGGER_SCAN:
    1695        2826 :                 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger");
    1696        2826 :                 drv->scan_state = SCAN_STARTED;
    1697        2826 :                 if (drv->scan_for_auth) {
    1698             :                         /*
    1699             :                          * Cannot indicate EVENT_SCAN_STARTED here since we skip
    1700             :                          * EVENT_SCAN_RESULTS in scan_for_auth case and the
    1701             :                          * upper layer implementation could get confused about
    1702             :                          * scanning state.
    1703             :                          */
    1704           6 :                         wpa_printf(MSG_DEBUG, "nl80211: Do not indicate scan-start event due to internal scan_for_auth");
    1705           6 :                         break;
    1706             :                 }
    1707        2820 :                 wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
    1708        2820 :                 break;
    1709             :         case NL80211_CMD_START_SCHED_SCAN:
    1710           0 :                 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started");
    1711           0 :                 drv->scan_state = SCHED_SCAN_STARTED;
    1712           0 :                 break;
    1713             :         case NL80211_CMD_SCHED_SCAN_STOPPED:
    1714           0 :                 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
    1715           0 :                 drv->scan_state = SCHED_SCAN_STOPPED;
    1716           0 :                 wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
    1717           0 :                 break;
    1718             :         case NL80211_CMD_NEW_SCAN_RESULTS:
    1719        2817 :                 wpa_dbg(drv->ctx, MSG_DEBUG,
    1720             :                         "nl80211: New scan results available");
    1721        2817 :                 drv->scan_state = SCAN_COMPLETED;
    1722        2817 :                 drv->scan_complete_events = 1;
    1723        2817 :                 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
    1724             :                                      drv->ctx);
    1725        2817 :                 send_scan_event(drv, 0, tb);
    1726        2817 :                 break;
    1727             :         case NL80211_CMD_SCHED_SCAN_RESULTS:
    1728           0 :                 wpa_dbg(drv->ctx, MSG_DEBUG,
    1729             :                         "nl80211: New sched scan results available");
    1730           0 :                 drv->scan_state = SCHED_SCAN_RESULTS;
    1731           0 :                 send_scan_event(drv, 0, tb);
    1732           0 :                 break;
    1733             :         case NL80211_CMD_SCAN_ABORTED:
    1734           3 :                 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
    1735           3 :                 drv->scan_state = SCAN_ABORTED;
    1736             :                 /*
    1737             :                  * Need to indicate that scan results are available in order
    1738             :                  * not to make wpa_supplicant stop its scanning.
    1739             :                  */
    1740           3 :                 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
    1741             :                                      drv->ctx);
    1742           3 :                 send_scan_event(drv, 1, tb);
    1743           3 :                 break;
    1744             :         case NL80211_CMD_AUTHENTICATE:
    1745             :         case NL80211_CMD_ASSOCIATE:
    1746             :         case NL80211_CMD_DEAUTHENTICATE:
    1747             :         case NL80211_CMD_DISASSOCIATE:
    1748             :         case NL80211_CMD_FRAME_TX_STATUS:
    1749             :         case NL80211_CMD_UNPROT_DEAUTHENTICATE:
    1750             :         case NL80211_CMD_UNPROT_DISASSOCIATE:
    1751      111104 :                 mlme_event(bss, cmd, tb[NL80211_ATTR_FRAME],
    1752       31744 :                            tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
    1753       31744 :                            tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
    1754       15872 :                            tb[NL80211_ATTR_COOKIE],
    1755       15872 :                            tb[NL80211_ATTR_RX_SIGNAL_DBM],
    1756       15872 :                            tb[NL80211_ATTR_STA_WME]);
    1757       15872 :                 break;
    1758             :         case NL80211_CMD_CONNECT:
    1759             :         case NL80211_CMD_ROAM:
    1760        9844 :                 mlme_event_connect(drv, cmd,
    1761        2461 :                                    tb[NL80211_ATTR_STATUS_CODE],
    1762        2461 :                                    tb[NL80211_ATTR_MAC],
    1763        2461 :                                    tb[NL80211_ATTR_REQ_IE],
    1764        2461 :                                    tb[NL80211_ATTR_RESP_IE],
    1765             :                                    NULL, NULL, NULL, NULL);
    1766        2461 :                 break;
    1767             :         case NL80211_CMD_CH_SWITCH_NOTIFY:
    1768         210 :                 mlme_event_ch_switch(drv,
    1769          35 :                                      tb[NL80211_ATTR_IFINDEX],
    1770          35 :                                      tb[NL80211_ATTR_WIPHY_FREQ],
    1771          35 :                                      tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
    1772          35 :                                      tb[NL80211_ATTR_CHANNEL_WIDTH],
    1773          35 :                                      tb[NL80211_ATTR_CENTER_FREQ1],
    1774          35 :                                      tb[NL80211_ATTR_CENTER_FREQ2]);
    1775          35 :                 break;
    1776             :         case NL80211_CMD_DISCONNECT:
    1777        4804 :                 mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],
    1778        2402 :                                       tb[NL80211_ATTR_MAC],
    1779        2402 :                                       tb[NL80211_ATTR_DISCONNECTED_BY_AP]);
    1780        2402 :                 break;
    1781             :         case NL80211_CMD_MICHAEL_MIC_FAILURE:
    1782           4 :                 mlme_event_michael_mic_failure(bss, tb);
    1783           4 :                 break;
    1784             :         case NL80211_CMD_JOIN_IBSS:
    1785          15 :                 mlme_event_join_ibss(drv, tb);
    1786          15 :                 break;
    1787             :         case NL80211_CMD_REMAIN_ON_CHANNEL:
    1788        1520 :                 mlme_event_remain_on_channel(drv, 0, tb);
    1789        1520 :                 break;
    1790             :         case NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL:
    1791        1518 :                 mlme_event_remain_on_channel(drv, 1, tb);
    1792        1518 :                 break;
    1793             :         case NL80211_CMD_NOTIFY_CQM:
    1794           6 :                 nl80211_cqm_event(drv, tb);
    1795           6 :                 break;
    1796             :         case NL80211_CMD_REG_CHANGE:
    1797        8320 :                 nl80211_reg_change_event(drv, tb);
    1798        8320 :                 break;
    1799             :         case NL80211_CMD_REG_BEACON_HINT:
    1800          42 :                 wpa_printf(MSG_DEBUG, "nl80211: Regulatory beacon hint");
    1801          42 :                 os_memset(&data, 0, sizeof(data));
    1802          42 :                 data.channel_list_changed.initiator = REGDOM_BEACON_HINT;
    1803          42 :                 wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,
    1804             :                                      &data);
    1805          42 :                 break;
    1806             :         case NL80211_CMD_NEW_STATION:
    1807        5116 :                 nl80211_new_station_event(drv, bss, tb);
    1808        5116 :                 break;
    1809             :         case NL80211_CMD_DEL_STATION:
    1810        5000 :                 nl80211_del_station_event(drv, tb);
    1811        5000 :                 break;
    1812             :         case NL80211_CMD_SET_REKEY_OFFLOAD:
    1813           0 :                 nl80211_rekey_offload_event(drv, tb);
    1814           0 :                 break;
    1815             :         case NL80211_CMD_PMKSA_CANDIDATE:
    1816           0 :                 nl80211_pmksa_candidate_event(drv, tb);
    1817           0 :                 break;
    1818             :         case NL80211_CMD_PROBE_CLIENT:
    1819           4 :                 nl80211_client_probe_event(drv, tb);
    1820           4 :                 break;
    1821             :         case NL80211_CMD_TDLS_OPER:
    1822           0 :                 nl80211_tdls_oper_event(drv, tb);
    1823           0 :                 break;
    1824             :         case NL80211_CMD_CONN_FAILED:
    1825           0 :                 nl80211_connect_failed_event(drv, tb);
    1826           0 :                 break;
    1827             :         case NL80211_CMD_FT_EVENT:
    1828           0 :                 mlme_event_ft_event(drv, tb);
    1829           0 :                 break;
    1830             :         case NL80211_CMD_RADAR_DETECT:
    1831          39 :                 nl80211_radar_event(drv, tb);
    1832          39 :                 break;
    1833             :         case NL80211_CMD_STOP_AP:
    1834           6 :                 nl80211_stop_ap(drv, tb);
    1835           6 :                 break;
    1836             :         case NL80211_CMD_VENDOR:
    1837           0 :                 nl80211_vendor_event(drv, tb);
    1838           0 :                 break;
    1839             :         case NL80211_CMD_NEW_PEER_CANDIDATE:
    1840          50 :                 nl80211_new_peer_candidate(drv, tb);
    1841          50 :                 break;
    1842             :         default:
    1843          35 :                 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
    1844             :                         "(cmd=%d)", cmd);
    1845          35 :                 break;
    1846             :         }
    1847             : }
    1848             : 
    1849             : 
    1850      207314 : int process_global_event(struct nl_msg *msg, void *arg)
    1851             : {
    1852      207314 :         struct nl80211_global *global = arg;
    1853      207314 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    1854             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
    1855             :         struct wpa_driver_nl80211_data *drv, *tmp;
    1856      207314 :         int ifidx = -1;
    1857             :         struct i802_bss *bss;
    1858      207314 :         u64 wdev_id = 0;
    1859      207314 :         int wdev_id_set = 0;
    1860             : 
    1861      207314 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    1862             :                   genlmsg_attrlen(gnlh, 0), NULL);
    1863             : 
    1864      207314 :         if (tb[NL80211_ATTR_IFINDEX])
    1865      196056 :                 ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
    1866       11258 :         else if (tb[NL80211_ATTR_WDEV]) {
    1867         145 :                 wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
    1868         145 :                 wdev_id_set = 1;
    1869             :         }
    1870             : 
    1871      327143 :         dl_list_for_each_safe(drv, tmp, &global->interfaces,
    1872             :                               struct wpa_driver_nl80211_data, list) {
    1873      290577 :                 for (bss = drv->first_bss; bss; bss = bss->next) {
    1874      333104 :                         if ((ifidx == -1 && !wdev_id_set) ||
    1875      285042 :                             ifidx == bss->ifindex ||
    1876         147 :                             (wdev_id_set && bss->wdev_id_set &&
    1877          29 :                              wdev_id == bss->wdev_id)) {
    1878       48091 :                                 do_process_drv_event(bss, gnlh->cmd, tb);
    1879       48091 :                                 return NL_SKIP;
    1880             :                         }
    1881             :                 }
    1882      119829 :                 wpa_printf(MSG_DEBUG,
    1883             :                            "nl80211: Ignored event (cmd=%d) for foreign interface (ifindex %d wdev 0x%llx)",
    1884      119829 :                            gnlh->cmd, ifidx, (long long unsigned int) wdev_id);
    1885             :         }
    1886             : 
    1887      159223 :         return NL_SKIP;
    1888             : }
    1889             : 
    1890             : 
    1891       12340 : int process_bss_event(struct nl_msg *msg, void *arg)
    1892             : {
    1893       12340 :         struct i802_bss *bss = arg;
    1894       12340 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    1895             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
    1896             : 
    1897       12340 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    1898             :                   genlmsg_attrlen(gnlh, 0), NULL);
    1899             : 
    1900       24680 :         wpa_printf(MSG_DEBUG, "nl80211: BSS Event %d (%s) received for %s",
    1901       24680 :                    gnlh->cmd, nl80211_command_to_string(gnlh->cmd),
    1902       12340 :                    bss->ifname);
    1903             : 
    1904       12340 :         switch (gnlh->cmd) {
    1905             :         case NL80211_CMD_FRAME:
    1906             :         case NL80211_CMD_FRAME_TX_STATUS:
    1907       12309 :                 mlme_event(bss, gnlh->cmd, tb[NL80211_ATTR_FRAME],
    1908             :                            tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
    1909             :                            tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
    1910             :                            tb[NL80211_ATTR_COOKIE],
    1911             :                            tb[NL80211_ATTR_RX_SIGNAL_DBM],
    1912             :                            tb[NL80211_ATTR_STA_WME]);
    1913       12309 :                 break;
    1914             :         case NL80211_CMD_UNEXPECTED_FRAME:
    1915          24 :                 nl80211_spurious_frame(bss, tb, 0);
    1916          24 :                 break;
    1917             :         case NL80211_CMD_UNEXPECTED_4ADDR_FRAME:
    1918           7 :                 nl80211_spurious_frame(bss, tb, 1);
    1919           7 :                 break;
    1920             :         default:
    1921           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
    1922           0 :                            "(cmd=%d)", gnlh->cmd);
    1923           0 :                 break;
    1924             :         }
    1925             : 
    1926       12340 :         return NL_SKIP;
    1927             : }

Generated by: LCOV version 1.10