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 1443382998 Lines: 716 1149 62.3 %
Date: 2015-09-27 Functions: 32 42 76.2 %

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

Generated by: LCOV version 1.10