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 1426431149 Lines: 716 1113 64.3 %
Date: 2015-03-15 Functions: 32 41 78.0 %

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

Generated by: LCOV version 1.10