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 1475438200 Lines: 740 1042 71.0 %
Date: 2016-10-02 Functions: 32 37 86.5 %

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

Generated by: LCOV version 1.10