// SPDX-License-Identifier: GPL-2.0-only /* * NXP Wireless LAN device driver: scan ioctl and command handling * * Copyright 2011-2020 NXP */ #include "decl.h" #include "ioctl.h" #include "util.h" #include "fw.h" #include "main.h" #include "11n.h" #include "cfg80211.h" /* The maximum number of channels the firmware can scan per command */ #define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN … #define MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD … /* Memory needed to store a max sized Channel List TLV for a firmware scan */ #define CHAN_TLV_MAX_SIZE … /* Memory needed to store supported rate */ #define RATE_TLV_MAX_SIZE … /* Memory needed to store a max number/size WildCard SSID TLV for a firmware scan */ #define WILDCARD_SSID_TLV_MAX_SIZE … /* Maximum memory needed for a mwifiex_scan_cmd_config with all TLVs at max */ #define MAX_SCAN_CFG_ALLOC … mwifiex_scan_cmd_config_tlv; enum cipher_suite { … }; static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = …; static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = …; static void _dbg_security_flags(int log_level, const char *func, const char *desc, struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { … } #define dbg_security_flags(mask, desc, priv, bss_desc) … static bool has_ieee_hdr(struct ieee_types_generic *ie, u8 key) { … } static bool has_vendor_hdr(struct ieee_types_vendor_specific *ie, u8 key) { … } /* * This function parses a given IE for a given OUI. * * This is used to parse a WPA/RSN IE to find if it has * a given oui in PTK. */ static u8 mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui) { … } /* * This function checks if a given OUI is present in a RSN IE. * * The function first checks if a RSN IE is present or not in the * BSS descriptor. It tries to locate the OUI only if such an IE is * present. */ static u8 mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) { … } /* * This function checks if a given OUI is present in a WPA IE. * * The function first checks if a WPA IE is present or not in the * BSS descriptor. It tries to locate the OUI only if such an IE is * present. */ static u8 mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) { … } /* * This function checks if wapi is enabled in driver and scanned network is * compatible with it. */ static bool mwifiex_is_bss_wapi(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { … } /* * This function checks if driver is configured with no security mode and * scanned network is compatible with it. */ static bool mwifiex_is_bss_no_sec(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { … } /* * This function checks if static WEP is enabled in driver and scanned network * is compatible with it. */ static bool mwifiex_is_bss_static_wep(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { … } /* * This function checks if wpa is enabled in driver and scanned network is * compatible with it. */ static bool mwifiex_is_bss_wpa(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { … } /* * This function checks if wpa2 is enabled in driver and scanned network is * compatible with it. */ static bool mwifiex_is_bss_wpa2(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { … } /* * This function checks if adhoc AES is enabled in driver and scanned network is * compatible with it. */ static bool mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { … } /* * This function checks if dynamic WEP is enabled in driver and scanned network * is compatible with it. */ static bool mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { … } /* * This function checks if a scanned network is compatible with the driver * settings. * * WEP WPA WPA2 ad-hoc encrypt Network * enabled enabled enabled AES mode Privacy WPA WPA2 Compatible * 0 0 0 0 NONE 0 0 0 yes No security * 0 1 0 0 x 1x 1 x yes WPA (disable * HT if no AES) * 0 0 1 0 x 1x x 1 yes WPA2 (disable * HT if no AES) * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES * 1 0 0 0 NONE 1 0 0 yes Static WEP * (disable HT) * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP * * Compatibility is not matched while roaming, except for mode. */ static s32 mwifiex_is_network_compatible(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc, u32 mode) { … } /* * This function creates a channel list for the driver to scan, based * on region/band information. * * This routine is used for any scan that is not provided with a * specific channel list to scan. */ static int mwifiex_scan_create_channel_list(struct mwifiex_private *priv, const struct mwifiex_user_scan_cfg *user_scan_in, struct mwifiex_chan_scan_param_set *scan_chan_list, u8 filtered_scan) { … } /* This function creates a channel list tlv for bgscan config, based * on region/band information. */ static int mwifiex_bgscan_create_channel_list(struct mwifiex_private *priv, const struct mwifiex_bg_scan_cfg *bgscan_cfg_in, struct mwifiex_chan_scan_param_set *scan_chan_list) { … } /* This function appends rate TLV to scan config command. */ static int mwifiex_append_rate_tlv(struct mwifiex_private *priv, struct mwifiex_scan_cmd_config *scan_cfg_out, u8 radio) { … } /* * This function constructs and sends multiple scan config commands to * the firmware. * * Previous routines in the code flow have created a scan command configuration * with any requested TLVs. This function splits the channel TLV into maximum * channels supported per scan lists and sends the portion of the channel TLV, * along with the other TLVs, to the firmware. */ static int mwifiex_scan_channel_list(struct mwifiex_private *priv, u32 max_chan_per_scan, u8 filtered_scan, struct mwifiex_scan_cmd_config *scan_cfg_out, struct mwifiex_ie_types_chan_list_param_set *chan_tlv_out, struct mwifiex_chan_scan_param_set *scan_chan_list) { … } /* * This function constructs a scan command configuration structure to use * in scan commands. * * Application layer or other functions can invoke network scanning * with a scan configuration supplied in a user scan configuration structure. * This structure is used as the basis of one or many scan command configuration * commands that are sent to the command processing module and eventually to the * firmware. * * This function creates a scan command configuration structure based on the * following user supplied parameters (if present): * - SSID filter * - BSSID filter * - Number of Probes to be sent * - Channel list * * If the SSID or BSSID filter is not present, the filter is disabled/cleared. * If the number of probes is not set, adapter default setting is used. */ static void mwifiex_config_scan(struct mwifiex_private *priv, const struct mwifiex_user_scan_cfg *user_scan_in, struct mwifiex_scan_cmd_config *scan_cfg_out, struct mwifiex_ie_types_chan_list_param_set **chan_list_out, struct mwifiex_chan_scan_param_set *scan_chan_list, u8 *max_chan_per_scan, u8 *filtered_scan, u8 *scan_current_only) { … } /* * This function inspects the scan response buffer for pointers to * expected TLVs. * * TLVs can be included at the end of the scan response BSS information. * * Data in the buffer is parsed pointers to TLVs that can potentially * be passed back in the response. */ static void mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter, struct mwifiex_ie_types_data *tlv, u32 tlv_buf_size, u32 req_tlv_type, struct mwifiex_ie_types_data **tlv_data) { … } /* * This function parses provided beacon buffer and updates * respective fields in bss descriptor structure. */ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, struct mwifiex_bssdescriptor *bss_entry) { … } /* * This function converts radio type scan parameter to a band configuration * to be used in join command. */ static u8 mwifiex_radio_type_to_band(u8 radio_type) { … } /* * This is an internal function used to start a scan based on an input * configuration. * * This uses the input user scan configuration information when provided in * order to send the appropriate scan commands to firmware to populate or * update the internal driver scan table. */ int mwifiex_scan_networks(struct mwifiex_private *priv, const struct mwifiex_user_scan_cfg *user_scan_in) { … } /* * This function prepares a scan command to be sent to the firmware. * * This uses the scan command configuration sent to the command processing * module in command preparation stage to configure a scan command structure * to send to firmware. * * The fixed fields specifying the BSS type and BSSID filters as well as a * variable number/length of TLVs are sent in the command to firmware. * * Preparation also includes - * - Setting command ID, and proper size * - Ensuring correct endian-ness */ int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, struct mwifiex_scan_cmd_config *scan_cfg) { … } /* * This function checks compatibility of requested network with current * driver settings. */ int mwifiex_check_network_compatibility(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { … } /* This function checks if SSID string contains all zeroes or length is zero */ static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid) { … } /* This function checks if any hidden SSID found in passive scan channels * and save those channels for specific SSID active scan */ static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv, struct cfg80211_bss *bss) { … } static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv, struct cfg80211_bss *bss) { … } static int mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info, u32 *bytes_left, u64 fw_tsf, u8 *radio_type, bool ext_scan, s32 rssi_val) { … } static void mwifiex_complete_scan(struct mwifiex_private *priv) { … } /* This function checks if any hidden SSID found in passive scan channels * and do specific SSID active scan for those channels */ static int mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv) { … } static void mwifiex_check_next_scan_command(struct mwifiex_private *priv) { … } void mwifiex_cancel_scan(struct mwifiex_adapter *adapter) { … } /* * This function handles the command response of scan. * * The response buffer for the scan command has the following * memory layout: * * .-------------------------------------------------------------. * | Header (4 * sizeof(t_u16)): Standard command response hdr | * .-------------------------------------------------------------. * | BufSize (t_u16) : sizeof the BSS Description data | * .-------------------------------------------------------------. * | NumOfSet (t_u8) : Number of BSS Descs returned | * .-------------------------------------------------------------. * | BSSDescription data (variable, size given in BufSize) | * .-------------------------------------------------------------. * | TLV data (variable, size calculated using Header->Size, | * | BufSize and sizeof the fixed fields above) | * .-------------------------------------------------------------. */ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, struct host_cmd_ds_command *resp) { … } /* * This function prepares an extended scan command to be sent to the firmware * * This uses the scan command configuration sent to the command processing * module in command preparation stage to configure a extended scan command * structure to send to firmware. */ int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, void *data_buf) { … } /* This function prepares an background scan config command to be sent * to the firmware */ int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, void *data_buf) { … } int mwifiex_stop_bg_scan(struct mwifiex_private *priv) { … } static void mwifiex_update_chan_statistics(struct mwifiex_private *priv, struct mwifiex_ietypes_chanstats *tlv_stat) { … } /* This function handles the command response of extended scan */ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv, struct host_cmd_ds_command *resp) { … } /* This function This function handles the event extended scan report. It * parses extended scan results and informs to cfg80211 stack. */ int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, void *buf) { … } /* * This function prepares command for background scan query. * * Preparation includes - * - Setting command ID and proper size * - Setting background scan flush parameter * - Ensuring correct endian-ness */ int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd) { … } /* * This function inserts scan command node to the scan pending queue. */ void mwifiex_queue_scan_cmd(struct mwifiex_private *priv, struct cmd_ctrl_node *cmd_node) { … } /* * This function sends a scan command for all available channels to the * firmware, filtered on a specific SSID. */ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, struct cfg80211_ssid *req_ssid) { … } /* * Sends IOCTL request to start a scan. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler. * * Scan command can be issued for both normal scan and specific SSID * scan, depending upon whether an SSID is provided or not. */ int mwifiex_request_scan(struct mwifiex_private *priv, struct cfg80211_ssid *req_ssid) { … } /* * This function appends the vendor specific IE TLV to a buffer. */ int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask, u8 **buffer) { … } /* * This function saves a beacon buffer of the current BSS descriptor. * * The current beacon buffer is saved so that it can be restored in the * following cases that makes the beacon buffer not to contain the current * ssid's beacon buffer. * - The current ssid was not found somehow in the last scan. * - The current ssid was the last entry of the scan table and overloaded. */ void mwifiex_save_curr_bcn(struct mwifiex_private *priv) { … } /* * This function frees the current BSS descriptor beacon buffer. */ void mwifiex_free_curr_bcn(struct mwifiex_private *priv) { … }