diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2020-09-16 10:32:58 -0700 |
|---|---|---|
| committer | Linux Build Service Account <lnxbuild@localhost> | 2020-09-16 10:32:58 -0700 |
| commit | fdca8623992f3e99208505fbe97a8018b7ddda28 (patch) | |
| tree | 48625665ca506ef57875aa82ee5e37c03324ebd6 | |
| parent | 1dbbf9a4bf027a8c29b5da6cb2a08f5c148b1440 (diff) | |
| parent | 6f4ef445a4377b3ff65c772dd06d740d05e99bb9 (diff) | |
Merge 6f4ef445a4377b3ff65c772dd06d740d05e99bb9 on remote branch
Change-Id: I224ff82129090a7d4060e336eee6faa3ec2808c0
56 files changed, 1730 insertions, 600 deletions
@@ -197,6 +197,9 @@ ifeq ($(KERNEL_BUILD), 0) CONFIG_WLAN_FEATURE_DSRC := y endif +#Flag to enable SAE +CONFIG_WLAN_FEATURE_SAE := y + ifneq ($(CONFIG_ROME_IF),sdio) #Flag to enable DISA CONFIG_WLAN_FEATURE_DISA := y @@ -207,9 +210,6 @@ ifneq ($(CONFIG_ROME_IF),sdio) #Flag to enable GMAC CONFIG_WLAN_FEATURE_GMAC := y - #Flag to enable SAE - CONFIG_WLAN_FEATURE_SAE := y - #Flag to enable Fast Path feature CONFIG_WLAN_FASTPATH := y diff --git a/core/cds/inc/cds_ieee80211_common.h b/core/cds/inc/cds_ieee80211_common.h index 1cbaa4c385d3..cc3472d4f69e 100644 --- a/core/cds/inc/cds_ieee80211_common.h +++ b/core/cds/inc/cds_ieee80211_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011,2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2014-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -1631,6 +1631,7 @@ enum { #define AKM_SUITE_TYPE_FT_PSK 0x04 #define AKM_SUITE_TYPE_SHA256_IEEE8021X 0x05 #define AKM_SUITE_TYPE_SHA256_PSK 0x06 +#define AKM_SUITE_TYPE_SAE 0x08 #define RSN_CAP_PREAUTH 0x01 #define RSN_CAP_PTKSA_REPLAYCOUNTER 0x0c @@ -1686,6 +1687,25 @@ enum { #define IEEE80211_RV(v) ((v) & IEEE80211_RATE_VAL) +#define LE_READ_2(p) \ + ((uint16_t)\ + ((((const uint8_t *)(p))[0]) |\ + (((const uint8_t *)(p))[1] << 8))) + +#define LE_READ_4(p) \ + ((uint32_t)\ + ((((const uint8_t *)(p))[0]) |\ + (((const uint8_t *)(p))[1] << 8) | \ + (((const uint8_t *)(p))[2] << 16) |\ + (((const uint8_t *)(p))[3] << 24))) + +#define BE_READ_4(p) \ + ((uint32_t)\ + ((((const uint8_t *)(p))[0] << 24) |\ + (((const uint8_t *)(p))[1] << 16) |\ + (((const uint8_t *)(p))[2] << 8) |\ + (((const uint8_t *)(p))[3]))) + /* * AUTH management packets * diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c index a1f8cf6c4ea4..0fa40da3d445 100644 --- a/core/cds/src/cds_sched.c +++ b/core/cds/src/cds_sched.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -83,6 +83,12 @@ static int cds_mc_thread(void *Arg); static int cds_ol_mon_thread(void *arg); static QDF_STATUS cds_alloc_ol_mon_pkt_freeq(p_cds_sched_context pSchedContext); +static inline +int cds_set_cpus_allowed_ptr(struct task_struct *task, unsigned long cpu) +{ + return set_cpus_allowed_ptr(task, cpumask_of(cpu)); +} + #ifdef QCA_CONFIG_SMP static int cds_ol_rx_thread(void *arg); static uint32_t affine_cpu; @@ -95,13 +101,6 @@ static QDF_STATUS cds_alloc_ol_rx_pkt_freeq(p_cds_sched_context pSchedContext); #define CDS_CPU_CLUSTER_TYPE_LITTLE 0 #define CDS_CPU_CLUSTER_TYPE_PERF 1 -static inline -int cds_set_cpus_allowed_ptr(struct task_struct *task, unsigned long cpu) -{ - return set_cpus_allowed_ptr(task, cpumask_of(cpu)); -} - - /** * cds_sched_find_attach_cpu - find available cores and attach to required core * @pSchedContext: wlan scheduler context @@ -618,9 +617,8 @@ OL_MON_THREAD_START_FAILURE: wake_up_interruptible(&pSchedContext->ol_rx_wait_queue); /* Wait for RX Thread to exit */ wait_for_completion(&pSchedContext->ol_rx_shutdown); -#endif - OL_RX_THREAD_START_FAILURE: +#endif /* Try and force the Main thread controller to exit */ set_bit(MC_SHUTDOWN_EVENT, &pSchedContext->mcEventFlag); set_bit(MC_POST_EVENT, &pSchedContext->mcEventFlag); diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c index 08294827a010..c3f39316ae13 100644 --- a/core/dp/txrx/ol_tx_desc.c +++ b/core/dp/txrx/ol_tx_desc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2014-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -33,6 +33,7 @@ #include <ol_txrx_encap.h> /* OL_TX_RESTORE_HDR, etc */ #endif #include <ol_txrx.h> +#include <utils_api.h> #ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS static inline void ol_tx_desc_sanity_checks(struct ol_txrx_pdev_t *pdev, @@ -1003,4 +1004,48 @@ void ol_tso_num_seg_free(struct ol_txrx_pdev_t *pdev, pdev->tso_num_seg_pool.num_free++; qdf_spin_unlock_bh(&pdev->tso_num_seg_pool.tso_num_seg_mutex); } + +bool collect_tso_frags(struct ol_txrx_pdev_t *pdev, + struct qdf_tso_seg_elem_t *tso_seg, + qdf_nbuf_t netbuf) +{ + uint8_t frag_cnt, num_frags = 0; + int frag_len = 0; + uint32_t tcp_seq_num; + uint16_t ip_len; + + qdf_spin_lock_bh(&pdev->tso_seg_pool.tso_mutex); + + if (tso_seg->seg.num_frags > 0) + num_frags = tso_seg->seg.num_frags - 1; + + /*Num of frags in a tso seg cannot be less than 2 */ + if (num_frags < 1) { + qdf_print("ERROR: num of frags in tso segment is %d\n", + (num_frags + 1)); + qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); + return false; + } + + tcp_seq_num = tso_seg->seg.tso_flags.tcp_seq_num; + tcp_seq_num = ani_cpu_to_be32(tcp_seq_num); + + ip_len = tso_seg->seg.tso_flags.ip_len; + ip_len = ani_cpu_to_be16(ip_len); + + for (frag_cnt = 0; frag_cnt < num_frags; frag_cnt++) { + qdf_mem_copy(qdf_nbuf_data(netbuf) + frag_len, + tso_seg->seg.tso_frags[frag_cnt].vaddr, + tso_seg->seg.tso_frags[frag_cnt].length); + frag_len += tso_seg->seg.tso_frags[frag_cnt].length; + } + + qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); + + qdf_mem_copy((qdf_nbuf_data(netbuf) + IPV4_PKT_LEN_OFFSET), + &ip_len, sizeof(ip_len)); + qdf_mem_copy((qdf_nbuf_data(netbuf) + IPV4_TCP_SEQ_NUM_OFFSET), + &tcp_seq_num, sizeof(tcp_seq_num)); + return true; +} #endif diff --git a/core/dp/txrx/ol_tx_desc.h b/core/dp/txrx/ol_tx_desc.h index 6f920e4f0555..b29422ca0496 100644 --- a/core/dp/txrx/ol_tx_desc.h +++ b/core/dp/txrx/ol_tx_desc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2014-2017, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -239,7 +239,20 @@ void ol_tso_num_seg_free(struct ol_txrx_pdev_t *pdev, void ol_free_remaining_tso_segs(ol_txrx_vdev_handle vdev, struct ol_txrx_msdu_info_t *msdu_info, bool is_tso_seg_mapping_done); - +/** + * collect_tso_frags() - collect all TSO fragments + * @pdev: The txrx pdev sending the data + * @tso_seg: The TSO segment element to be checked + * @netbuf: Target netbuf used to store all data from TSO fragments + * + * This function collects data contained in all TSO fragments related + * to a certain TSO segment element and put them into a single netbuf. + * + * Return: true if TSO fragments are really collected; false otherwise + */ +bool collect_tso_frags(struct ol_txrx_pdev_t *pdev, + struct qdf_tso_seg_elem_t *tso_seg, + qdf_nbuf_t netbuf); #else #define ol_tso_alloc_segment(pdev) /*no-op*/ #define ol_tso_free_segment(pdev, tso_seg) /*no-op*/ @@ -247,6 +260,13 @@ void ol_free_remaining_tso_segs(ol_txrx_vdev_handle vdev, #define ol_tso_num_seg_free(pdev, tso_num_seg) /*no-op*/ /*no-op*/ #define ol_free_remaining_tso_segs(vdev, msdu_info, is_tso_seg_mapping_done) +static inline +bool collect_tso_frags(struct ol_txrx_pdev_t *dev, + struct qdf_tso_seg_elem_t *tso_seg, + qdf_nbuf_t netbuf) +{ + return false; +} #endif /** diff --git a/core/dp/txrx/ol_tx_send.c b/core/dp/txrx/ol_tx_send.c index a1c433499fe2..66860a314865 100644 --- a/core/dp/txrx/ol_tx_send.c +++ b/core/dp/txrx/ol_tx_send.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -837,6 +837,7 @@ ol_tx_process_mon_tx_completion( int nbuf_len; struct qdf_tso_seg_elem_t *tso_seg = NULL; struct ol_mon_tx_status pkt_tx_status = {0}; + bool frags_collected = false; pkt_tx_status.status = status; pkt_tx_status.tx_retry_cnt = payload->tx_retry_cnt; @@ -881,44 +882,11 @@ ol_tx_process_mon_tx_completion( qdf_nbuf_put_tail(netbuf, nbuf_len); if (tx_desc->pkt_type == OL_TX_FRM_TSO) { - uint8_t frag_cnt, num_frags = 0; - int frag_len = 0; - uint32_t tcp_seq_num; - uint16_t ip_len; - - qdf_spin_lock_bh(&pdev->tso_seg_pool.tso_mutex); - - if (tso_seg->seg.num_frags > 0) - num_frags = tso_seg->seg.num_frags - 1; - - /*Num of frags in a tso seg cannot be less than 2 */ - if (num_frags < 1) { - qdf_print("ERROR: num of frags in tso segment is %d\n", - (num_frags + 1)); + frags_collected = collect_tso_frags(pdev, tso_seg, netbuf); + if (!frags_collected) { qdf_nbuf_free(netbuf); - qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); return; } - - tcp_seq_num = tso_seg->seg.tso_flags.tcp_seq_num; - tcp_seq_num = ani_cpu_to_be32(tcp_seq_num); - - ip_len = tso_seg->seg.tso_flags.ip_len; - ip_len = ani_cpu_to_be16(ip_len); - - for (frag_cnt = 0; frag_cnt < num_frags; frag_cnt++) { - qdf_mem_copy(qdf_nbuf_data(netbuf) + frag_len, - tso_seg->seg.tso_frags[frag_cnt].vaddr, - tso_seg->seg.tso_frags[frag_cnt].length); - frag_len += tso_seg->seg.tso_frags[frag_cnt].length; - } - - qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); - - qdf_mem_copy((qdf_nbuf_data(netbuf) + IPV4_PKT_LEN_OFFSET), - &ip_len, sizeof(ip_len)); - qdf_mem_copy((qdf_nbuf_data(netbuf) + IPV4_TCP_SEQ_NUM_OFFSET), - &tcp_seq_num, sizeof(tcp_seq_num)); } else { qdf_mem_copy(qdf_nbuf_data(netbuf), qdf_nbuf_data(tx_desc->netbuf), diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 49ca04fccdbd..ecf0bf196a2e 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -5608,6 +5608,7 @@ bool ol_txrx_mon_mgmt_process(struct mon_rx_status *txrx_status, * * Return: none */ +#ifndef CONFIG_HL_SUPPORT static QDF_STATUS ol_txrx_convert8023to80311(uint8_t *bssid, qdf_nbuf_t msdu, void *desc) @@ -5713,6 +5714,7 @@ ol_txrx_convert8023to80311(uint8_t *bssid, return status; } +#endif #define SHORT_PREAMBLE 1 #define LONG_PREAMBLE 0 @@ -6114,6 +6116,17 @@ free_buf: * * Return: none */ +#ifdef CONFIG_HL_SUPPORT +static void +ol_txrx_mon_rx_data_cb(void *ppdev, void *nbuf_list, uint8_t vdev_id, + uint8_t tid, struct ol_mon_tx_status pkt_tx_status, + bool pkt_format) +{ + qdf_nbuf_t buf_list = (qdf_nbuf_t)nbuf_list; + + ol_txrx_drop_nbuf_list(buf_list); +} +#else static void ol_txrx_mon_rx_data_cb(void *ppdev, void *nbuf_list, uint8_t vdev_id, uint8_t tid, struct ol_mon_tx_status pkt_tx_status, @@ -6244,6 +6257,7 @@ ol_txrx_mon_rx_data_cb(void *ppdev, void *nbuf_list, uint8_t vdev_id, free_buf: drop_count = ol_txrx_drop_nbuf_list(buf_list); } +#endif /** * ol_txrx_pktcapture_status_map() - map Tx status for data packets diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 29cbd5a83397..d73f3528d2b5 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -13481,6 +13481,29 @@ enum hw_filter_mode { /* * <ini> + * enable_sae_for_sap - Enable/Disable SAE support in driver for SAP + * @Min: 0 + * @Max: 1 + * @Default: 1 + * + * This ini is used to enable/disable SAE support in driver for SAP mode + * Driver will process/drop the SAE authentication frames based on this config. + * + * Related: None + * + * Supported Feature: SAE + * Usage: External + * + * </ini> + */ + +#define CFG_ENABLE_SAE_FOR_SAP_NAME "enable_sae_for_sap" +#define CFG_ENABLE_SAE_FOR_SAP_DEFAULT (1) +#define CFG_ENABLE_SAE_FOR_SAP_MIN (0) +#define CFG_ENABLE_SAE_FOR_SAP_MAX (1) + +/* + * <ini> * chan_width_weightage - Channel Width Weightage to calculate best candidate * @Min: 0 * @Max: 100 @@ -15560,6 +15583,28 @@ enum hw_filter_mode { #define CFG_DISABLE_4WAY_HS_OFFLOAD_DEFAULT (0) /* + * <ini> + * nb_commands_interval - Used to rate limit nb commands from userspace + * + * @Min: 0 + * @Max: 10 + * Default: 3 + * + * This ini is used to specify the duration in which any supp. nb command from + * userspace will not be processed completely in driver. For ex, the default + * value of 3 seconds signifies that consecutive commands within that + * time will not be processed fully. + * + * Usage: Internal + * + * </ini> + */ +#define CFG_NB_COMMANDS_RATE_LIMIT "nb_commands_interval" +#define CFG_NB_COMMANDS_RATE_LIMIT_MIN (0) +#define CFG_NB_COMMANDS_RATE_LIMIT_MAX (10) +#define CFG_NB_COMMANDS_RATE_LIMIT_DEFAULT (3) + +/* * Type declarations */ @@ -16490,6 +16535,7 @@ struct hdd_config { uint8_t enable_tx_sch_delay; #ifdef WLAN_FEATURE_SAE bool is_sae_enabled; + bool enable_sae_for_sap; #endif bool enable_rtt_mac_randomization; bool enable_ftopen; @@ -16528,6 +16574,7 @@ struct hdd_config { bool disable_4way_hs_offload; bool ShortGI80MhzEnable; bool ShortGI160MhzEnable; + uint8_t nb_commands_interval; }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/inc/wlan_hdd_ipa.h b/core/hdd/inc/wlan_hdd_ipa.h index 9db92f432b71..d66b436aab7b 100644 --- a/core/hdd/inc/wlan_hdd_ipa.h +++ b/core/hdd/inc/wlan_hdd_ipa.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -100,6 +100,7 @@ bool hdd_ipa_is_fw_wdi_actived(hdd_context_t *hdd_ctx); #ifndef QCA_LL_TX_FLOW_CONTROL_V2 int hdd_ipa_send_mcc_scc_msg(hdd_context_t *hdd_ctx, bool mcc_mode); void hdd_ipa_set_mcc_mode(bool mcc_mode); +void hdd_ipa_mcc_work_handler(struct work_struct *work); #else static inline int hdd_ipa_send_mcc_scc_msg(hdd_context_t *hdd_ctx, bool mcc_mode) @@ -247,8 +248,8 @@ static inline void hdd_ipa_uc_stat_query(hdd_context_t *hdd_ctx, *ipa_rx_diff = 0; } -static inline void hdd_ipa_uc_stat_request(hdd_adapter_t *adapter, - uint8_t reason) +static inline void hdd_ipa_uc_stat_request(hdd_context_t *hdd_ctx, + uint8_t reason) { } diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 624d8ff03718..5daf67e646e6 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -62,6 +62,29 @@ #define NUM_TX_QUEUES 4 #endif +/* HDD_IS_RATE_LIMIT_REQ: Macro helper to implement rate limiting + * @flag: The flag to determine if limiting is required or not + * @rate: The number of seconds within which if multiple commands come, the + * flag will be set to true + * + * If the function in which this macro is used is called multiple times within + * "rate" number of seconds, the "flag" will be set to true which can be used + * to reject/take appropriate action. + */ +#define HDD_IS_RATE_LIMIT_REQ(flag, rate)\ + do {\ + static ulong __last_ticks;\ + ulong __ticks = jiffies;\ + flag = false; \ + if (!time_after(__ticks,\ + __last_ticks + rate * HZ)) {\ + flag = true; \ + } \ + else { \ + __last_ticks = __ticks;\ + } \ + } while (0) + /* * API in_compat_syscall() is introduced in 4.6 kernel to check whether we're * in a compat syscall or not. It is a new way to query the syscall type, which diff --git a/core/hdd/inc/wlan_hdd_p2p.h b/core/hdd/inc/wlan_hdd_p2p.h index f71ed6b1847a..0e024442898f 100644 --- a/core/hdd/inc/wlan_hdd_p2p.h +++ b/core/hdd/inc/wlan_hdd_p2p.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -98,9 +98,10 @@ int hdd_set_p2p_ps(struct net_device *dev, void *msgData); int hdd_set_p2p_opps(struct net_device *dev, uint8_t *command); int hdd_set_p2p_noa(struct net_device *dev, uint8_t *command); -void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, - uint32_t nFrameLength, uint8_t *pbFrames, - uint8_t frameType, uint32_t rxChan, int8_t rxRssi); +void __hdd_indicate_mgmt_frame(hdd_adapter_t *adapter, + uint32_t frame_length, uint8_t *frames, + uint8_t frame_type, uint32_t rx_chan, + int8_t rx_rssi, enum rxmgmt_flags rx_flags); void hdd_remain_chan_ready_handler(hdd_adapter_t *pAdapter, uint32_t scan_id); diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index df3aa8be02c8..dc070c6c7836 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -54,6 +54,7 @@ #include <wlan_logging_sock_svc.h> #include "wlan_hdd_tsf.h" #include "wlan_hdd_scan.h" +#include "wlan_hdd_main.h" /* These are needed to recognize WPA and RSN suite types */ #define HDD_WPA_OUI_SIZE 4 @@ -2307,10 +2308,10 @@ static void hdd_send_re_assoc_event(struct net_device *dev, chan_no = pCsrRoamInfo->pBssDesc->channelId; if (chan_no <= 14) freq = ieee80211_channel_to_frequency(chan_no, - NL80211_BAND_2GHZ); + HDD_NL80211_BAND_2GHZ); else freq = ieee80211_channel_to_frequency(chan_no, - NL80211_BAND_5GHZ); + HDD_NL80211_BAND_5GHZ); chan = ieee80211_get_channel(pAdapter->wdev.wiphy, freq); sme_roam_get_connect_profile(hal_handle, pAdapter->sessionId, diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index c47987d70367..11f9f3ca3e89 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -5625,6 +5625,12 @@ struct reg_table_entry g_registry_table[] = { CFG_IS_SAE_ENABLED_DEFAULT, CFG_IS_SAE_ENABLED_MIN, CFG_IS_SAE_ENABLED_MAX), + REG_VARIABLE(CFG_ENABLE_SAE_FOR_SAP_NAME, WLAN_PARAM_Integer, + struct hdd_config, enable_sae_for_sap, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_SAE_FOR_SAP_DEFAULT, + CFG_ENABLE_SAE_FOR_SAP_MIN, + CFG_ENABLE_SAE_FOR_SAP_MAX), #endif REG_VARIABLE(CFG_BTM_SOLICITED_TIMEOUT, WLAN_PARAM_Integer, @@ -5854,6 +5860,13 @@ struct reg_table_entry g_registry_table[] = { CFG_DISABLE_4WAY_HS_OFFLOAD_DEFAULT, CFG_DISABLE_4WAY_HS_OFFLOAD_MIN, CFG_DISABLE_4WAY_HS_OFFLOAD_MAX), + + REG_VARIABLE(CFG_NB_COMMANDS_RATE_LIMIT, WLAN_PARAM_Integer, + struct hdd_config, nb_commands_interval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NB_COMMANDS_RATE_LIMIT_DEFAULT, + CFG_NB_COMMANDS_RATE_LIMIT_MIN, + CFG_NB_COMMANDS_RATE_LIMIT_MAX), }; /** @@ -6795,10 +6808,21 @@ static void hdd_cfg_print_sae(hdd_context_t *hdd_ctx) CFG_IS_SAE_ENABLED_NAME, hdd_ctx->config->is_sae_enabled); } + +static void hdd_cfg_print_sae_sap(hdd_context_t *hdd_ctx) +{ + hdd_debug("Name = [%s] value = [%u]", + CFG_ENABLE_SAE_FOR_SAP_NAME, + hdd_ctx->config->enable_sae_for_sap); +} #else static void hdd_cfg_print_sae(hdd_context_t *hdd_ctx) { } + +static void hdd_cfg_print_sae_sap(hdd_context_t *hdd_ctx) +{ +} #endif #ifdef MWS_COEX @@ -7895,6 +7919,7 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) CFG_CHANNEL_SELECT_LOGIC_CONC_NAME, pHddCtx->config->channel_select_logic_conc); hdd_cfg_print_sae(pHddCtx); + hdd_cfg_print_sae_sap(pHddCtx); hdd_debug("Name = [%s] value = [0x%x]", CFG_ENABLE_UNIT_TEST_FRAMEWORK_NAME, pHddCtx->config->is_unit_test_framework_enabled); @@ -8670,6 +8695,34 @@ static bool hdd_update_vht_cap_in_cfg(hdd_context_t *hdd_ctx) } +#ifdef WLAN_FEATURE_SAE +/** + * hdd_update_sae_cfg() - API to update SAE setting to MAC/WNI layer + * @hdd_ctx: pointer to hdd_ctx + * + * This API reads the SAE setting from HDD config structure and updates the + * same to MAC/WNI layer. + * + * Return: true if operation is successful, false otherwise. + */ +static inline bool hdd_update_sae_cfg(hdd_context_t *hdd_ctx) +{ + bool status = true; + if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_SAP_SAE_ENABLED, + hdd_ctx->config->enable_sae_for_sap) == + QDF_STATUS_E_FAILURE) { + status = false; + hdd_err("Couldn't pass on WNI_CFG_SAP_SAE_ENABLED to CCM"); + } + return status; +} +#else +static inline bool hdd_update_sae_cfg(hdd_context_t *hdd_ctx) +{ + return true; +} +#endif + /** * hdd_update_config_cfg() - API to update INI setting based on hw/fw caps * @hdd_ctx: pointer to hdd_ctx @@ -9141,6 +9194,7 @@ bool hdd_update_config_cfg(hdd_context_t *hdd_ctx) hdd_err("Couldn't pass on WNI_CFG_RATE_FOR_TX_MGMT_5G to CCM"); } + status = hdd_update_sae_cfg(hdd_ctx); return status; } #ifdef FEATURE_WLAN_SCAN_PNO diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 6d077856b24c..75254e293084 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -14192,12 +14192,12 @@ static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx) if (band_5g) { for (i = 0; i < hdd_ctx->num_rf_chains; i++) band_5g->ht_cap.mcs.rx_mask[i] = 0xff; - /* - * According to mcs_nss HT MCS parameters highest data - * rate for Nss = 1 is 150 Mbps - */ - band_5g->ht_cap.mcs.rx_highest = - cpu_to_le16(150 * hdd_ctx->num_rf_chains); + /* + * According to mcs_nss HT MCS parameters highest data + * rate for Nss = 1 is 150 Mbps + */ + band_5g->ht_cap.mcs.rx_highest = + cpu_to_le16(150 * hdd_ctx->num_rf_chains); } } @@ -21672,13 +21672,56 @@ static int wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy, #if defined(WLAN_FEATURE_SAE) && \ defined(CFG80211_EXTERNAL_AUTH_SUPPORT) +#if defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT) +/** + * wlan_hdd_extauth_cache_pmkid() - Extract and cache pmkid + * @adapter: hdd vdev/net_device context + * @hHal: Handle to the hal + * @params: Pointer to external auth params. + * + * Extract the PMKID and BSS from external auth params and add to the + * PMKSA Cache in CSR. + */ +static void +wlan_hdd_extauth_cache_pmkid(hdd_adapter_t *adapter, + tHalHandle hHal, + struct cfg80211_external_auth_params *params) +{ + tPmkidCacheInfo pmk_cache; + QDF_STATUS result; + + if (params->pmkid) { + qdf_mem_zero(&pmk_cache, sizeof(pmk_cache)); + qdf_mem_copy(pmk_cache.BSSID.bytes, params->bssid, + MAC_ADDR_LEN); + qdf_mem_copy(pmk_cache.PMKID, params->pmkid, + CSR_RSN_PMKID_SIZE); + result = sme_roam_set_pmkid_cache(hHal, adapter->sessionId, + &pmk_cache, 1, false); + if (!QDF_IS_STATUS_SUCCESS(result)) + hdd_debug("external_auth: Failed to cache PMKID"); + } +} +#else +static void +wlan_hdd_extauth_cache_pmkid(hdd_adapter_t *adapter, + tHalHandle hHal, + struct cfg80211_external_auth_params *params) +{} +#endif /** * __wlan_hdd_cfg80211_external_auth() - Handle external auth + * * @wiphy: Pointer to wireless phy * @dev: net device - * @params: Pointer to external auth params - * + * @params: Pointer to external auth params. * Return: 0 on success, negative errno on failure + * + * Userspace sends status of the external authentication(e.g., SAE) with a peer. + * The message carries BSSID of the peer and auth status (WLAN_STATUS_SUCCESS/ + * WLAN_STATUS_UNSPECIFIED_FAILURE) in params. + * Userspace may send PMKID in params, which can be used for + * further connections. */ static int __wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy, @@ -21688,6 +21731,7 @@ __wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy, hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *hdd_ctx = wiphy_priv(wiphy); int ret; + struct qdf_mac_addr peer_mac_addr; if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) { hdd_err("Command not allowed in FTM mode"); @@ -21703,8 +21747,14 @@ __wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy, if (ret) return ret; - hdd_debug("external_auth status: %d", params->status); - sme_handle_sae_msg(hdd_ctx->hHal, adapter->sessionId, params->status); + hdd_debug("external_auth status: %d peer mac: " MAC_ADDRESS_STR, + params->status, MAC_ADDR_ARRAY(params->bssid)); + qdf_mem_copy(peer_mac_addr.bytes, params->bssid, MAC_ADDR_LEN); + + wlan_hdd_extauth_cache_pmkid(adapter, hdd_ctx->hHal, params); + + sme_handle_sae_msg(hdd_ctx->hHal, adapter->sessionId, params->status, + peer_mac_addr); return ret; } diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 8c4d993b62cb..eb4c8374285a 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -410,10 +410,10 @@ static int wlan_hdd_probe(struct device *dev, void *bdev, const struct hif_bus_i * during load time and during re-init */ cds_set_recovery_in_progress(false); + hdd_start_complete(0); if (!reinit) { cds_set_load_in_progress(false); cds_set_driver_loaded(true); - hdd_start_complete(0); } hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); @@ -444,6 +444,7 @@ err_init_qdf_ctx: hdd_remove_pm_qos(dev); hdd_stop_driver_ops_timer(); + hdd_start_complete(ret); mutex_unlock(&hdd_init_deinit_lock); return check_for_probe_defer(ret); } diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index f232d18428a7..ff2e4c11667a 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -596,6 +596,7 @@ static int __hdd_hostapd_set_mac_address(struct net_device *dev, void *addr) hdd_info("Changing MAC to " MAC_ADDRESS_STR " of interface %s ", MAC_ADDR_ARRAY(mac_addr.bytes), dev->name); + memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN); memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN); EXIT(); return 0; @@ -9023,7 +9024,7 @@ static void hdd_update_beacon_rate(hdd_adapter_t *adapter, struct cfg80211_bitrate_mask *beacon_rate_mask; enum nl80211_band band; - band = params->chandef.chan->band; + band = (enum nl80211_band)params->chandef.chan->band; beacon_rate_mask = ¶ms->beacon_rate; if (beacon_rate_mask->control[band].legacy) { adapter->sessionCtx.ap.sapConfig.beacon_tx_rate = diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index f2275fc5e09f..6d1377ef0b02 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -6783,7 +6783,7 @@ void hdd_ipa_set_mcc_mode(bool mcc_mode) schedule_work(&hdd_ipa->mcc_work); } -static void hdd_ipa_mcc_work_handler(struct work_struct *work) +void hdd_ipa_mcc_work_handler(struct work_struct *work) { struct hdd_ipa_priv *hdd_ipa; hdd_context_t *hdd_ctx; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 4aa922e2b903..b516be33874a 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5142,6 +5142,7 @@ QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, wlan_hdd_del_station(adapter); hdd_ipa_flush(hdd_ctx); + qdf_flush_work(&hdd_ctx->sap_pre_cac_work); case QDF_P2P_GO_MODE: if (hdd_ctx->config->conc_custom_rule1 && @@ -5312,7 +5313,7 @@ QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx, bool close_session) ENTER(); - cds_flush_work(&hdd_ctx->sap_pre_cac_work); + qdf_flush_work(&hdd_ctx->sap_pre_cac_work); cds_flush_sta_ap_intf_work(hdd_ctx); status = hdd_get_front_adapter(hdd_ctx, &adapterNode); @@ -5364,7 +5365,7 @@ QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx) ENTER(); - cds_flush_work(&hdd_ctx->sap_pre_cac_work); + qdf_flush_work(&hdd_ctx->sap_pre_cac_work); cds_flush_sta_ap_intf_work(hdd_ctx); status = hdd_get_front_adapter(hdd_ctx, &adapterNode); @@ -8780,7 +8781,8 @@ void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind) frame_ind->frameBuf, frame_ind->frameType, frame_ind->rxChan, - frame_ind->rxRssi); + frame_ind->rxRssi, + frame_ind->rx_flags); } status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next); @@ -8799,7 +8801,8 @@ void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind) frame_ind->frameBuf, frame_ind->frameType, frame_ind->rxChan, - frame_ind->rxRssi); + frame_ind->rxRssi, + frame_ind->rx_flags); } /** @@ -12802,7 +12805,7 @@ static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp, goto exit; } - if (!cds_is_driver_loaded()) { + if (!cds_is_driver_loaded() || cds_is_driver_recovering()) { init_completion(&wlan_start_comp); rc = wait_for_completion_timeout(&wlan_start_comp, msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME)); diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index cd147f16a76a..88a7a212e170 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -2003,7 +2003,8 @@ static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, * When frame to be transmitted is auth mgmt, then trigger * sme_send_mgmt_tx to send auth frame */ - if ((pAdapter->device_mode == QDF_STA_MODE) && + if ((pAdapter->device_mode == QDF_STA_MODE || + pAdapter->device_mode == QDF_SAP_MODE) && (type == SIR_MAC_MGMT_FRAME && subType == SIR_MAC_MGMT_AUTH)) { qdf_status = sme_send_mgmt_tx(WLAN_HDD_GET_HAL_CTX(pAdapter), @@ -3593,15 +3594,62 @@ static uint16_t get_rx_frame_freq_from_chan(uint32_t rx_chan) HDD_NL80211_BAND_5GHZ); } +#if defined(WLAN_FEATURE_SAE) && defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT) +/** + * wlan_hdd_set_rxmgmt_external_auth_flag() - Set the EXTERNAL_AUTH flag + * @nl80211_flag: flags to be sent to nl80211 from enum nl80211_rxmgmt_flags + * + * Set the flag NL80211_RXMGMT_FLAG_EXTERNAL_AUTH if supported. + */ +static void +wlan_hdd_set_rxmgmt_external_auth_flag(enum nl80211_rxmgmt_flags *nl80211_flag) +{ + *nl80211_flag |= NL80211_RXMGMT_FLAG_EXTERNAL_AUTH; +} +#else +static void +wlan_hdd_set_rxmgmt_external_auth_flag(enum nl80211_rxmgmt_flags *nl80211_flag) +{ +} +#endif + +/** + * wlan_hdd_cfg80211_convert_rxmgmt_flags() - Convert RXMGMT value + * @nl80211_flag: Flags to be sent to nl80211 from enum nl80211_rxmgmt_flags + * @flag: flags set by driver(SME/PE) from enum rxmgmt_flags + * + * Convert driver internal RXMGMT flag value to nl80211 defined RXMGMT flag + * Return: 0 on success, -EINVAL on invalid value + */ +static int +wlan_hdd_cfg80211_convert_rxmgmt_flags(enum rxmgmt_flags flag, + enum nl80211_rxmgmt_flags *nl80211_flag) +{ + int ret = -EINVAL; + + if (flag & RXMGMT_FLAG_EXTERNAL_AUTH) { + wlan_hdd_set_rxmgmt_external_auth_flag(nl80211_flag); + ret = 0; + } + + return ret; +} + static void indicate_rx_mgmt_over_nl80211(hdd_adapter_t *adapter, uint32_t frm_len, uint8_t *pb_frames, uint16_t freq, - int8_t rx_rssi) + int8_t rx_rssi, + enum rxmgmt_flags rx_flags) { + enum nl80211_rxmgmt_flags nl80211_flag = 0; + + if (wlan_hdd_cfg80211_convert_rxmgmt_flags(rx_flags, &nl80211_flag)) + hdd_debug("Failed to convert RXMGMT flags :0x%x to nl80211 format", + rx_flags); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) cfg80211_rx_mgmt(adapter->dev->ieee80211_ptr, freq, rx_rssi * 100, pb_frames, - frm_len, NL80211_RXMGMT_FLAG_ANSWERED); + frm_len, NL80211_RXMGMT_FLAG_ANSWERED | nl80211_flag); #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) cfg80211_rx_mgmt(adapter->dev->ieee80211_ptr, freq, rx_rssi * 100, pb_frames, @@ -3616,7 +3664,8 @@ static void indicate_rx_mgmt_over_nl80211(hdd_adapter_t *adapter, void __hdd_indicate_mgmt_frame(hdd_adapter_t *adapter, uint32_t frm_len, uint8_t *pb_frames, uint8_t frame_type, - uint32_t rx_chan, int8_t rx_rssi) + uint32_t rx_chan, int8_t rx_rssi, + enum rxmgmt_flags rx_flags) { uint16_t freq; uint8_t type = 0; @@ -3718,6 +3767,6 @@ indicate: adapter->sessionId, adapter->dev->ifindex); indicate_rx_mgmt_over_nl80211(adapter, frm_len, pb_frames, - freq, rx_rssi); + freq, rx_rssi, rx_flags); } diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 7e95159b4ae0..74121adc0ddd 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -1998,9 +1998,7 @@ int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, struct cfg80211_wowlan *wow) { -#ifdef QCA_CONFIG_SMP #define RX_TLSHIM_SUSPEND_TIMEOUT 200 /* msecs */ -#endif hdd_context_t *pHddCtx = wiphy_priv(wiphy); p_cds_sched_context cds_sched_context = get_cds_sched_ctxt(); hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; @@ -2216,8 +2214,8 @@ resume_all: #ifdef QCA_CONFIG_SMP complete(&cds_sched_context->ol_resume_rx_event); pHddCtx->is_ol_rx_thread_suspended = false; -#endif resume_mc: +#endif complete(&cds_sched_context->ResumeMcEvent); pHddCtx->isMcThreadSuspended = false; @@ -2507,6 +2505,7 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev); int status; hdd_station_ctx_t *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + static bool is_rate_limited; ENTER(); @@ -2532,10 +2531,14 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, return -EINVAL; } + HDD_IS_RATE_LIMIT_REQ(is_rate_limited, + pHddCtx->config->nb_commands_interval); + mutex_lock(&pHddCtx->iface_change_lock); - if (pHddCtx->driver_status != DRIVER_MODULES_ENABLED) { + if (pHddCtx->driver_status != DRIVER_MODULES_ENABLED || + is_rate_limited) { mutex_unlock(&pHddCtx->iface_change_lock); - hdd_debug("Driver Module not enabled return success"); + hdd_debug("Modules not enabled/rate limited, use cached stats"); /* Send cached data to upperlayer*/ *dbm = adapter->hdd_stats.ClassA_stat.max_pwr; return 0; diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 5b7d009630c1..e2e762c9a69e 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -35,6 +35,8 @@ #include "wma_api.h" #include "wma.h" +#define HDD_LINK_STATS_MAX 5 + /* 11B, 11G Rate table include Basic rate and Extended rate * The IDX field is the rate index * The HI field is the rate when RSSI is strong or being ignored @@ -125,10 +127,29 @@ static int rssi_mcs_tbl[][10] = { {-76, -73, -71, -68, -64, -60, -59, -58, -53, -51} /* 80 */ }; - #ifdef WLAN_FEATURE_LINK_LAYER_STATS /** + * struct hdd_ll_stats - buffered hdd link layer stats + * @ll_stats_node: pointer to next stats buffered in scheduler thread context + * @result_param_id: Received link layer stats ID + * @result: received stats from FW + * @more_data: if more stats are pending + * @no_of_radios: no of radios + * @no_of_peers: no of peers + */ +struct hdd_ll_stats { + qdf_list_node_t ll_stats_node; + u32 result_param_id; + void *result; + u32 more_data; + union { + u32 no_of_radios; + u32 no_of_peers; + } stats_nradio_npeer; +}; + +/** * put_wifi_rate_stat() - put wifi rate stats * @stats: Pointer to stats context * @vendor_event: Pointer to vendor event @@ -861,15 +882,22 @@ static int hdd_llstats_post_radio_stats(hdd_adapter_t *adapter, QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS, radiostat->numChannels)) { hdd_err("QCA_WLAN_VENDOR_ATTR put fail"); + goto failure; } if (radiostat->total_num_tx_power_levels) { - if (nla_put(vendor_event, + ret = + nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL, sizeof(u32) * radiostat->total_num_tx_power_levels, - radiostat->tx_time_per_power_level)) { + radiostat->tx_time_per_power_level); + qdf_mem_free(radiostat->tx_time_per_power_level); + radiostat->tx_time_per_power_level = NULL; + if (ret) { + qdf_mem_free(radiostat->channels); + radiostat->channels = NULL; hdd_err("nla_put fail"); goto failure; } @@ -878,6 +906,8 @@ static int hdd_llstats_post_radio_stats(hdd_adapter_t *adapter, if (radiostat->numChannels) { ret = hdd_llstats_radio_fill_channels(adapter, radiostat, vendor_event); + qdf_mem_free(radiostat->channels); + radiostat->channels = NULL; if (ret) goto failure; } @@ -954,74 +984,186 @@ static void hdd_link_layer_process_radio_stats(hdd_adapter_t *pAdapter, EXIT(); } -/** - * hdd_ll_process_radio_stats() - Wrapper function for cfg80211/debugfs - * @adapter: Pointer to device adapter - * @more_data: More data - * @data: Pointer to stats data - * @num_radios: Number of radios - * @resp_id: Response ID from FW - * - * Receiving Link Layer Radio statistics from FW. This function is a wrapper - * function which calls cfg80211/debugfs functions based on the response ID. - * - * Return: None - */ -static void hdd_ll_process_radio_stats(hdd_adapter_t *adapter, - uint32_t more_data, void *data, uint32_t num_radio, - uint32_t resp_id) +static void hdd_process_ll_stats(tSirLLStatsResults *results, + struct hdd_request *request) { - if (DEBUGFS_LLSTATS_REQID == resp_id) - hdd_debugfs_process_radio_stats(adapter, more_data, - (tpSirWifiRadioStat)data, num_radio); - else - hdd_link_layer_process_radio_stats(adapter, more_data, - (tpSirWifiRadioStat)data, num_radio); -} + struct hdd_ll_stats_priv *priv = hdd_request_priv(request); + struct hdd_ll_stats *stats = NULL; + size_t stat_size = 0; -/** - * hdd_ll_process_iface_stats() - Wrapper function for cfg80211/debugfs - * @adapter: Pointer to device adapter - * @data: Pointer to stats data - * @num_peers: Number of peers - * @resp_id: Response ID from FW - * - * Receiving Link Layer Radio statistics from FW. This function is a wrapper - * function which calls cfg80211/debugfs functions based on the response ID. - * - * Return: None - */ -static void hdd_ll_process_iface_stats(hdd_adapter_t *adapter, - void *data, uint32_t num_peers, uint32_t resp_id) -{ - if (DEBUGFS_LLSTATS_REQID == resp_id) - hdd_debugfs_process_iface_stats(adapter, - (tpSirWifiIfaceStat) data, num_peers); - else - hdd_link_layer_process_iface_stats(adapter, - (tpSirWifiIfaceStat) data, num_peers); + if (!(priv->request_bitmap & results->paramId)) + return; + + if (results->paramId & WMI_LINK_STATS_RADIO) { + tpSirWifiRadioStat rs_results, stat_result; + u64 channel_size = 0, pwr_lvl_size = 0; + int i; + stats = qdf_mem_malloc(sizeof(*stats)); + if (!stats) + goto exit; + + stat_size = sizeof(tSirWifiRadioStat) * results->num_radio; + stats->result_param_id = WMI_LINK_STATS_RADIO; + stat_result = qdf_mem_malloc(stat_size); + if (!stat_result) { + qdf_mem_free(stats); + goto exit; + } + stats->result = stat_result; + rs_results = (tpSirWifiRadioStat)results->results; + qdf_mem_copy(stats->result, results->results, stat_size); + for (i = 0; i < results->num_radio; i++) { + channel_size = rs_results->numChannels * + sizeof(tSirWifiChannelStats); + pwr_lvl_size = sizeof(uint32_t) * + rs_results->total_num_tx_power_levels; + + if (rs_results->total_num_tx_power_levels && + rs_results->tx_time_per_power_level) { + stat_result->tx_time_per_power_level = + qdf_mem_malloc(pwr_lvl_size); + if (!stat_result->tx_time_per_power_level) { + while (i-- > 0) { + stat_result--; + qdf_mem_free(stat_result-> + tx_time_per_power_level); + qdf_mem_free(stat_result-> + channels); + } + qdf_mem_free(stat_result); + qdf_mem_free(stats); + goto exit; + } + qdf_mem_copy(stat_result->tx_time_per_power_level, + rs_results->tx_time_per_power_level, + pwr_lvl_size); + } + if (channel_size) { + stat_result->channels = + qdf_mem_malloc(channel_size); + if (!stat_result->channels) { + qdf_mem_free(stat_result-> + tx_time_per_power_level); + while (i-- > 0) { + stat_result--; + qdf_mem_free(stat_result-> + tx_time_per_power_level); + qdf_mem_free(stat_result-> + channels); + } + qdf_mem_free(stats->result); + qdf_mem_free(stats); + goto exit; + } + qdf_mem_copy(stat_result->channels, + rs_results->channels, + channel_size); + } + rs_results++; + stat_result++; + } + stats->stats_nradio_npeer.no_of_radios = results->num_radio; + stats->more_data = results->moreResultToFollow; + if (!results->moreResultToFollow) + priv->request_bitmap &= ~stats->result_param_id; + } else if (results->paramId & WMI_LINK_STATS_IFACE) { + stats = qdf_mem_malloc(sizeof(*stats)); + if (!stats) + goto exit; + + stats->result_param_id = WMI_LINK_STATS_IFACE; + stats->stats_nradio_npeer.no_of_peers = results->num_peers; + stats->result = qdf_mem_malloc(sizeof(tSirWifiIfaceStat)); + if (!stats->result) { + qdf_mem_free(stats); + goto exit; + } + qdf_mem_copy(stats->result, results->results, + sizeof(tSirWifiIfaceStat)); + if (!results->num_peers) + priv->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER); + priv->request_bitmap &= ~stats->result_param_id; + } else if (results->paramId & WMI_LINK_STATS_ALL_PEER) { + tpSirWifiPeerStat peer_stat = (tpSirWifiPeerStat) + results->results; + tpSirWifiPeerInfo peer_info = NULL; + u64 num_rate = 0, peers, rates; + int i; + stats = qdf_mem_malloc(sizeof(*stats)); + if (!stats) + goto exit; + + peer_info = (tpSirWifiPeerInfo)peer_stat->peerInfo; + for (i = 1; i <= peer_stat->numPeers; i++) { + num_rate += peer_info->numRate; + peer_info = (tpSirWifiPeerInfo)((uint8_t *) + peer_info + sizeof(tSirWifiPeerInfo) + + (peer_info->numRate * + sizeof(tSirWifiRateStat))); + } + + peers = sizeof(tSirWifiPeerInfo) * peer_stat->numPeers; + rates = sizeof(tSirWifiRateStat) * num_rate; + stat_size = sizeof(tSirWifiPeerStat) + peers + rates; + stats->result_param_id = WMI_LINK_STATS_ALL_PEER; + + stats->result = qdf_mem_malloc(stat_size); + if (!stats->result) { + qdf_mem_free(stats); + goto exit; + } + + qdf_mem_copy(stats->result, results->results, stat_size); + stats->more_data = results->moreResultToFollow; + if (!results->moreResultToFollow) + priv->request_bitmap &= ~stats->result_param_id; + } else { + hdd_err("INVALID LL_STATS_NOTIFY RESPONSE"); + } + /* send indication to caller thread */ + if (stats) + qdf_list_insert_back(&priv->ll_stats_q, &stats->ll_stats_node); + + if (!priv->request_bitmap) +exit: + hdd_request_complete(request); } -/** - * hdd_ll_process_peer_stats() - Wrapper function for cfg80211/debugfs - * @adapter: Pointer to device adapter - * @more_data: More data - * @data: Pointer to stats data - * @resp_id: Response ID from FW - * - * Receiving Link Layer Radio statistics from FW. This function is a wrapper - * function which calls cfg80211/debugfs functions based on the response ID. - * - * Return: None - */ -static void hdd_ll_process_peer_stats(hdd_adapter_t *adapter, - uint32_t more_data, void *data, uint32_t resp_id) +static void hdd_debugfs_process_ll_stats(hdd_adapter_t *adapter, + tSirLLStatsResults *results, + struct hdd_request *request) { - if (DEBUGFS_LLSTATS_REQID == resp_id) - hdd_debugfs_process_peer_stats(adapter, data); - else - hdd_link_layer_process_peer_stats(adapter, more_data, - (tpSirWifiPeerStat) data); + struct hdd_ll_stats_priv *priv = hdd_request_priv(request); + + if (results->paramId & WMI_LINK_STATS_RADIO) { + hdd_debugfs_process_radio_stats(adapter, + results->moreResultToFollow, + results->results, + results->num_radio); + if (!results->moreResultToFollow) + priv->request_bitmap &= ~(WMI_LINK_STATS_RADIO); + } else if (results->paramId & WMI_LINK_STATS_IFACE) { + hdd_debugfs_process_iface_stats(adapter, results->results, + results->num_peers); + + /* Firmware doesn't send peerstats event if no peers are + * connected. HDD should not wait for any peerstats in + * this case and return the status to middleware after + * receiving iface stats + */ + + if (!results->num_peers) + priv->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER); + } else if (results->paramId & WMI_LINK_STATS_ALL_PEER) { + hdd_debugfs_process_peer_stats(adapter, results->results); + if (!results->moreResultToFollow) + priv->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER); + } else { + hdd_err("INVALID LL_STATS_NOTIFY RESPONSE"); + } + + if (!priv->request_bitmap) + hdd_request_complete(request); } /** @@ -1081,61 +1223,25 @@ void wlan_hdd_cfg80211_link_layer_stats_callback(void *ctx, int indType, priv = hdd_request_priv(request); /* validate response received from target */ - if ((priv->request_id != linkLayerStatsResults->rspId) || - !(priv->request_bitmap & linkLayerStatsResults->paramId)) { - hdd_err("Error : Request id %d response id %d request bitmap 0x%x response bitmap 0x%x", - priv->request_id, linkLayerStatsResults->rspId, - priv->request_bitmap, linkLayerStatsResults->paramId); + if (priv->request_id != linkLayerStatsResults->rspId) { + hdd_err("Request id %d response id %d request bitmap 0x%x response bitmap 0x%x", + priv->request_id, linkLayerStatsResults->rspId, + priv->request_bitmap, linkLayerStatsResults->paramId); hdd_request_put(request); return; } - if (linkLayerStatsResults->paramId & WMI_LINK_STATS_RADIO) { - hdd_ll_process_radio_stats(pAdapter, - linkLayerStatsResults->moreResultToFollow, - linkLayerStatsResults->results, - linkLayerStatsResults->num_radio, - linkLayerStatsResults->rspId); - - if (!linkLayerStatsResults->moreResultToFollow) - priv->request_bitmap &= ~(WMI_LINK_STATS_RADIO); - - } else if (linkLayerStatsResults->paramId & - WMI_LINK_STATS_IFACE) { - hdd_ll_process_iface_stats(pAdapter, - linkLayerStatsResults->results, - linkLayerStatsResults->num_peers, - linkLayerStatsResults->rspId); - - /* Firmware doesn't send peerstats event if no peers are - * connected. HDD should not wait for any peerstats in - * this case and return the status to middleware after - * receiving iface stats - */ - if (!linkLayerStatsResults->num_peers) - priv->request_bitmap &= - ~(WMI_LINK_STATS_ALL_PEER); - priv->request_bitmap &= ~(WMI_LINK_STATS_IFACE); - - } else if (linkLayerStatsResults-> - paramId & WMI_LINK_STATS_ALL_PEER) { - hdd_ll_process_peer_stats(pAdapter, - linkLayerStatsResults->moreResultToFollow, - linkLayerStatsResults->results, - linkLayerStatsResults->rspId); - - if (!linkLayerStatsResults->moreResultToFollow) - priv->request_bitmap &= - ~(WMI_LINK_STATS_ALL_PEER); - - } else { - hdd_err("INVALID LL_STATS_NOTIFY RESPONSE"); + if (linkLayerStatsResults->rspId == DEBUGFS_LLSTATS_REQID) { + hdd_debugfs_process_ll_stats(pAdapter, + linkLayerStatsResults, + request); + } else { + qdf_spin_lock(&priv->ll_stats_lock); + if (priv->request_bitmap) + hdd_process_ll_stats(linkLayerStatsResults, request); + qdf_spin_unlock(&priv->ll_stats_lock); } - /* complete response event if all requests are completed */ - if (!priv->request_bitmap) - hdd_request_complete(request); - hdd_request_put(request); break; } @@ -1312,6 +1418,46 @@ nla_policy [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK] = {.type = NLA_U32} }; +static void wlan_hdd_handle_ll_stats(hdd_adapter_t *adapter, + struct hdd_ll_stats *stats, + int ret) +{ + switch (stats->result_param_id) { + case WMI_LINK_STATS_RADIO: + { + tpSirWifiRadioStat radio_stat = stats->result; + int i, num_radio = stats->stats_nradio_npeer.no_of_radios; + + if (ret == -ETIMEDOUT) { + for (i = 0; i < num_radio; i++) { + if (radio_stat->numChannels) + qdf_mem_free(radio_stat->channels); + if (radio_stat->total_num_tx_power_levels) + qdf_mem_free(radio_stat-> + tx_time_per_power_level); + radio_stat++; + } + return; + } + hdd_link_layer_process_radio_stats(adapter, stats->more_data, + radio_stat, num_radio); + } + break; + case WMI_LINK_STATS_IFACE: + hdd_link_layer_process_iface_stats(adapter, stats->result, + stats->stats_nradio_npeer. + no_of_peers); + break; + case WMI_LINK_STATS_ALL_PEER: + hdd_link_layer_process_peer_stats(adapter, + stats->more_data, + stats->result); + break; + default: + hdd_err("not requested event"); + } +} + /** * wlan_hdd_send_ll_stats_req() - send LL stats request * @hdd_ctx: pointer to hdd context @@ -1319,12 +1465,16 @@ nla_policy * * Return: 0 if success, non-zero if failure */ -static int wlan_hdd_send_ll_stats_req(hdd_context_t *hdd_ctx, +static int wlan_hdd_send_ll_stats_req(hdd_adapter_t *adapter, tSirLLStatsGetReq *req) { int ret = 0; - struct hdd_ll_stats_priv *priv = NULL; + struct hdd_ll_stats_priv *priv; + struct hdd_ll_stats *stats = NULL; struct hdd_request *request = NULL; + qdf_list_node_t *ll_node; + QDF_STATUS status; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); void *cookie = NULL; static const struct hdd_request_params params = { .priv_size = sizeof(*priv), @@ -1345,6 +1495,8 @@ static int wlan_hdd_send_ll_stats_req(hdd_context_t *hdd_ctx, priv->request_id = req->reqId; priv->request_bitmap = req->paramIdMask; + qdf_spinlock_create(&priv->ll_stats_lock); + qdf_list_create(&priv->ll_stats_q, HDD_LINK_STATS_MAX); if (QDF_STATUS_SUCCESS != sme_ll_stats_get_req(hdd_ctx->hHal, req, cookie)) { @@ -1352,18 +1504,33 @@ static int wlan_hdd_send_ll_stats_req(hdd_context_t *hdd_ctx, ret = -EINVAL; goto exit; } - ret = hdd_request_wait_for_response(request); if (ret) { hdd_err("Target response timed out request id %d request bitmap 0x%x", priv->request_id, priv->request_bitmap); + qdf_spin_lock(&priv->ll_stats_lock); + priv->request_bitmap = 0; + qdf_spin_unlock(&priv->ll_stats_lock); ret = -ETIMEDOUT; - goto exit; } - EXIT(); - + qdf_spin_lock(&priv->ll_stats_lock); + status = qdf_list_remove_front(&priv->ll_stats_q, &ll_node); + qdf_spin_unlock(&priv->ll_stats_lock); + while (QDF_IS_STATUS_SUCCESS(status)) { + stats = qdf_container_of(ll_node, struct hdd_ll_stats, + ll_stats_node); + wlan_hdd_handle_ll_stats(adapter, stats, ret); + qdf_mem_free(stats->result); + qdf_mem_free(stats); + qdf_spin_lock(&priv->ll_stats_lock); + status = qdf_list_remove_front(&priv->ll_stats_q, &ll_node); + qdf_spin_unlock(&priv->ll_stats_lock); + } + qdf_list_destroy(&priv->ll_stats_q); exit: + EXIT(); hdd_request_put(request); + return ret; } @@ -1406,7 +1573,7 @@ int wlan_hdd_ll_stats_get(hdd_adapter_t *adapter, uint32_t req_id, } rtnl_lock(); - ret = wlan_hdd_send_ll_stats_req(hdd_ctx, &get_req); + ret = wlan_hdd_send_ll_stats_req(adapter, &get_req); rtnl_unlock(); if (0 != ret) hdd_err("Send LL stats req failed, id:%u, mask:%d, session:%d", @@ -1493,7 +1660,7 @@ __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, return -EINVAL; } - ret = wlan_hdd_send_ll_stats_req(pHddCtx, &LinkLayerStatsGetReq); + ret = wlan_hdd_send_ll_stats_req(pAdapter, &LinkLayerStatsGetReq); if (0 != ret) { hdd_err("Failed to send LL stats request (id:%u)", LinkLayerStatsGetReq.reqId); diff --git a/core/hdd/src/wlan_hdd_stats.h b/core/hdd/src/wlan_hdd_stats.h index 496106f682a3..48e9b05ed200 100644 --- a/core/hdd/src/wlan_hdd_stats.h +++ b/core/hdd/src/wlan_hdd_stats.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018,2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -81,13 +81,17 @@ struct index_data_rate_type { /** * struct hdd_ll_stats_priv - hdd link layer stats private - * + * @ll_stats: head to different link layer stats received in scheduler + * thread context * @request_id: userspace-assigned link layer stats request id * @request_bitmap: userspace-assigned link layer stats request bitmap + * @ll_stats_lock: Lock to serially access request_bitmap */ struct hdd_ll_stats_priv { + qdf_list_t ll_stats_q; uint32_t request_id; uint32_t request_bitmap; + qdf_spinlock_t ll_stats_lock; }; /* diff --git a/core/mac/inc/ani_system_defs.h b/core/mac/inc/ani_system_defs.h index 9cf44ca3f203..d6b938bc4683 100644 --- a/core/mac/inc/ani_system_defs.h +++ b/core/mac/inc/ani_system_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -200,4 +200,35 @@ typedef struct sBcnReportFields { uint16_t CapabilityInfo; } qdf_packed tBcnReportFields, *tpBcnReportFields; +enum ani_akm_type { + ANI_AKM_TYPE_NONE, + ANI_AKM_TYPE_RSN, + ANI_AKM_TYPE_RSN_PSK, + ANI_AKM_TYPE_FT_RSN, + ANI_AKM_TYPE_FT_RSN_PSK, + ANI_AKM_TYPE_RSN_PSK_SHA256, + ANI_AKM_TYPE_RSN_8021X_SHA256, +#ifdef WLAN_FEATURE_SAE + ANI_AKM_TYPE_SAE, + ANI_AKM_TYPE_FT_SAE, +#endif + ANI_AKM_TYPE_SUITEB_EAP_SHA256, + ANI_AKM_TYPE_SUITEB_EAP_SHA384, + ANI_AKM_TYPE_FT_SUITEB_EAP_SHA384, + ANI_AKM_TYPE_FILS_SHA256, + ANI_AKM_TYPE_FILS_SHA384, + ANI_AKM_TYPE_FT_FILS_SHA256, + ANI_AKM_TYPE_FT_FILS_SHA384, + ANI_AKM_TYPE_OWE, +#ifdef FEATURE_WLAN_ESE + ANI_AKM_TYPE_CCKM, +#endif + ANI_AKM_TYPE_OSEN, + ANI_AKM_TYPE_DPP_RSN, + ANI_AKM_TYPE_WPA, + ANI_AKM_TYPE_WPA_PSK, + ANI_NUM_OF_SUPPORT_AKM_TYPE, + ANI_AKM_TYPE_UNKNOWN = 0xff, +}; + #endif /* __ANI_SYSTEM_DEFS_H */ diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 7cea62f543b2..a007c98b67f9 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 1 #define QWLAN_VERSION_PATCH 1 -#define QWLAN_VERSION_EXTRA "R" -#define QWLAN_VERSION_BUILD 76 +#define QWLAN_VERSION_EXTRA "U" +#define QWLAN_VERSION_BUILD 77 -#define QWLAN_VERSIONSTR "5.1.1.76R" +#define QWLAN_VERSIONSTR "5.1.1.77U" #endif /* QWLAN_VERSION_H */ diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 3fdc2869f661..9f870a04e937 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -1536,6 +1536,7 @@ typedef struct sSirSmeAssocInd { tDot11fIEHTCaps HTCaps; tDot11fIEVHTCaps VHTCaps; tSirMacCapabilityInfo capability_info; + bool is_sae_authenticated; } tSirSmeAssocInd, *tpSirSmeAssocInd; /* / Definition for Association confirm */ @@ -1549,6 +1550,7 @@ typedef struct sSirSmeAssocCnf { uint16_t aid; struct qdf_mac_addr alternate_bssid; uint8_t alternateChannelId; + tSirMacStatusCodes mac_status_code; } tSirSmeAssocCnf, *tpSirSmeAssocCnf; /* / Enum definition for Wireless medium status change codes */ @@ -3025,12 +3027,24 @@ typedef struct sSirKeepAliveReq { uint8_t sessionId; } tSirKeepAliveReq, *tpSirKeepAliveReq; +/** + * enum rxmgmt_flags - flags for received management frame. + * @RXMGMT_FLAG_NONE: Default value to indicate no flags are set. + * @RXMGMT_FLAG_EXTERNAL_AUTH: frame can be used for external authentication + * by upper layers. + */ +enum rxmgmt_flags { + RXMGMT_FLAG_NONE, + RXMGMT_FLAG_EXTERNAL_AUTH = 1 << 1, +}; + typedef struct sSirSmeMgmtFrameInd { uint16_t frame_len; uint32_t rxChan; uint8_t sessionId; uint8_t frameType; int8_t rxRssi; + enum rxmgmt_flags rx_flags; uint8_t frameBuf[1]; /* variable */ } tSirSmeMgmtFrameInd, *tpSirSmeMgmtFrameInd; @@ -8581,12 +8595,14 @@ struct sir_sae_info { * @length: message length * @session_id: SME session id * @sae_status: SAE status, 0: Success, Non-zero: Failure. + * @peer_mac_addr: peer MAC address */ struct sir_sae_msg { uint16_t message_type; uint16_t length; uint16_t session_id; uint8_t sae_status; + tSirMacAddr peer_mac_addr; }; /** diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h index 5f23432ec24b..8e15026a07b8 100644 --- a/core/mac/inc/sir_mac_prot_def.h +++ b/core/mac/inc/sir_mac_prot_def.h @@ -653,7 +653,8 @@ #define SIR_MAX_BEACON_SIZE 512 #define SIR_MAX_PROBE_RESP_SIZE 512 -/* / Status Code (present in Management response frames) enum */ +/* Status Code (present in Management response frames) enum */ +/* (IEEE Std 802.11-2016, 9.4.1.9, Table 9-46) */ typedef enum eSirMacStatusCodes { eSIR_MAC_SUCCESS_STATUS = 0, /* Reserved */ @@ -698,7 +699,9 @@ typedef enum eSirMacStatusCodes { eSIR_MAC_DSSS_OFDM_NOT_SUPPORTED_STATUS = 26, /* Association denied due to requesting station not supporting the DSSS-OFDM option */ /* reserved 27-29 */ eSIR_MAC_TRY_AGAIN_LATER = 30, /* Association request rejected temporarily, try again later */ - /* reserved 31 */ +#ifdef WLAN_FEATURE_11W + eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION_STATUS = 31, /* Robust management frames policy violation */ +#endif eSIR_MAC_QOS_UNSPECIFIED_FAILURE_STATUS = 32, /* Unspecified, QoS-related failure */ eSIR_MAC_QAP_NO_BANDWIDTH_STATUS = 33, /* Association denied because QoS AP has insufficient bandwidth to handle another */ /* QoS STA */ @@ -731,9 +734,9 @@ typedef enum eSirMacStatusCodes { eSIR_MAC_DEST_STA_NOT_QSTA_STATUS = 50, /* The Destination STA is not a QoS STA */ eSIR_MAC_INVALID_LISTEN_INTERVAL_STATUS = 51, /* Association denied because the ListenInterval is too large */ - eSIR_MAC_DSSS_CCK_RATE_MUST_SUPPORT_STATUS = 52, /* FIXME: */ - eSIR_MAC_DSSS_CCK_RATE_NOT_SUPPORT_STATUS = 53, - eSIR_MAC_PSMP_CONTROLLED_ACCESS_ONLY_STATUS = 54, + eSIR_MAC_INVALID_FT_ACTION_FRAME_COUNT = 52, + eSIR_MAC_INVALID_PMKID = 53, + #ifdef FEATURE_WLAN_ESE eSIR_MAC_ESE_UNSPECIFIED_QOS_FAILURE_STATUS = 200, /* ESE-Unspecified, QoS related failure in (Re)Assoc response frames */ eSIR_MAC_ESE_TSPEC_REQ_REFUSED_STATUS = 201, /* ESE-TSPEC request refused due to AP's policy configuration in AddTs Rsp, (Re)Assoc Rsp. */ diff --git a/core/mac/inc/wni_cfg.h b/core/mac/inc/wni_cfg.h index 6a436fc3c708..e893c3af2cd0 100644 --- a/core/mac/inc/wni_cfg.h +++ b/core/mac/inc/wni_cfg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -255,6 +255,9 @@ enum { WNI_CFG_EDCA_ETSI_ACBE, WNI_CFG_EDCA_ETSI_ACVI, WNI_CFG_EDCA_ETSI_ACVO, +#ifdef WLAN_FEATURE_SAE + WNI_CFG_SAP_SAE_ENABLED, +#endif /* Any new items to be added should be above this strictly */ CFG_PARAM_MAX_NUM }; diff --git a/core/mac/src/cfg/cfg_param_name.c b/core/mac/src/cfg/cfg_param_name.c index d960a6219657..486632ec660c 100644 --- a/core/mac/src/cfg/cfg_param_name.c +++ b/core/mac/src/cfg/cfg_param_name.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -337,4 +337,7 @@ unsigned char *g_cfg_param_name[] = { (unsigned char *)"EDCA_ETSI_ACBE", (unsigned char *)"EDCA_ETSI_ACVI", (unsigned char *)"EDCA_ETSI_ACVO", +#ifdef WLAN_FEATURE_SAE + (unsigned char *)"SAP_SAE_ENABLED", +#endif }; diff --git a/core/mac/src/cfg/cfg_proc_msg.c b/core/mac/src/cfg/cfg_proc_msg.c index acc40f750048..053490659e89 100644 --- a/core/mac/src/cfg/cfg_proc_msg.c +++ b/core/mac/src/cfg/cfg_proc_msg.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -1188,6 +1188,11 @@ cgstatic cfg_static[CFG_PARAM_MAX_NUM] = { {WNI_CFG_EDCA_ETSI_ACVO, CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, 0, 0, 0}, +#ifdef WLAN_FEATURE_SAE + {WNI_CFG_SAP_SAE_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + 0, 1, 1}, +#endif }; diff --git a/core/mac/src/include/parser_api.h b/core/mac/src/include/parser_api.h index 4a65b276bda3..1df8250a20de 100644 --- a/core/mac/src/include/parser_api.h +++ b/core/mac/src/include/parser_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -425,6 +425,7 @@ typedef struct sSirAssocReq { tDot11fIEExtCap ExtCap; tDot11fIEvendor_vht_ie vendor_vht_ie; tDot11fIEhs20vendor_ie hs20vendor_ie; + bool is_sae_authenticated; } tSirAssocReq, *tpSirAssocReq; /* / Association Response structure (one day to be replaced by */ diff --git a/core/mac/src/pe/include/lim_api.h b/core/mac/src/pe/include/lim_api.h index ec7ca33f8b04..013a077d8b28 100644 --- a/core/mac/src/pe/include/lim_api.h +++ b/core/mac/src/pe/include/lim_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -322,5 +322,14 @@ static inline void lim_fill_join_rsp_ht_caps(tpPESession session, #endif QDF_STATUS lim_update_ext_cap_ie(tpAniSirGlobal mac_ctx, uint8_t *ie_data, uint8_t *local_ie_buf, uint16_t *local_ie_len); + +/** + * lim_translate_rsn_oui_to_akm_type() - translate RSN OUI to AKM type + * @auth_suite: auth suite + * + * Return: AKM type + */ +enum ani_akm_type lim_translate_rsn_oui_to_akm_type(uint8_t auth_suite[4]); + /************************************************************/ #endif /* __LIM_API_H */ diff --git a/core/mac/src/pe/include/lim_global.h b/core/mac/src/pe/include/lim_global.h index f455308936d4..d2bb3480de81 100644 --- a/core/mac/src/pe/include/lim_global.h +++ b/core/mac/src/pe/include/lim_global.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -298,6 +298,33 @@ typedef struct sLimMlmOemDataRsp { } tLimMlmOemDataRsp, *tpLimMlmOemDataRsp; #endif +/* Forward declarations */ +struct sSirAssocReq; +struct sDphHashNode; + +/* struct lim_assoc_data - Assoc data to be cached to defer association + * indication to SME + * @present: Indicates whether assoc data is present or not + * @sub_type: Indicates whether it is Association Request(=0) or Reassociation + * Request(=1) frame + * @hdr: MAC header + * @assoc_req: pointer to parsed ASSOC/REASSOC Request frame + * @pmf_connection: flag indicating pmf connection + * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above + * @dup_entry: flag indicating if duplicate entry found + * @sta_ds: station dph entry + */ +struct lim_assoc_data { + bool present; + uint8_t sub_type; + tSirMacMgmtHdr hdr; + struct sSirAssocReq *assoc_req; + bool pmf_connection; + bool assoc_req_copied; + bool dup_entry; + struct sDphHashNode *sta_ds; +}; + /* Pre-authentication structure definition */ typedef struct tLimPreAuthNode { struct tLimPreAuthNode *next; @@ -313,6 +340,10 @@ typedef struct tLimPreAuthNode { TX_TIMER timer; uint16_t seq_num; unsigned long timestamp; + /* keeping copy of association request received, this is + * to defer the association request processing + */ + struct lim_assoc_data assoc_req; } tLimPreAuthNode, *tpLimPreAuthNode; /* Pre-authentication table definition */ diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 58f7190fb4ae..24c0a037b70b 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -2555,3 +2555,58 @@ QDF_STATUS lim_update_ext_cap_ie(tpAniSirGlobal mac_ctx, return QDF_STATUS_SUCCESS; } +#define LIM_RSN_OUI_SIZE 4 + +struct rsn_oui_akm_type_map { + enum ani_akm_type akm_type; + uint8_t rsn_oui[LIM_RSN_OUI_SIZE]; +}; + +static const struct rsn_oui_akm_type_map rsn_oui_akm_type_mapping_table[] = { + {ANI_AKM_TYPE_RSN, {0x00, 0x0F, 0xAC, 0x01} }, + {ANI_AKM_TYPE_RSN_PSK, {0x00, 0x0F, 0xAC, 0x02} }, + {ANI_AKM_TYPE_FT_RSN, {0x00, 0x0F, 0xAC, 0x03} }, + {ANI_AKM_TYPE_FT_RSN_PSK, {0x00, 0x0F, 0xAC, 0x04} }, + {ANI_AKM_TYPE_RSN_8021X_SHA256, {0x00, 0x0F, 0xAC, 0x05} }, + {ANI_AKM_TYPE_RSN_PSK_SHA256, {0x00, 0x0F, 0xAC, 0x06} }, +#ifdef WLAN_FEATURE_SAE + {ANI_AKM_TYPE_SAE, {0x00, 0x0F, 0xAC, 0x08} }, + {ANI_AKM_TYPE_FT_SAE, {0x00, 0x0F, 0xAC, 0x09} }, +#endif + {ANI_AKM_TYPE_SUITEB_EAP_SHA256, {0x00, 0x0F, 0xAC, 0x0B} }, + {ANI_AKM_TYPE_SUITEB_EAP_SHA384, {0x00, 0x0F, 0xAC, 0x0C} }, + {ANI_AKM_TYPE_FT_SUITEB_EAP_SHA384, {0x00, 0x0F, 0xAC, 0x0D} }, + {ANI_AKM_TYPE_FILS_SHA256, {0x00, 0x0F, 0xAC, 0x0E} }, + {ANI_AKM_TYPE_FILS_SHA384, {0x00, 0x0F, 0xAC, 0x0F} }, + {ANI_AKM_TYPE_FT_FILS_SHA256, {0x00, 0x0F, 0xAC, 0x10} }, + {ANI_AKM_TYPE_FT_FILS_SHA384, {0x00, 0x0F, 0xAC, 0x11} }, + {ANI_AKM_TYPE_OWE, {0x00, 0x0F, 0xAC, 0x12} }, +#ifdef FEATURE_WLAN_ESE + {ANI_AKM_TYPE_CCKM, {0x00, 0x40, 0x96, 0x00} }, +#endif + {ANI_AKM_TYPE_OSEN, {0x50, 0x6F, 0x9A, 0x01} }, + {ANI_AKM_TYPE_DPP_RSN, {0x50, 0x6F, 0x9A, 0x02} }, + {ANI_AKM_TYPE_WPA, {0x00, 0x50, 0xF2, 0x01} }, + {ANI_AKM_TYPE_WPA_PSK, {0x00, 0x50, 0xF2, 0x02} }, + /* Add akm type above here */ + {ANI_AKM_TYPE_UNKNOWN, {0} }, +}; + +enum ani_akm_type lim_translate_rsn_oui_to_akm_type(uint8_t auth_suite[4]) +{ + const struct rsn_oui_akm_type_map *map; + enum ani_akm_type akm_type; + + map = rsn_oui_akm_type_mapping_table; + while (true) { + akm_type = map->akm_type; + if ((akm_type == ANI_AKM_TYPE_UNKNOWN) || + (qdf_mem_cmp(auth_suite, map->rsn_oui, 4) == 0)) + break; + map++; + } + + pe_debug("akm_type: %d", akm_type); + + return akm_type; +} diff --git a/core/mac/src/pe/lim/lim_p2p.c b/core/mac/src/pe/lim/lim_p2p.c index 121f18145831..32b6745c1d21 100644 --- a/core/mac/src/pe/lim/lim_p2p.c +++ b/core/mac/src/pe/lim/lim_p2p.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -374,7 +374,8 @@ void lim_remain_on_chn_rsp(tpAniSirGlobal pMac, QDF_STATUS status, uint32_t *dat void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType, uint8_t *frame, uint32_t frameLen, uint16_t sessionId, uint32_t rxChannel, - tpPESession psessionEntry, int8_t rxRssi) + tpPESession session_entry, + int8_t rx_rssi, enum rxmgmt_flags rx_flags) { tpSirSmeMgmtFrameInd pSirSmeMgmtFrame = NULL; uint16_t length; @@ -397,8 +398,9 @@ void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType, pSirSmeMgmtFrame->frame_len = frameLen; pSirSmeMgmtFrame->sessionId = sessionId; pSirSmeMgmtFrame->frameType = frameType; - pSirSmeMgmtFrame->rxRssi = rxRssi; + pSirSmeMgmtFrame->rxRssi = rx_rssi; pSirSmeMgmtFrame->rxChan = rxChannel; + pSirSmeMgmtFrame->rx_flags = rx_flags; qdf_mem_zero(pSirSmeMgmtFrame->frameBuf, frameLen); qdf_mem_copy(pSirSmeMgmtFrame->frameBuf, frame, frameLen); diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index 402f42b04e46..5063c5fbc390 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -1096,10 +1096,11 @@ static void __lim_process_qos_map_configure_frame(tpAniSirGlobal mac_ctx, return; } lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType, - (uint8_t *) mac_hdr, - frame_len + sizeof(tSirMacMgmtHdr), 0, - WMA_GET_RX_CH(rx_pkt_info), session, - WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info)); + (uint8_t *)mac_hdr, + frame_len + sizeof(tSirMacMgmtHdr), 0, + WMA_GET_RX_CH(rx_pkt_info), session, + WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info), + RXMGMT_FLAG_NONE); } #ifdef ANI_SUPPORT_11H @@ -1318,9 +1319,10 @@ __lim_process_radio_measure_request(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, /* Save seq no of currently processing rrm report req frame */ pMac->rrm.rrmPEContext.prev_rrm_report_seq_num = curr_seq_num; lim_send_sme_mgmt_frame_ind(pMac, pHdr->fc.subType, (uint8_t *)pHdr, - frameLen + sizeof(tSirMacMgmtHdr), 0, - WMA_GET_RX_CH(pRxPacketInfo), psessionEntry, - WMA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo)); + frameLen + sizeof(tSirMacMgmtHdr), 0, + WMA_GET_RX_CH(pRxPacketInfo), psessionEntry, + WMA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo), + RXMGMT_FLAG_NONE); frm = qdf_mem_malloc(sizeof(*frm)); if (frm == NULL) { @@ -1555,7 +1557,7 @@ static void __lim_process_sa_query_response_action_frame(tpAniSirGlobal pMac, WMA_GET_RX_CH(pRxPacketInfo), psessionEntry, WMA_GET_RX_RSSI_NORMALIZED( - pRxPacketInfo)); + pRxPacketInfo), RXMGMT_FLAG_NONE); return; } @@ -1686,7 +1688,7 @@ static void lim_process_action_vendor_specific(tpAniSirGlobal mac_ctx, sizeof(tSirMacMgmtHdr), session_id, WMA_GET_RX_CH(pkt_info), session, WMA_GET_RX_RSSI_NORMALIZED( - pkt_info)); + pkt_info), RXMGMT_FLAG_NONE); } else { pe_debug("Unhandled public action frame (Vendor specific) OUI: %x %x %x %x", action_hdr->Oui[0], @@ -1870,7 +1872,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, frame_len + sizeof(tSirMacMgmtHdr), session->smeSessionId, WMA_GET_RX_CH(rx_pkt_info), - session, rssi); + session, rssi, RXMGMT_FLAG_NONE); break; default: pe_debug("Action ID: %d not handled in WNM category", @@ -1960,7 +1962,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, WMA_GET_RX_CH(rx_pkt_info), session, WMA_GET_RX_RSSI_NORMALIZED( - rx_pkt_info)); + rx_pkt_info), RXMGMT_FLAG_NONE); } else { pe_debug("Dropping the vendor specific action frame beacause of (WES Mode not enabled (WESMODE: %d) or OUI mismatch (%02x %02x %02x) or not received with SelfSta address) system role: %d", IS_WES_MODE_ENABLED(mac_ctx), @@ -2006,7 +2008,8 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, frame_len + sizeof(tSirMacMgmtHdr), session->smeSessionId, WMA_GET_RX_CH(rx_pkt_info), session, - WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info)); + WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info), + RXMGMT_FLAG_NONE); break; default: @@ -2072,7 +2075,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, WMA_GET_RX_CH(rx_pkt_info), session, WMA_GET_RX_RSSI_NORMALIZED( - rx_pkt_info)); + rx_pkt_info), RXMGMT_FLAG_NONE); break; } case SIR_MAC_ACTION_PROT_DUAL_PUB: @@ -2089,7 +2092,8 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, mac_hdr->fc.subType, (uint8_t *) mac_hdr, frame_len + sizeof(tSirMacMgmtHdr), session->smeSessionId, - WMA_GET_RX_CH(rx_pkt_info), session, rssi); + WMA_GET_RX_CH(rx_pkt_info), session, rssi, + RXMGMT_FLAG_NONE); break; default: pe_warn("Unhandled - Protected Dual Public Action"); @@ -2104,30 +2108,23 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, } /** - * lim_process_action_frame_no_session + * lim_process_action_frame_no_session() - action frame handler + * @mac - Pointer to Global MAC structure + * @bd - A pointer to Buffer descriptor + associated PDUs * - ***FUNCTION: * This function is called by limProcessMessageQueue() upon * Action frame reception and no session. * Currently only public action frames can be received from * a non-associated station. * - ***LOGIC: - * - ***ASSUMPTIONS: - * - ***NOTE: - * - * @param pMac - Pointer to Global MAC structure - * @param *pBd - A pointer to Buffer descriptor + associated PDUs * @return None */ -void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd) +void lim_process_action_frame_no_session(tpAniSirGlobal mac, uint8_t *bd) { - tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(pBd); - uint32_t frame_len = WMA_GET_RX_PAYLOAD_LEN(pBd); - uint8_t *pBody = WMA_GET_RX_MPDU_DATA(pBd); + tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(bd); + uint32_t frame_len = WMA_GET_RX_PAYLOAD_LEN(bd); + uint8_t *pBody = WMA_GET_RX_MPDU_DATA(bd); tpSirMacActionFrameHdr action_hdr = (tpSirMacActionFrameHdr) pBody; tpSirMacVendorSpecificPublicActionFrameHdr vendor_specific; @@ -2146,7 +2143,7 @@ void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd) vendor_specific = (tpSirMacVendorSpecificPublicActionFrameHdr) action_hdr; - lim_process_action_vendor_specific(pMac, pBd, + lim_process_action_vendor_specific(mac, bd, vendor_specific, NULL); break; @@ -2160,12 +2157,12 @@ void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd) */ pe_debug("Public Action Frame %d received", action_hdr->actionID); - lim_send_sme_mgmt_frame_ind(pMac, - mac_hdr->fc.subType, - (uint8_t *) mac_hdr, + lim_send_sme_mgmt_frame_ind( + mac, mac_hdr->fc.subType, (uint8_t *)mac_hdr, frame_len + sizeof(tSirMacMgmtHdr), 0, - WMA_GET_RX_CH(pBd), NULL, - WMA_GET_RX_RSSI_NORMALIZED(pBd)); + WMA_GET_RX_CH(bd), NULL, + WMA_GET_RX_RSSI_NORMALIZED(bd), + RXMGMT_FLAG_NONE); break; default: diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c index 75952720f3b9..5cded988402d 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -717,6 +717,47 @@ static void lim_print_ht_cap(tpAniSirGlobal mac_ctx, tpPESession session, } } +typedef enum wlan_crypto_rsn_cap { + WLAN_CRYPTO_RSN_CAP_PREAUTH = 0x01, + WLAN_CRYPTO_RSN_CAP_MFP_ENABLED = 0x80, + WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED = 0x40, +} wlan_crypto_rsn_cap; + +/** + * lim_check_sae_pmf_cap() - check pmf capability for SAE STA + * @session: pointer to pe session entry + * @rsn: pointer to RSN + * @akm_type: AKM type + * + * This function checks if SAE STA is pmf capable when SAE SAP is pmf + * capable. Reject with eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION + * if SAE STA is pmf disable. + * + * Return: tSirMacStatusCodes + */ +#ifdef WLAN_FEATURE_SAE +static tSirMacStatusCodes lim_check_sae_pmf_cap(tpPESession session, + tDot11fIERSN *rsn, + enum ani_akm_type akm_type) +{ + tSirMacStatusCodes status = eSIR_MAC_SUCCESS_STATUS; + + if (session->pLimStartBssReq->pmfCapable && + (rsn->RSN_Cap[0] & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) == 0 && + akm_type == ANI_AKM_TYPE_SAE) + status = eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION_STATUS; + + return status; +} +#else +static tSirMacStatusCodes lim_check_sae_pmf_cap(tpPESession session, + tDot11fIERSN *rsn, + enum ani_akm_type akm_type) +{ + return eSIR_MAC_SUCCESS_STATUS; +} +#endif + /** * lim_check_wpa_rsn_ie() - wpa and rsn ie related checks * @session: pointer to pe session entry @@ -739,6 +780,8 @@ static bool lim_check_wpa_rsn_ie(tpPESession session, tpAniSirGlobal mac_ctx, tDot11fIEWPA dot11f_ie_wpa = {0}; tDot11fIERSN dot11f_ie_rsn = {0}; tSirRetStatus status = eSIR_SUCCESS; + enum ani_akm_type akm_type; + tSirMacStatusCodes mac_status; /* * Clear the buffers so that frame parser knows that there isn't a @@ -826,6 +869,20 @@ static bool lim_check_wpa_rsn_ie(tpPESession session, tpAniSirGlobal mac_ctx, session); return false; } + akm_type = lim_translate_rsn_oui_to_akm_type( + dot11f_ie_rsn.akm_suite[0]); + + mac_status = lim_check_sae_pmf_cap(session, &dot11f_ie_rsn, + akm_type); + if (eSIR_MAC_SUCCESS_STATUS != mac_status) { + /* Reject pmf disable SAE STA */ + pe_warn("Re/Assoc rejected from: " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(hdr->sa)); + lim_send_assoc_rsp_mgmt_frame(mac_ctx, mac_status, + 1, hdr->sa, sub_type, + 0, session); + return false; + } } else if (assoc_req->wpaPresent) { if (!assoc_req->wpa.length) { pe_warn("Re/Assoc rejected from: " @@ -987,6 +1044,8 @@ static bool lim_process_assoc_req_no_sta_ctx(tpAniSirGlobal mac_ctx, } /* Delete 'pre-auth' context of STA */ *auth_type = sta_pre_auth_ctx->authType; + if (sta_pre_auth_ctx->authType == eSIR_AUTH_TYPE_SAE) + assoc_req->is_sae_authenticated = true; lim_delete_pre_auth_node(mac_ctx, hdr->sa); /* All is well. Assign AID (after else part) */ return true; @@ -1676,25 +1735,11 @@ static bool lim_update_sta_ctx(tpAniSirGlobal mac_ctx, tpPESession session, return true; } -/** - * lim_process_assoc_cleanup() - frees up resources used in function - * lim_process_assoc_req_frame() - * @mac_ctx: pointer to Global MAC structure - * @session: pointer to pe session entry - * @assoc_req: pointer to ASSOC/REASSOC Request frame - * @sta_ds: station dph entry - * @tmp_assoc_req: pointer to tmp ASSOC/REASSOC Request frame - * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above - * - * Frees up resources used in function lim_process_assoc_req_frame - * - * Return: void - */ -static void lim_process_assoc_cleanup(tpAniSirGlobal mac_ctx, - tpPESession session, - tpSirAssocReq assoc_req, - tpDphHashNode sta_ds, - bool *assoc_req_copied) +void lim_process_assoc_cleanup(tpAniSirGlobal mac_ctx, + tpPESession session, + tpSirAssocReq assoc_req, + tpDphHashNode sta_ds, + bool assoc_req_copied) { tpSirAssocReq tmp_assoc_req; @@ -1707,7 +1752,7 @@ static void lim_process_assoc_cleanup(tpAniSirGlobal mac_ctx, qdf_mem_free(assoc_req); /* to avoid double free */ - if (*assoc_req_copied && session->parsedAssocReq) + if (assoc_req_copied && session->parsedAssocReq) session->parsedAssocReq[sta_ds->assocId] = NULL; } @@ -1732,6 +1777,170 @@ static void lim_process_assoc_cleanup(tpAniSirGlobal mac_ctx, } /** + * lim_defer_sme_indication() - Defer assoc indication to SME + * @mac_ctx: Pointer to Global MAC structure + * @session: pe session entry + * @sub_type: Indicates whether it is Association Request(=0) or Reassociation + * Request(=1) frame + * @hdr: A pointer to the MAC header + * @assoc_req: pointer to ASSOC/REASSOC Request frame + * @pmf_connection: flag indicating pmf connection + * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above + * @dup_entry: flag indicating if duplicate entry found + * + * Defer Initialization of PE data structures and wait for an external event. + * lim_send_assoc_ind_to_sme() will be called to initialize PE data structures + * when the expected event is received. + * + * Return: void + */ +static void lim_defer_sme_indication(tpAniSirGlobal mac_ctx, + tpPESession session, + uint8_t sub_type, + tpSirMacMgmtHdr hdr, + tpSirAssocReq assoc_req, + bool pmf_connection, + bool assoc_req_copied, + bool dup_entry, + struct sDphHashNode *sta_ds) +{ + struct tLimPreAuthNode *sta_pre_auth_ctx; + /* Extract pre-auth context for the STA, if any. */ + sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, hdr->sa); + sta_pre_auth_ctx->assoc_req.present = true; + sta_pre_auth_ctx->assoc_req.sub_type = sub_type; + qdf_mem_copy(&sta_pre_auth_ctx->assoc_req.hdr, hdr, + sizeof(tSirMacMgmtHdr)); + sta_pre_auth_ctx->assoc_req.assoc_req = assoc_req; + sta_pre_auth_ctx->assoc_req.pmf_connection = pmf_connection; + sta_pre_auth_ctx->assoc_req.assoc_req_copied = assoc_req_copied; + sta_pre_auth_ctx->assoc_req.dup_entry = dup_entry; + sta_pre_auth_ctx->assoc_req.sta_ds = sta_ds; +} + +bool lim_send_assoc_ind_to_sme(tpAniSirGlobal mac_ctx, + tpPESession session, + uint8_t sub_type, + tpSirMacMgmtHdr hdr, + tpSirAssocReq assoc_req, + bool pmf_connection, + bool *assoc_req_copied, + bool dup_entry, bool force_1x1) +{ + uint16_t peer_idx; + struct tLimPreAuthNode *sta_pre_auth_ctx; + tpDphHashNode sta_ds = NULL; + tHalBitVal qos_mode; + tAniAuthType auth_type; + uint8_t update_ctx = false; + + limGetQosMode(session, &qos_mode); + /* Extract 'associated' context for STA, if any. */ + sta_ds = dph_lookup_hash_entry(mac_ctx, hdr->sa, &peer_idx, + &session->dph.dphHashTable); + + /* Extract pre-auth context for the STA, if any. */ + sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, hdr->sa); + + if (!sta_ds) { + if (!lim_process_assoc_req_no_sta_ctx(mac_ctx, hdr, session, + assoc_req, sub_type, + sta_pre_auth_ctx, sta_ds, + &auth_type)) + return false; + } else { + if (!lim_process_assoc_req_sta_ctx(mac_ctx, hdr, session, + assoc_req, sub_type, + sta_pre_auth_ctx, sta_ds, + peer_idx, &auth_type, + &update_ctx)) + return false; + goto send_ind_to_sme; + } + + /* check if sta is allowed per QoS AC rules */ + if (!lim_chk_wmm(mac_ctx, hdr, session, assoc_req, sub_type, qos_mode)) + return false; + + /* STA is Associated ! */ + pe_debug("Received: %s Req successful from " MAC_ADDRESS_STR, + (sub_type == LIM_ASSOC) ? "Assoc" : "ReAssoc", + MAC_ADDR_ARRAY(hdr->sa)); + + /* + * AID for this association will be same as the peer Index used in DPH + * table. Assign unused/least recently used peer Index from perStaDs. + * NOTE: lim_assign_peer_idx() assigns AID values ranging between + * 1 - cfg_item(WNI_CFG_ASSOC_STA_LIMIT) + */ + + peer_idx = lim_assign_peer_idx(mac_ctx, session); + + if (!peer_idx) { + /* Could not assign AID. Reject association */ + pe_err("PeerIdx not avaialble. Reject associaton"); + lim_reject_association(mac_ctx, hdr->sa, sub_type, + true, auth_type, peer_idx, false, + eSIR_MAC_UNSPEC_FAILURE_STATUS, + session); + return false; + } + + /* Add an entry to hash table maintained by DPH module */ + + sta_ds = dph_add_hash_entry(mac_ctx, hdr->sa, peer_idx, + &session->dph.dphHashTable); + + if (!sta_ds) { + /* Could not add hash table entry at DPH */ + pe_err("couldn't add hash entry at DPH for aid: %d MacAddr:" + MAC_ADDRESS_STR, peer_idx, MAC_ADDR_ARRAY(hdr->sa)); + + /* Release AID */ + lim_release_peer_idx(mac_ctx, peer_idx, session); + + lim_reject_association(mac_ctx, hdr->sa, sub_type, + true, auth_type, peer_idx, false, + eSIR_MAC_UNSPEC_FAILURE_STATUS, + session); + return false; + } + +send_ind_to_sme: + if (!lim_update_sta_ds(mac_ctx, hdr, session, assoc_req, + sub_type, sta_ds, auth_type, + assoc_req_copied, peer_idx, qos_mode, + pmf_connection, force_1x1)) + return false; + + /* BTAMP: Storing the parsed assoc request in the session array */ + if (session->parsedAssocReq) + session->parsedAssocReq[sta_ds->assocId] = assoc_req; + *assoc_req_copied = true; + + /* If it is duplicate entry wait till the peer is deleted */ + if (!dup_entry) { + if (!lim_update_sta_ctx(mac_ctx, session, assoc_req, + sub_type, sta_ds, update_ctx)) + return false; + } + + /* AddSta is success here */ + if (LIM_IS_AP_ROLE(session) && IS_DOT11_MODE_HT(session->dot11mode) && + assoc_req->HTCaps.present && assoc_req->wmeInfoPresent) { + /* + * Update in the HAL Sta Table for the Update of the Protection + * Mode + */ + lim_post_sm_state_update(mac_ctx, sta_ds->staIndex, + sta_ds->htMIMOPSState, sta_ds->staAddr, + session->smeSessionId); + } + + return true; +} + +/** * lim_process_assoc_req_frame() - Process RE/ASSOC Request frame. * @mac_ctx: Pointer to Global MAC structure * @rx_pkt_info: A pointer to Buffer descriptor + associated PDUs @@ -1747,14 +1956,13 @@ void lim_process_assoc_req_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, uint8_t sub_type, tpPESession session) { bool pmf_connection = false, assoc_req_copied = false; - uint8_t update_ctx, *frm_body; - uint16_t peer_idx, assoc_id = 0; + uint8_t *frm_body; + uint16_t assoc_id = 0; uint32_t frame_len; uint32_t phy_mode; tHalBitVal qos_mode; tpSirMacMgmtHdr hdr; struct tLimPreAuthNode *sta_pre_auth_ctx; - tAniAuthType auth_type; tSirMacCapabilityInfo local_cap; tpDphHashNode sta_ds = NULL; tpSirAssocReq assoc_req; @@ -1917,8 +2125,6 @@ void lim_process_assoc_req_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, sub_type, &local_cap)) goto error; - update_ctx = false; - if (false == lim_chk_ssid(mac_ctx, hdr, session, assoc_req, sub_type)) goto error; @@ -1958,36 +2164,6 @@ void lim_process_assoc_req_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, assoc_req, sub_type, &pmf_connection)) goto error; - /* Extract 'associated' context for STA, if any. */ - sta_ds = dph_lookup_hash_entry(mac_ctx, hdr->sa, &peer_idx, - &session->dph.dphHashTable); - - /* Extract pre-auth context for the STA, if any. */ - sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, hdr->sa); - - if (sta_ds == NULL) { - if (false == lim_process_assoc_req_no_sta_ctx(mac_ctx, hdr, - session, assoc_req, sub_type, sta_pre_auth_ctx, - sta_ds, &auth_type)) - goto error; - } else { - if (false == lim_process_assoc_req_sta_ctx(mac_ctx, hdr, - session, assoc_req, sub_type, sta_pre_auth_ctx, - sta_ds, peer_idx, &auth_type, &update_ctx)) - goto error; - goto sendIndToSme; - } - - /* check if sta is allowed per QoS AC rules */ - if (false == lim_chk_wmm(mac_ctx, hdr, session, - assoc_req, sub_type, qos_mode)) - goto error; - - /* STA is Associated ! */ - pe_err("Received: %s Req successful from " MAC_ADDRESS_STR, - (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc", - MAC_ADDR_ARRAY(hdr->sa)); - if (session->pePersona == QDF_P2P_GO_MODE) { /* * WAR: In P2P GO mode, if the P2P client device @@ -2007,82 +2183,38 @@ void lim_process_assoc_req_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, frame_len - LIM_ASSOC_REQ_IE_OFFSET); } - /* - * AID for this association will be same as the peer Index used in DPH - * table. Assign unused/least recently used peer Index from perStaDs. - * NOTE: lim_assign_peer_idx() assigns AID values ranging between - * 1 - cfg_item(WNI_CFG_ASSOC_STA_LIMIT) - */ - - peer_idx = lim_assign_peer_idx(mac_ctx, session); - - if (!peer_idx) { - /* Could not assign AID. Reject association */ - pe_err("PeerIdx not avaialble. Reject associaton"); - lim_reject_association(mac_ctx, hdr->sa, sub_type, - true, auth_type, peer_idx, false, - eSIR_MAC_UNSPEC_FAILURE_STATUS, - session); - goto error; - } - - /* Add an entry to hash table maintained by DPH module */ - - sta_ds = dph_add_hash_entry(mac_ctx, hdr->sa, peer_idx, - &session->dph.dphHashTable); - - if (sta_ds == NULL) { - /* Could not add hash table entry at DPH */ - pe_err("couldn't add hash entry at DPH for aid: %d MacAddr:" - MAC_ADDRESS_STR, peer_idx, MAC_ADDR_ARRAY(hdr->sa)); - - /* Release AID */ - lim_release_peer_idx(mac_ctx, peer_idx, session); + /* Extract pre-auth context for the STA, if any. */ + sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, hdr->sa); - lim_reject_association(mac_ctx, hdr->sa, sub_type, - true, auth_type, peer_idx, false, - eSIR_MAC_UNSPEC_FAILURE_STATUS, - session); - goto error; + /* SAE authentication is offloaded to hostapd. Hostapd sends + * authentication status to driver after completing SAE + * authentication (after sending out 4/4 SAE auth frame). + * There is a possible race condition where driver gets + * assoc request from SAE station before getting authentication + * status from hostapd. Don't reject the association in such + * cases and defer the processing of assoc request frame by caching + * the frame and process it when the auth status is received. + */ + if (sta_pre_auth_ctx && + sta_pre_auth_ctx->authType == eSIR_AUTH_TYPE_SAE && + sta_pre_auth_ctx->mlmState == eLIM_MLM_WT_SAE_AUTH_STATE) { + pe_debug("Received assoc request frame while SAE authentication is in progress; Defer association request handling till SAE auth status is received"); + lim_defer_sme_indication(mac_ctx, session, sub_type, hdr, + assoc_req, pmf_connection, + assoc_req_copied, dup_entry, sta_ds); + return; } -sendIndToSme: - if (false == lim_update_sta_ds(mac_ctx, hdr, session, assoc_req, - sub_type, sta_ds, auth_type, - &assoc_req_copied, peer_idx, qos_mode, - pmf_connection, force_1x1)) + /* Send assoc indication to SME */ + if (!lim_send_assoc_ind_to_sme(mac_ctx, session, sub_type, hdr, + assoc_req, pmf_connection, + &assoc_req_copied, dup_entry, force_1x1)) goto error; - - /* BTAMP: Storing the parsed assoc request in the session array */ - if (session->parsedAssocReq) - session->parsedAssocReq[sta_ds->assocId] = assoc_req; - assoc_req_copied = true; - - /* If it is duplicate entry wait till the peer is deleted */ - if (dup_entry != true) { - if (false == lim_update_sta_ctx(mac_ctx, session, assoc_req, - sub_type, sta_ds, update_ctx)) - goto error; - } - - /* AddSta is sucess here */ - if (LIM_IS_AP_ROLE(session) && IS_DOT11_MODE_HT(session->dot11mode) && - assoc_req->HTCaps.present && assoc_req->wmeInfoPresent) { - /* - * Update in the HAL Sta Table for the Update of the Protection - * Mode - */ - lim_post_sm_state_update(mac_ctx, sta_ds->staIndex, - sta_ds->htMIMOPSState, sta_ds->staAddr, - session->smeSessionId); - } - return; - error: lim_process_assoc_cleanup(mac_ctx, session, assoc_req, sta_ds, - &assoc_req_copied); + assoc_req_copied); return; } @@ -2510,6 +2642,8 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, sizeof(tDot11fIEVHTCaps)); lim_fill_assoc_ind_vht_info(mac_ctx, session_entry, assoc_req, assoc_ind, sta_ds); + assoc_ind->is_sae_authenticated = + assoc_req->is_sae_authenticated; lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_IND, (uint32_t *) assoc_ind); qdf_mem_free(assoc_ind); diff --git a/core/mac/src/pe/lim/lim_process_auth_frame.c b/core/mac/src/pe/lim/lim_process_auth_frame.c index 8948bda446af..f1048e714c47 100644 --- a/core/mac/src/pe/lim/lim_process_auth_frame.c +++ b/core/mac/src/pe/lim/lim_process_auth_frame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -44,6 +44,31 @@ #include "lim_process_fils.h" #include "lim_send_messages.h" +#ifdef WLAN_FEATURE_SAE +/** + * sap_sae_enabled() - API to check if SAP SAE availability. + * @mac_ctx: pointer to MAC context + * + * This API reads the SAE setting from MAC/WNI layer. + * + * Return: true if SAE is enabled, false otherwise. + */ +static inline bool sap_sae_enabled(tpAniSirGlobal mac_ctx) +{ + uint32_t sap_sae_enabled; + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_SAP_SAE_ENABLED, + &sap_sae_enabled) != eSIR_SUCCESS) { + sap_sae_enabled = 0; + } + return (sap_sae_enabled != 0); +} +#else +static inline bool sap_sae_enabled(tpAniSirGlobal mac_ctx) +{ + return false; +} +#endif + /** * is_auth_valid * @@ -278,7 +303,44 @@ static void lim_process_auth_open_system_algo(tpAniSirGlobal mac_ctx, #ifdef WLAN_FEATURE_SAE /** - * lim_process_sae_auth_frame()-Process SAE authentication frame + * lim_external_auth_add_pre_auth_node() - Add preauth node for the peer + * performing external authentication + * @mac_ctx: MAC context + * @mac_hdr: Mac header of the packet + * @mlm_state: MLM state to be marked to track SAE authentication + * + * Return: None + */ +static void lim_external_auth_add_pre_auth_node(tpAniSirGlobal mac_ctx, + tpSirMacMgmtHdr mac_hdr, + tLimMlmStates mlm_state) +{ + struct tLimPreAuthNode *auth_node; + tpLimPreAuthTable preauth_table = &mac_ctx->lim.gLimPreAuthTimerTable; + + pe_debug("=======> eSIR_AUTH_TYPE_SAE"); + /* Create entry for this STA in pre-auth list */ + auth_node = lim_acquire_free_pre_auth_node(mac_ctx, preauth_table); + if (!auth_node) { + pe_debug("Max pre-auth nodes reached " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(mac_hdr->sa)); + return; + } + pe_debug("Creating preauth node for SAE peer " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(mac_hdr->sa)); + qdf_mem_copy((uint8_t *)auth_node->peerMacAddr, + mac_hdr->sa, sizeof(tSirMacAddr)); + auth_node->mlmState = mlm_state; + auth_node->authType = eSIR_AUTH_TYPE_SAE; + auth_node->timestamp = qdf_mc_timer_get_system_ticks(); + auth_node->seq_num = ((mac_hdr->seqControl.seqNumHi << 4) | + (mac_hdr->seqControl.seqNumLo)); + auth_node->assoc_req.present = false; + lim_add_pre_auth_node(mac_ctx, auth_node); +} + +/** + * lim_process_sae_auth_frame() - Process SAE authentication frame * @mac_ctx: MAC context * @rx_pkt_info: Rx packet * @pe_session: PE session @@ -286,11 +348,13 @@ static void lim_process_auth_open_system_algo(tpAniSirGlobal mac_ctx, * Return: None */ static void lim_process_sae_auth_frame(tpAniSirGlobal mac_ctx, - uint8_t *rx_pkt_info, tpPESession pe_session) + uint8_t *rx_pkt_info, + tpPESession pe_session) { tpSirMacMgmtHdr mac_hdr; uint32_t frame_len; uint8_t *body_ptr; + enum rxmgmt_flags rx_flags = RXMGMT_FLAG_NONE; mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info); @@ -299,19 +363,44 @@ static void lim_process_sae_auth_frame(tpAniSirGlobal mac_ctx, pe_debug("Received SAE Auth frame type %d subtype %d", mac_hdr->fc.type, mac_hdr->fc.subType); - if (pe_session->limMlmState != eLIM_MLM_WT_SAE_AUTH_STATE) - pe_err("received SAE auth response in unexpected state %x", - pe_session->limMlmState); + if (LIM_IS_STA_ROLE(pe_session) && + pe_session->limMlmState != eLIM_MLM_WT_SAE_AUTH_STATE) + pe_err("received SAE auth response for STA in unexpected state %x", + pe_session->limMlmState); + + if (LIM_IS_AP_ROLE(pe_session)) { + struct tLimPreAuthNode *sta_pre_auth_ctx; + + rx_flags = RXMGMT_FLAG_EXTERNAL_AUTH; + /* Add preauth node when the first SAE authentication frame + * is received and mark state as authenticating. + * It's not good to track SAE authentication frames with + * authTransactionSeqNumber as it's subjected to + * SAE protocol optimizations. + */ + /* Extract pre-auth context for the STA, if any. */ + sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, + mac_hdr->sa); + if (!sta_pre_auth_ctx || + (sta_pre_auth_ctx->mlmState != eLIM_MLM_WT_SAE_AUTH_STATE && + sta_pre_auth_ctx->mlmState != + eLIM_MLM_AUTHENTICATED_STATE)) { + lim_external_auth_add_pre_auth_node( + mac_ctx, mac_hdr, eLIM_MLM_WT_SAE_AUTH_STATE); + } + } lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType, - (uint8_t *) mac_hdr, - frame_len + sizeof(tSirMacMgmtHdr), 0, - WMA_GET_RX_CH(rx_pkt_info), pe_session, - WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info)); + (uint8_t *)mac_hdr, + frame_len + sizeof(tSirMacMgmtHdr), 0, + WMA_GET_RX_CH(rx_pkt_info), pe_session, + WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info), + rx_flags); } #else -static inline void lim_process_sae_auth_frame(tpAniSirGlobal mac_ctx, - uint8_t *rx_pkt_info, tpPESession pe_session) +static inline void lim_process_sae_auth_frame(tpAniSirGlobal mac_ctx, + uint8_t *rx_pkt_info, + tpPESession pe_session) {} #endif @@ -1417,10 +1506,11 @@ lim_process_auth_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, pe_err("failed to convert Auth Frame to structure or Auth is not valid"); goto free; } - } else if ((auth_alg == - eSIR_AUTH_TYPE_SAE) && (LIM_IS_STA_ROLE(pe_session))) { - lim_process_sae_auth_frame(mac_ctx, - rx_pkt_info, pe_session); + } else if (auth_alg == eSIR_AUTH_TYPE_SAE) { + if (sap_sae_enabled(mac_ctx) && + (LIM_IS_STA_ROLE(pe_session) || LIM_IS_AP_ROLE(pe_session))) + lim_process_sae_auth_frame(mac_ctx, rx_pkt_info, + pe_session); goto free; } else if ((sir_convert_auth_frame2_struct(mac_ctx, body_ptr, frame_len, rx_auth_frame) != eSIR_SUCCESS) diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index c6c3e8b3bd88..7d0df1cd9a88 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -64,6 +64,116 @@ static void lim_process_normal_hdd_msg(tpAniSirGlobal mac_ctx, #ifdef WLAN_FEATURE_SAE /** + * lim_process_sae_msg_sta() - Process SAE message for STA + * @mac: Global MAC pointer + * @session: Pointer to the PE session entry + * @sae_msg: SAE message buffer pointer + * + * Return: None + */ +static void lim_process_sae_msg_sta(tpAniSirGlobal mac, + tpPESession session, + struct sir_sae_msg *sae_msg) +{ + switch (session->limMlmState) { + case eLIM_MLM_WT_SAE_AUTH_STATE: + /* SAE authentication is completed. + * Restore from auth state + */ + if (tx_timer_running(&mac->lim.limTimers.sae_auth_timer)) + lim_deactivate_and_change_timer(mac, + eLIM_AUTH_SAE_TIMER); + /* success */ + if (sae_msg->sae_status == IEEE80211_STATUS_SUCCESS) + lim_restore_from_auth_state(mac, + eSIR_SME_SUCCESS, + eSIR_MAC_SUCCESS_STATUS, + session); + else + lim_restore_from_auth_state( + mac, eSIR_SME_AUTH_REFUSED, + eSIR_MAC_UNSPEC_FAILURE_STATUS, session); + break; + default: + /* SAE msg is received in unexpected state */ + pe_err("received SAE msg instate %X", session->limMlmState); + lim_print_mlm_state(mac, LOGE, session->limMlmState); + break; + } +} + +/** + * lim_process_sae_msg_ap() - Process SAE message + * @mac: Global MAC pointer + * @session: Pointer to the PE session entry + * @sae_msg: SAE message buffer pointer + * + * Return: None + */ +static void lim_process_sae_msg_ap(tpAniSirGlobal mac, + tpPESession session, + struct sir_sae_msg *sae_msg) +{ + struct tLimPreAuthNode *sta_pre_auth_ctx; + struct lim_assoc_data *assoc_req; + /* Extract pre-auth context for the STA and move limMlmState + * of preauth node to eLIM_MLM_AUTHENTICATED_STATE + */ + sta_pre_auth_ctx = lim_search_pre_auth_list(mac, + sae_msg->peer_mac_addr); + + if (!sta_pre_auth_ctx) { + pe_debug("No preauth node created for " + MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(sae_msg->peer_mac_addr)); + return; + } + + assoc_req = &sta_pre_auth_ctx->assoc_req; + + if (sae_msg->sae_status != IEEE80211_STATUS_SUCCESS) { + pe_debug("SAE authentication failed for " + MAC_ADDRESS_STR " status: %u", + MAC_ADDR_ARRAY(sae_msg->peer_mac_addr), + sae_msg->sae_status); + if (assoc_req->present) { + pe_debug("Assoc req cached; clean it up"); + lim_process_assoc_cleanup(mac, session, + assoc_req->assoc_req, + assoc_req->sta_ds, + assoc_req->assoc_req_copied); + assoc_req->present = false; + } + lim_delete_pre_auth_node(mac, sae_msg->peer_mac_addr); + return; + } + sta_pre_auth_ctx->mlmState = eLIM_MLM_AUTHENTICATED_STATE; + /* Send assoc indication to SME if any assoc request is cached*/ + if (assoc_req->present) { + /* Assoc request is present in preauth context. Get the assoc + * request and make it invalid in preauth context. It'll be + * freed later in the legacy path. + */ + bool assoc_req_copied; + + assoc_req->present = false; + pe_debug("Assoc req cached; handle it"); + if (lim_send_assoc_ind_to_sme(mac, session, + assoc_req->sub_type, + &assoc_req->hdr, + assoc_req->assoc_req, + assoc_req->pmf_connection, + &assoc_req_copied, + assoc_req->dup_entry, + false) == false) + lim_process_assoc_cleanup(mac, session, + assoc_req->assoc_req, + assoc_req->sta_ds, + assoc_req_copied); + } +} + +/** * lim_process_sae_msg() - Process SAE message * @mac: Global MAC pointer * @body: Buffer pointer @@ -87,40 +197,23 @@ static void lim_process_sae_msg(tpAniSirGlobal mac, struct sir_sae_msg *body) return; } - if (session->pePersona != QDF_STA_MODE) { + if (session->pePersona != QDF_STA_MODE && + session->pePersona != QDF_SAP_MODE) { pe_err("SAE:Not supported in this mode %d", session->pePersona); return; } - pe_debug("SAE:status %d limMlmState %d pePersona %d", - sae_msg->sae_status, session->limMlmState, - session->pePersona); - switch (session->limMlmState) { - case eLIM_MLM_WT_SAE_AUTH_STATE: - /* SAE authentication is completed. Restore from auth state */ - if (tx_timer_running(&mac->lim.limTimers.sae_auth_timer)) - lim_deactivate_and_change_timer(mac, - eLIM_AUTH_SAE_TIMER); - /* success */ - if (sae_msg->sae_status == IEEE80211_STATUS_SUCCESS) - lim_restore_from_auth_state(mac, - eSIR_SME_SUCCESS, - eSIR_MAC_SUCCESS_STATUS, - session); - else - lim_restore_from_auth_state(mac, - eSIR_SME_AUTH_REFUSED, - eSIR_MAC_UNSPEC_FAILURE_STATUS, - session); - break; - default: - /* SAE msg is received in unexpected state */ - pe_err("received SAE msg in state %X", - session->limMlmState); - lim_print_mlm_state(mac, LOGE, session->limMlmState); - break; - } + pe_debug("SAE:status %d limMlmState %d pePersona %d peer: " + MAC_ADDRESS_STR, sae_msg->sae_status, + session->limMlmState, session->pePersona, + MAC_ADDR_ARRAY(sae_msg->peer_mac_addr)); + if (LIM_IS_STA_ROLE(session)) + lim_process_sae_msg_sta(mac, session, sae_msg); + else if (LIM_IS_AP_ROLE(session)) + lim_process_sae_msg_ap(mac, session, sae_msg); + else + pe_debug("SAE message on unsupported interface"); } #else static inline void lim_process_sae_msg(tpAniSirGlobal mac, void *body) @@ -907,12 +1000,13 @@ lim_check_mgmt_registered_frames(tpAniSirGlobal mac_ctx, uint8_t *buff_desc, QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, FL("rcvd frame match with registered frame params")); /* Indicate this to SME */ - lim_send_sme_mgmt_frame_ind(mac_ctx, hdr->fc.subType, - (uint8_t *) hdr, + lim_send_sme_mgmt_frame_ind( + mac_ctx, hdr->fc.subType, (uint8_t *)hdr, WMA_GET_RX_PAYLOAD_LEN(buff_desc) + - sizeof(tSirMacMgmtHdr), mgmt_frame->sessionId, - WMA_GET_RX_CH(buff_desc), session_entry, - WMA_GET_RX_RSSI_NORMALIZED(buff_desc)); + sizeof(tSirMacMgmtHdr), + mgmt_frame->sessionId, WMA_GET_RX_CH(buff_desc), + session_entry, WMA_GET_RX_RSSI_NORMALIZED(buff_desc), + RXMGMT_FLAG_NONE); if ((type == SIR_MAC_MGMT_FRAME) && (fc.type == SIR_MAC_MGMT_FRAME) diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index 5110ecd9432a..f21787407d6b 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -757,7 +757,7 @@ lim_fill_assoc_ind_params(tpAniSirGlobal mac_ctx, if (assoc_ind->VHTCaps.present) sme_assoc_ind->VHTCaps = assoc_ind->VHTCaps; sme_assoc_ind->capability_info = assoc_ind->capabilityInfo; - + sme_assoc_ind->is_sae_authenticated = assoc_ind->is_sae_authenticated; } /** diff --git a/core/mac/src/pe/lim/lim_process_probe_req_frame.c b/core/mac/src/pe/lim/lim_process_probe_req_frame.c index 82961f0b025c..af06148a3793 100644 --- a/core/mac/src/pe/lim/lim_process_probe_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_probe_req_frame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -555,7 +555,8 @@ lim_indicate_probe_req_to_hdd(tpAniSirGlobal pMac, uint8_t *pBd, (frameLen + sizeof(tSirMacMgmtHdr)), psessionEntry->smeSessionId, WMA_GET_RX_CH(pBd), psessionEntry, - WMA_GET_RX_RSSI_NORMALIZED(pBd)); + WMA_GET_RX_RSSI_NORMALIZED(pBd), + RXMGMT_FLAG_NONE); } /*** end lim_indicate_probe_req_to_hdd() ***/ /** diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index e5e33917fb9c..a6b3ce7807d6 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -3602,21 +3602,33 @@ void __lim_process_sme_assoc_cnf_new(tpAniSirGlobal mac_ctx, uint32_t msg_type, session_entry); goto end; } else { + uint8_t add_pre_auth_context = true; /* * SME_ASSOC_CNF status is non-success, so STA is not allowed * to be associated since the HAL sta entry is created for * denied STA we need to remove this HAL entry. * So to do that set updateContext to 1 */ + tSirMacStatusCodes mac_status_code = + eSIR_MAC_UNSPEC_FAILURE_STATUS; if (!sta_ds->mlmStaContext.updateContext) sta_ds->mlmStaContext.updateContext = 1; - pe_debug("Recv Assoc Cnf, status Code : %d(assoc id=%d)", - assoc_cnf.statusCode, sta_ds->assocId); + pe_debug("Recv Assoc Cnf, status Code : %d(assoc id=%d) Reason code: %d", + assoc_cnf.statusCode, sta_ds->assocId, + assoc_cnf.mac_status_code); + if (assoc_cnf.mac_status_code) + mac_status_code = assoc_cnf.mac_status_code; + if (assoc_cnf.mac_status_code == eSIR_MAC_INVALID_PMKID || + assoc_cnf.mac_status_code == + eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS) + add_pre_auth_context = false; + lim_reject_association(mac_ctx, sta_ds->staAddr, sta_ds->mlmStaContext.subType, - true, sta_ds->mlmStaContext.authType, + add_pre_auth_context, + sta_ds->mlmStaContext.authType, sta_ds->assocId, true, - eSIR_MAC_UNSPEC_FAILURE_STATUS, + mac_status_code, session_entry); } end: diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c index 5cf1f04803e0..b4831eef1f2f 100644 --- a/core/mac/src/pe/lim/lim_process_tdls.c +++ b/core/mac/src/pe/lim/lim_process_tdls.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -2223,8 +2223,7 @@ lim_tdls_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode stads, tDot11fIEVHTCaps *vht_caps) { tSirMacRateSet temp_rate_set; - uint32_t i, j, val, min, is_a_rate; - tSirMacRateSet temp_rate_set2; + uint32_t i, j, val, is_a_rate; uint32_t phymode; uint8_t mcsSet[SIZE_OF_SUPPORTED_MCS_SET]; tpSirSupportedRates rates; @@ -2233,70 +2232,9 @@ lim_tdls_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode stads, uint8_t nss; is_a_rate = 0; - temp_rate_set2.numRates = 0; lim_get_phy_mode(mac_ctx, &phymode, NULL); - /* get own rate set */ - val = WNI_CFG_OPERATIONAL_RATE_SET_LEN; - if (wlan_cfg_get_str(mac_ctx, WNI_CFG_OPERATIONAL_RATE_SET, - (uint8_t *) &temp_rate_set.rate, - &val) != eSIR_SUCCESS) { - /* Could not get rateset from CFG. Log error. */ - pe_err("could not retrieve rateset"); - val = 0; - } - temp_rate_set.numRates = val; - - if (phymode == WNI_CFG_PHY_MODE_11G) { - /* get own extended rate set */ - val = WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN; - if (wlan_cfg_get_str(mac_ctx, - WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, - (uint8_t *) &temp_rate_set2.rate, - &val) != eSIR_SUCCESS) - temp_rate_set2.numRates = val; - } - - if ((temp_rate_set.numRates + temp_rate_set2.numRates) > 12) { - pe_err("more than 12 rates in CFG"); - return eSIR_FAILURE; - } - - /** - * Handling of the rate set IEs is the following: - * - keep only rates that we support and that the station supports - * - sort and the rates into the pSta->rate array - */ - - /* Copy all rates in temp_rate_set, there are 12 rates max */ - for (i = 0; i < temp_rate_set2.numRates; i++) - temp_rate_set.rate[i + temp_rate_set.numRates] = - temp_rate_set2.rate[i]; - - temp_rate_set.numRates += temp_rate_set2.numRates; - - /** - * Sort rates in temp_rate_set (they are likely to be already sorted) - * put the result in temp_rate_set2 - */ - temp_rate_set2.numRates = 0; - - for (i = 0; i < temp_rate_set.numRates; i++) { - min = 0; - val = 0xff; - - for (j = 0; j < temp_rate_set.numRates; j++) - if ((uint32_t) (temp_rate_set.rate[j] & 0x7f) < val) { - val = temp_rate_set.rate[j] & 0x7f; - min = j; - } - - temp_rate_set2.rate[temp_rate_set2.numRates++] = - temp_rate_set.rate[min]; - temp_rate_set.rate[min] = 0xff; - } - /** * Copy received rates in temp_rate_set, the parser has ensured * unicity of the rates so there cannot be more than 12 . @@ -2315,27 +2253,22 @@ lim_tdls_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode stads, rates = &stads->supportedRates; qdf_mem_set((uint8_t *) rates, sizeof(tSirSupportedRates), 0); - for (i = 0; i < temp_rate_set2.numRates; i++) { - for (j = 0; j < temp_rate_set.numRates; j++) { - if ((temp_rate_set2.rate[i] & 0x7F) != - (temp_rate_set.rate[j] & 0x7F)) - continue; - - if ((b_rateindex > SIR_NUM_11B_RATES) || - (a_rateindex > SIR_NUM_11A_RATES)) { - pe_warn("Invalid number of rates (11b->%d, 11a->%d)", - b_rateindex, a_rateindex); - return eSIR_FAILURE; - } - if (sirIsArate(temp_rate_set2.rate[i] & 0x7f)) { - is_a_rate = 1; - if (a_rateindex < SIR_NUM_11A_RATES) - rates->llaRates[a_rateindex++] = temp_rate_set2.rate[i]; - } else { - if (b_rateindex < SIR_NUM_11B_RATES) - rates->llbRates[b_rateindex++] = temp_rate_set2.rate[i]; - } - break; + for (j = 0; j < temp_rate_set.numRates; j++) { + if ((b_rateindex > SIR_NUM_11B_RATES) || + (a_rateindex > SIR_NUM_11A_RATES)) { + pe_warn("Invalid number of rates (11b->%d, 11a->%d)", + b_rateindex, a_rateindex); + return eSIR_FAILURE; + } + if (sirIsArate(temp_rate_set.rate[j] & 0x7f)) { + is_a_rate = 1; + if (a_rateindex < SIR_NUM_11A_RATES) + rates->llaRates[a_rateindex++] = + temp_rate_set.rate[j]; + } else { + if (b_rateindex < SIR_NUM_11B_RATES) + rates->llbRates[b_rateindex++] = + temp_rate_set.rate[j]; } } diff --git a/core/mac/src/pe/lim/lim_security_utils.c b/core/mac/src/pe/lim/lim_security_utils.c index a99bcff2a561..f6c544102f83 100644 --- a/core/mac/src/pe/lim/lim_security_utils.c +++ b/core/mac/src/pe/lim/lim_security_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -320,9 +320,18 @@ void lim_add_pre_auth_node(tpAniSirGlobal pMac, struct tLimPreAuthNode *pAuthNod void lim_release_pre_auth_node(tpAniSirGlobal pMac, tpLimPreAuthNode pAuthNode) { pAuthNode->fFree = 1; - MTRACE(mac_trace - (pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, - eLIM_PRE_AUTH_CLEANUP_TIMER)); + if (pAuthNode->authType == eSIR_AUTH_TYPE_SAE && + pAuthNode->assoc_req.present) { + tpSirAssocReq assoc = + (tpSirAssocReq)pAuthNode->assoc_req.assoc_req; + + if (assoc->assocReqFrameLength) + qdf_mem_free(assoc->assocReqFrame); + qdf_mem_free(assoc); + pAuthNode->assoc_req.present = false; + } + MTRACE(mac_trace(pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, + eLIM_PRE_AUTH_CLEANUP_TIMER)); tx_timer_deactivate(&pAuthNode->timer); pMac->lim.gLimNumPreAuthContexts--; } /*** end lim_release_pre_auth_node() ***/ diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 87b5598c03de..7d49ff37421d 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -1629,6 +1629,7 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, void *packet; QDF_STATUS qdf_status; uint16_t add_ie_len, assoc_ack_status; + uint16_t current_len = 0, vendor_ie_len = 0; uint8_t *add_ie; uint8_t *wps_ie = NULL; uint8_t power_caps = false; @@ -1645,7 +1646,7 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, uint32_t bcn_ie_len = 0; uint32_t aes_block_size_len = 0; enum rateid min_rid = RATEID_DEFAULT; - uint8_t *mbo_ie = NULL; + uint8_t *mbo_ie = NULL, *vendor_ies = NULL; uint8_t mbo_ie_len = 0; if (NULL == pe_session) { @@ -1962,6 +1963,33 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, } /* + * Strip rest of the vendor IEs and append to the assoc request frame. + * Append the IEs just before MBO IEs as MBO IEs have to be at the + * end of the frame. + */ + if (wlan_cfg_get_ie_ptr(add_ie, add_ie_len, SIR_MAC_EID_VENDOR, + ONE_BYTE)) { + vendor_ies = qdf_mem_malloc(MAX_VENDOR_IES_LEN + 2); + if (vendor_ies) { + current_len = add_ie_len; + sir_status = lim_strip_ie(mac_ctx, add_ie, &add_ie_len, + SIR_MAC_EID_VENDOR, ONE_BYTE, + NULL, + 0, + vendor_ies, + MAX_VENDOR_IES_LEN); + if (sir_status != eSIR_SUCCESS) { + pe_err("Failed to strip Vendor IEs"); + goto end; + } + + vendor_ie_len = current_len - add_ie_len; + pe_debug("Stripped vendor IEs of size: %u", + current_len); + } + } + + /* * Do unpack to populate the add_ie buffer to frm structure * before packing the frm structure. In this way, the IE ordering * which the latest 802.11 spec mandates is maintained. @@ -1987,7 +2015,7 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, } bytes = payload + sizeof(tSirMacMgmtHdr) + - aes_block_size_len + mbo_ie_len; + aes_block_size_len + mbo_ie_len + vendor_ie_len; qdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame, (void **)&packet); @@ -2027,6 +2055,11 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, pe_warn("Assoc request pack warning (0x%08x)", status); } + /* Copy the vendor IEs to the end of the frame */ + qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload, + vendor_ies, vendor_ie_len); + payload = payload + vendor_ie_len; + /* Copy the MBO IE to the end of the frame */ qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload, mbo_ie, mbo_ie_len); @@ -2104,6 +2137,7 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, goto end; } end: + qdf_mem_free(vendor_ies); qdf_mem_free(mbo_ie); /* Free up buffer allocated for mlm_assoc_req */ qdf_mem_free(mlm_assoc_req); @@ -4699,12 +4733,16 @@ void lim_send_mgmt_frame_tx(tpAniSirGlobal mac_ctx, QDF_STATUS qdf_status; uint8_t *frame; void *packet; + tpSirMacMgmtHdr mac_hdr; msg_len = mb_msg->msg_len - sizeof(*mb_msg); pe_debug("sending fc->type: %d fc->subType: %d", fc->type, fc->subType); sme_session_id = mb_msg->session_id; + mac_hdr = (tpSirMacMgmtHdr)mb_msg->data; + + lim_add_mgmt_seq_num(mac_ctx, mac_hdr); qdf_status = cds_packet_alloc((uint16_t) msg_len, (void **)&frame, (void **)&packet); diff --git a/core/mac/src/pe/lim/lim_send_messages.h b/core/mac/src/pe/lim/lim_send_messages.h index fd1e661d55d8..b2acad9de49c 100644 --- a/core/mac/src/pe/lim/lim_send_messages.h +++ b/core/mac/src/pe/lim/lim_send_messages.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -88,6 +88,8 @@ void lim_set_active_edca_params(tpAniSirGlobal pMac, tSirRetStatus lim_send_beacon_filter_info(tpAniSirGlobal pMac, tpPESession psessionEntry); +#define MAX_VENDOR_IES_LEN 1532 + #ifdef WLAN_FEATURE_11W tSirRetStatus lim_send_exclude_unencrypt_ind(tpAniSirGlobal pMac, bool excludeUnenc, diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 8caf092c4af5..babb7ffae70f 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -270,6 +270,7 @@ typedef struct sLimMlmAssocInd { tDot11fIEHTCaps HTCaps; tDot11fIEVHTCaps VHTCaps; + bool is_sae_authenticated; } tLimMlmAssocInd, *tpLimMlmAssocInd; typedef struct sLimMlmReassocReq { @@ -904,11 +905,23 @@ void lim_change_channel_with_callback(tpAniSirGlobal pMac, uint8_t newChannel, CHANGE_CHANNEL_CALLBACK callback, uint32_t *cbdata, tpPESession psessionEntry); - -void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType, - uint8_t *frame, uint32_t frameLen, - uint16_t sessionId, uint32_t rxChan, - tpPESession psessionEntry, int8_t rxRssi); +/* + * lim_send_sme_mgmt_frame_ind() - Function to send mgmt frame ind to HDD + * @mac_ctx: Pointer to Global MAC structure + * @frame_type: Type of mgmt frame + * @frame: Frame pointer + * @frame_len: Length og mgmt frame + * @session_id: session id + * @rx_chan: Channel of where packet is received + * @psession_entry: PE Session Entry + * @rx_rssi: rssi value + * @rx_flags: RXMGMT flags to be set for the frame. Defined in enum rxmgmt_flags + */ +void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal mac_ctx, uint8_t frame_type, + uint8_t *frame, uint32_t frame_len, + uint16_t session_id, uint32_t rx_chan, + tpPESession psession_entry, + int8_t rx_rssi, enum rxmgmt_flags rx_flags); void lim_process_remain_on_chn_timeout(tpAniSirGlobal pMac); void lim_process_insert_single_shot_noa_timeout(tpAniSirGlobal pMac); void lim_convert_active_channel_to_passive_channel(tpAniSirGlobal pMac); @@ -1040,4 +1053,49 @@ void lim_send_mgmt_frame_tx(tpAniSirGlobal mac_ctx, */ bool lim_p2p_check_oui_and_force_1x1(tpAniSirGlobal mac_ctx, uint8_t *assoc_ie, uint32_t assoc_ie_len); + +/** + * lim_process_assoc_cleanup() - frees up resources used in function + * lim_process_assoc_req_frame() + * @mac_ctx: pointer to Global MAC structure + * @session: pointer to pe session entry + * @assoc_req: pointer to ASSOC/REASSOC Request frame + * @sta_ds: station dph entry + * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above + * + * Frees up resources used in function lim_process_assoc_req_frame + * + * Return: void + */ +void lim_process_assoc_cleanup(tpAniSirGlobal mac_ctx, + tpPESession session, + tpSirAssocReq assoc_req, + tpDphHashNode sta_ds, + bool assoc_req_copied); + +/** + * lim_send_assoc_ind_to_sme() - Initialize PE data structures and send assoc + * indication to SME. + * @mac_ctx: Pointer to Global MAC structure + * @session: pe session entry + * @sub_type: Indicates whether it is Association Request(=0) or Reassociation + * Request(=1) frame + * @hdr: A pointer to the MAC header + * @assoc_req: pointer to ASSOC/REASSOC Request frame + * @pmf_connection: flag indicating pmf connection + * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above + * @dup_entry: flag indicating if duplicate entry found + * @force_1x1: flag to indicate if the STA nss needs to be downgraded to 1x1 + * + * Return: true on success, and false otherwise + */ +bool lim_send_assoc_ind_to_sme(tpAniSirGlobal mac_ctx, + tpPESession session, + uint8_t sub_type, + tpSirMacMgmtHdr hdr, + tpSirAssocReq assoc_req, + bool pmf_connection, + bool *assoc_req_copied, + bool dup_entry, + bool force_1x1); #endif /* __LIM_TYPES_H */ diff --git a/core/mac/src/pe/nan/nan_datapath.c b/core/mac/src/pe/nan/nan_datapath.c index 6a38d72a050e..34d73712b7d9 100644 --- a/core/mac/src/pe/nan/nan_datapath.c +++ b/core/mac/src/pe/nan/nan_datapath.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019,2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -158,9 +158,8 @@ static QDF_STATUS lim_handle_ndp_indication_event(tpAniSirGlobal mac_ctx, goto ndp_indication_failed; } } - if (NDP_ROLE_RESPONDER == ndp_ind->role) - lim_send_ndp_event_to_sme(mac_ctx, eWNI_SME_NDP_INDICATION, - ndp_ind, sizeof(*ndp_ind), 0); + lim_send_ndp_event_to_sme(mac_ctx, eWNI_SME_NDP_INDICATION, + ndp_ind, sizeof(*ndp_ind), 0); /* * With NDP indication if peer does not exists already add_sta is * executed resulting in new peer else no action is taken. Note that @@ -170,13 +169,8 @@ static QDF_STATUS lim_handle_ndp_indication_event(tpAniSirGlobal mac_ctx, * used by service layer to identify failure. */ ndp_indication_failed: - /* - * Free config if failure or for NDP_ROLE_INITIATOR role - * As for success responder case this info is sent till HDD - * and will be freed in sme. - */ - if (status != QDF_STATUS_SUCCESS || - NDP_ROLE_INITIATOR == ndp_ind->role) { + /* free config and app info if failure */ + if (status != QDF_STATUS_SUCCESS) { qdf_mem_free(ndp_ind->ndp_config.ndp_cfg); qdf_mem_free(ndp_ind->ndp_info.ndp_app_info); ndp_ind->ndp_config.ndp_cfg = NULL; diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index f5aadcca0c81..7beb7bb15e0c 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -4844,6 +4844,7 @@ static QDF_STATUS sap_get_channel_list(ptSapContext sap_ctx, tSapChSelSpectInfo spect_info_obj = { NULL, 0 }; uint16_t ch_width; uint8_t i; + uint8_t ch; if (NULL == hal) { QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, @@ -4958,10 +4959,8 @@ static QDF_STATUS sap_get_channel_list(ptSapContext sap_ctx, continue; } -#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE - uint8_t ch; - ch = CDS_CHANNEL_NUM(loop_count); +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE if ((sap_ctx->acs_cfg->skip_scan_status == eSAP_DO_PAR_ACS_SCAN)) { if ((ch >= sap_ctx->acs_cfg->skip_scan_range1_stch && @@ -4991,7 +4990,7 @@ static QDF_STATUS sap_get_channel_list(ptSapContext sap_ctx, ch_count, ch); } #else - list[ch_count] = CDS_CHANNEL_NUM(loop_count); + list[ch_count] = ch; ch_count++; #endif } diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index fef3c05dc7a3..32022b370d32 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -360,6 +360,11 @@ typedef struct tagCsrEseCckmIe { uint8_t cckmIe[DOT11F_IE_RSN_MAX_LEN]; uint8_t cckmIeLen; } tCsrEseCckmIe; + +#define reset_cckm_info(cckm_info) \ + qdf_mem_zero((cckm_info), sizeof(tCsrEseCckmInfo)) +#else +#define reset_cckm_info(cckm_info) #endif /* FEATURE_WLAN_ESE */ typedef struct sCsrChannel_ { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 55674fcc965e..080249e76944 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -2309,14 +2309,20 @@ QDF_STATUS sme_send_mgmt_tx(tHalHandle hal, uint8_t session_id, * @hal: The handle returned by mac_open * @session_id: session id * @sae_status: status of SAE authentication + * @peer_mac_addr: mac address of the peer to be authenticated * * Return: QDF_STATUS */ -QDF_STATUS sme_handle_sae_msg(tHalHandle hal, uint8_t session_id, - uint8_t sae_status); +QDF_STATUS sme_handle_sae_msg(tHalHandle hal, + uint8_t session_id, + uint8_t sae_status, + struct qdf_mac_addr peer_mac_addr); #else -static inline QDF_STATUS sme_handle_sae_msg(tHalHandle hal, uint8_t session_id, - uint8_t sae_status) +static inline +QDF_STATUS sme_handle_sae_msg(tHalHandle hal, + uint8_t session_id, + uint8_t sae_status, + struct qdf_mac_addr peer_mac_addr) { return QDF_STATUS_SUCCESS; } diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index ff32941eff97..4eec3b9da324 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -19487,8 +19487,10 @@ QDF_STATUS sme_send_mgmt_tx(tHalHandle hal, uint8_t session_id, } #ifdef WLAN_FEATURE_SAE -QDF_STATUS sme_handle_sae_msg(tHalHandle hal, uint8_t session_id, - uint8_t sae_status) +QDF_STATUS sme_handle_sae_msg(tHalHandle hal, + uint8_t session_id, + uint8_t sae_status, + struct qdf_mac_addr peer_mac_addr) { QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; tpAniSirGlobal mac = PMAC_STRUCT(hal); @@ -19505,9 +19507,13 @@ QDF_STATUS sme_handle_sae_msg(tHalHandle hal, uint8_t session_id, sae_msg->length = sizeof(*sae_msg); sae_msg->session_id = session_id; sae_msg->sae_status = sae_status; - sme_debug("SAE: sae_status %d session_id %d", - sae_msg->sae_status, - sae_msg->session_id); + qdf_mem_copy(sae_msg->peer_mac_addr, + peer_mac_addr.bytes, + MAC_ADDR_LEN); + sme_debug("SAE: sae_status %d session_id %d Peer: " + MAC_ADDRESS_STR, sae_msg->sae_status, + sae_msg->session_id, + MAC_ADDR_ARRAY(sae_msg->peer_mac_addr)); qdf_status = cds_send_mb_message_to_mac(sae_msg); } diff --git a/core/sme/src/common/sme_ft_api.c b/core/sme/src/common/sme_ft_api.c index b34bdaec3a7b..516552d0e004 100644 --- a/core/sme/src/common/sme_ft_api.c +++ b/core/sme/src/common/sme_ft_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017,2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017,2019-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -487,7 +487,7 @@ void sme_reset_key(tHalHandle mac_handle, uint32_t vdev_id) return; qdf_mem_zero(&session->psk_pmk, sizeof(session->psk_pmk)); session->pmk_len = 0; - qdf_mem_zero(&session->eseCckmInfo, sizeof(session->eseCckmInfo)); + reset_cckm_info(&session->eseCckmInfo); } /* Reset the FT context. */ diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 52560b37b560..3d5b76fddf06 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -47,7 +47,9 @@ #include "pld_common.h" #include "qdf_crypto.h" #include <wlan_logging_sock_svc.h> +#include <cds_ieee80211_common.h> +#define RSN_AUTH_KEY_MGMT_SAE RSN_SEL(AKM_SUITE_TYPE_SAE) #define MAX_PWR_FCC_CHAN_12 8 #define MAX_PWR_FCC_CHAN_13 2 @@ -11675,6 +11677,54 @@ static QDF_STATUS csr_send_reset_ap_caps_changed(tpAniSirGlobal pMac, return status; } +static bool csr_is_sae_akm_present(tDot11fIERSN * const rsn_ie) +{ + uint16_t i; + + if (rsn_ie->akm_suite_cnt > 6) { + sme_debug("Invalid akm_suite_cnt in Rx RSN IE"); + return false; + } + + for (i = 0; i < rsn_ie->akm_suite_cnt; i++) { + if (LE_READ_4(rsn_ie->akm_suite[i]) == RSN_AUTH_KEY_MGMT_SAE) { + sme_debug("SAE AKM present"); + return true; + } + } + return false; +} + +static bool csr_is_sae_peer_allowed(tpAniSirGlobal mac, + tSirSmeAssocInd *assoc_ind, + tCsrRoamSession *session, + tSirMacAddr peer_mac_addr, + tDot11fIERSN *rsn_ie, + tSirMacStatusCodes *mac_status_code) +{ + bool is_allowed = false; + + /* Allow the peer if it's SAE authenticated */ + if (assoc_ind->is_sae_authenticated) + return true; + + /* Allow the peer with valid PMKID */ + if (!rsn_ie->pmkid_count) { + *mac_status_code = eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS; + sme_debug("No PMKID present in RSNIE; Tried to use SAE AKM after non-SAE authentication"); + } else if (csr_is_pmkid_found_for_peer(mac, session, peer_mac_addr, + &rsn_ie->pmkid[0][0], + rsn_ie->pmkid_count)) { + sme_debug("Valid PMKID found for SAE peer"); + is_allowed = true; + } else { + *mac_status_code = eSIR_MAC_INVALID_PMKID; + sme_debug("No valid PMKID found for SAE peer"); + } + + return is_allowed; +} + static void csr_roam_chk_lnk_assoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) { @@ -11684,6 +11734,7 @@ csr_roam_chk_lnk_assoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) tCsrRoamInfo *roam_info_ptr = NULL; tSirSmeAssocInd *pAssocInd; tCsrRoamInfo roam_info; + tSirMacStatusCodes mac_status_code = eSIR_MAC_SUCCESS_STATUS; qdf_mem_set(&roam_info, sizeof(roam_info), 0); sme_debug("Receive WNI_SME_ASSOC_IND from SME"); @@ -11756,13 +11807,35 @@ csr_roam_chk_lnk_assoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) status = csr_roam_call_callback(mac_ctx, sessionId, roam_info_ptr, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND); - if (!QDF_IS_STATUS_SUCCESS(status)) + if (!QDF_IS_STATUS_SUCCESS(status)) { /* Refused due to Mac filtering */ roam_info_ptr->statusCode = eSIR_SME_ASSOC_REFUSED; + } else if (pAssocInd->rsnIE.length) { + tDot11fIERSN rsn_ie = {0}; + + if (dot11f_unpack_ie_rsn(mac_ctx, + pAssocInd->rsnIE.rsnIEdata + 2, + pAssocInd->rsnIE.length - 2, + &rsn_ie, false) + != DOT11F_PARSE_SUCCESS || + (csr_is_sae_akm_present(&rsn_ie) && + !csr_is_sae_peer_allowed(mac_ctx, pAssocInd, + session, + pAssocInd->peerMacAddr, + &rsn_ie, + &mac_status_code))) { + status = QDF_STATUS_E_INVAL; + roam_info_ptr->statusCode = + eSIR_SME_ASSOC_REFUSED; + sme_debug("SAE peer not allowed: Status: %d", + mac_status_code); + } + } } /* Send Association completion message to PE */ - status = csr_send_assoc_cnf_msg(mac_ctx, pAssocInd, status); + status = csr_send_assoc_cnf_msg(mac_ctx, pAssocInd, status, + mac_status_code); /* * send a message to CSR itself just to avoid the EAPOL frames going * OTA before association response @@ -17102,8 +17175,10 @@ QDF_STATUS csr_send_mb_deauth_cnf_msg(tpAniSirGlobal pMac, return status; } -QDF_STATUS csr_send_assoc_cnf_msg(tpAniSirGlobal pMac, tpSirSmeAssocInd - pAssocInd, QDF_STATUS Halstatus) +QDF_STATUS csr_send_assoc_cnf_msg(tpAniSirGlobal pMac, + tpSirSmeAssocInd pAssocInd, + QDF_STATUS Halstatus, + tSirMacStatusCodes mac_status_code) { QDF_STATUS status = QDF_STATUS_SUCCESS; tSirSmeAssocCnf *pMsg; @@ -17116,10 +17191,12 @@ QDF_STATUS csr_send_assoc_cnf_msg(tpAniSirGlobal pMac, tpSirSmeAssocInd return QDF_STATUS_E_NOMEM; pMsg->messageType = eWNI_SME_ASSOC_CNF; pMsg->length = sizeof(tSirSmeAssocCnf); - if (QDF_IS_STATUS_SUCCESS(Halstatus)) + if (QDF_IS_STATUS_SUCCESS(Halstatus)) { pMsg->statusCode = eSIR_SME_SUCCESS; - else + } else { pMsg->statusCode = eSIR_SME_ASSOC_REFUSED; + pMsg->mac_status_code = mac_status_code; + } /* bssId */ qdf_mem_copy(pMsg->bssid.bytes, pAssocInd->bssId, QDF_MAC_ADDR_SIZE); diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index e417673842ae..e823a7102398 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -475,9 +475,10 @@ QDF_STATUS csr_send_mb_disassoc_cnf_msg(tpAniSirGlobal pMac, tpSirSmeDisassocInd pDisassocInd); QDF_STATUS csr_send_mb_deauth_cnf_msg(tpAniSirGlobal pMac, tpSirSmeDeauthInd pDeauthInd); -QDF_STATUS csr_send_assoc_cnf_msg(tpAniSirGlobal pMac, tpSirSmeAssocInd - pAssocInd, - QDF_STATUS status); +QDF_STATUS csr_send_assoc_cnf_msg(tpAniSirGlobal pMac, + tpSirSmeAssocInd pAssocInd, + QDF_STATUS status, + tSirMacStatusCodes mac_status_code); QDF_STATUS csr_send_assoc_ind_to_upper_layer_cnf_msg(tpAniSirGlobal pMac, tpSirSmeAssocInd pAssocInd, QDF_STATUS Halstatus, @@ -1301,4 +1302,20 @@ bool csr_lookup_pmkid_using_bssid(tpAniSirGlobal mac, tPmkidCacheInfo *pmk_cache, uint32_t *index); +/** + * csr_is_pmkid_found_for_peer() - check if pmkid sent by peer is present + * in PMK cache. Used in SAP mode. + * @mac: pointer to mac + * @session: sme session pointer + * @peer_mac_addr: mac address of the connecting peer + * @pmkid: pointer to pmkid(s) send by peer + * @pmkid_count: number of pmkids sent by peer + * + * Return: true if pmkid is found else false + */ +bool csr_is_pmkid_found_for_peer(tpAniSirGlobal mac, + tCsrRoamSession *session, + tSirMacAddr peer_mac_addr, + uint8_t *pmkid, uint16_t pmkid_count); + #endif /* CSR_INSIDE_API_H__ */ diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 7958cba2a5ea..7f32969e3f89 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -3098,6 +3098,32 @@ static void csr_check_sae_auth(tpAniSirGlobal mac_ctx, } #endif +bool csr_is_pmkid_found_for_peer(tpAniSirGlobal mac, + tCsrRoamSession *session, + tSirMacAddr peer_mac_addr, + uint8_t *pmkid, + uint16_t pmkid_count) +{ + uint32_t i, index; + uint8_t *session_pmkid; + tPmkidCacheInfo pmkid_cache; + + qdf_mem_zero(&pmkid_cache, sizeof(pmkid_cache)); + qdf_mem_copy(pmkid_cache.BSSID.bytes, peer_mac_addr, MAC_ADDR_LEN); + + if (!csr_lookup_pmkid_using_bssid(mac, session, &pmkid_cache, &index)) + return false; + session_pmkid = &session->PmkidCacheInfo[index].PMKID[0]; + for (i = 0; i < pmkid_count; i++) { + if (!qdf_mem_cmp(pmkid + (i * CSR_RSN_PMKID_SIZE), + session_pmkid, CSR_RSN_PMKID_SIZE)) + return true; + } + + sme_debug("PMKID in PmkidCacheInfo doesn't match with PMKIDs of peer"); + return false; +} + /** * csr_get_rsn_information() - to get RSN infomation * @hal: pointer to HAL diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 161609e3e178..3bf53e023984 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -11133,6 +11133,9 @@ int wma_unified_power_debug_stats_event_handler(void *handle, mac->sme.power_stats_resp_callback(power_stats_results, mac->sme.power_debug_stats_context); + + mac->sme.power_stats_resp_callback = NULL; + mac->sme.power_debug_stats_context = NULL; qdf_mem_free(power_stats_results); return 0; } |
