diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 9f25432be7e3..e17950ca5277 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -268,17 +268,42 @@ static void hdd_get_band_helper(struct hdd_context *hdd_ctx, int *ui_band) } } +/** + * hdd_check_and_fill_freq() - to validate chan and convert into freq + * @in_chan: input as channel number or freq to be checked + * @freq: frequency for input in_chan (output parameter) + * + * This function checks input "in_chan" is channel number, if yes then fills + * appropriate frequency into "freq" out param. If the "in_param" is greater + * than WNI_CFG_CURRENT_CHANNEL_STAMAX then checks for valid frequencies. + * + * Return: true if "in_chan" is valid channel/frequency; false otherwise + */ +static bool hdd_check_and_fill_freq(uint32_t in_chan, qdf_freq_t *freq) +{ + if (in_chan <= WNI_CFG_CURRENT_CHANNEL_STAMAX) + *freq = wlan_chan_to_freq(in_chan); + else if (WLAN_REG_IS_24GHZ_CH_FREQ(in_chan) || + WLAN_REG_IS_5GHZ_CH_FREQ(in_chan) || + WLAN_REG_IS_6GHZ_CHAN_FREQ(in_chan)) + *freq = in_chan; + else + return false; + + return true; +} + /** * _hdd_parse_bssid_and_chan() - helper function to parse bssid and channel * @data: input data * @target_ap_bssid: pointer to bssid (output parameter) - * @channel: pointer to channel (output parameter) + * @freq: pointer to freq (output parameter) * * Return: 0 if parsing is successful; -EINVAL otherwise */ static int _hdd_parse_bssid_and_chan(const uint8_t **data, uint8_t *bssid, - uint8_t *channel) + qdf_freq_t *freq) { const uint8_t *in_ptr; int v = 0; @@ -343,17 +368,17 @@ static int _hdd_parse_bssid_and_chan(const uint8_t **data, if ('\0' == *in_ptr) goto error; - /* get the next argument ie the channel number */ + /* get the next argument ie the channel/freq number */ v = sscanf(in_ptr, "%31s ", temp_buf); if (1 != v) goto error; v = kstrtos32(temp_buf, 10, &temp_int); - if ((v < 0) || (temp_int < 0) || - (temp_int > WNI_CFG_CURRENT_CHANNEL_STAMAX)) - return -EINVAL; + if (v < 0 || temp_int < 0) + goto error; + else if (!hdd_check_and_fill_freq(temp_int, freq)) + goto error; - *channel = temp_int; *data = in_ptr; return 0; error: @@ -362,7 +387,7 @@ error: } /** - * hdd_parse_send_action_frame_data() - HDD Parse send action frame data + * hdd_parse_send_action_frame_v1_data() - HDD Parse send action frame data * @command: Pointer to input data * @bssid: Pointer to target Ap bssid * @channel: Pointer to the Target AP channel @@ -372,14 +397,15 @@ error: * @buf_len: Pointer to data length * * This function parses the send action frame data passed in the format - * SENDACTIONFRAME + * SENDACTIONFRAME + * * * Return: 0 for success non-zero for failure */ static int hdd_parse_send_action_frame_v1_data(const uint8_t *command, uint8_t *bssid, - uint8_t *channel, uint8_t *dwell_time, + qdf_freq_t *freq, uint8_t *dwell_time, uint8_t **buf, uint8_t *buf_len) { const uint8_t *in_ptr = command; @@ -391,7 +417,7 @@ hdd_parse_send_action_frame_v1_data(const uint8_t *command, uint8_t temp_buf[32]; uint8_t temp_u8 = 0; - if (_hdd_parse_bssid_and_chan(&in_ptr, bssid, channel)) + if (_hdd_parse_bssid_and_chan(&in_ptr, bssid, freq)) return -EINVAL; /* point to the next argument */ @@ -478,20 +504,20 @@ hdd_parse_send_action_frame_v1_data(const uint8_t *command, * hdd_parse_reassoc_command_data() - HDD Parse reassoc command data * @command: Pointer to input data (its a NULL terminated string) * @bssid: Pointer to target Ap bssid - * @channel: Pointer to the Target AP channel + * @freq: Pointer to the Target AP frequency * * This function parses the reasoc command data passed in the format - * REASSOC + * REASSOC * * Return: 0 for success non-zero for failure */ static int hdd_parse_reassoc_command_v1_data(const uint8_t *command, uint8_t *bssid, - uint8_t *channel) + qdf_freq_t *freq) { const uint8_t *in_ptr = command; - if (_hdd_parse_bssid_and_chan(&in_ptr, bssid, channel)) + if (_hdd_parse_bssid_and_chan(&in_ptr, bssid, freq)) return -EINVAL; return 0; @@ -633,28 +659,28 @@ exit: * * This function parses the v1 REASSOC command with the format * - * REASSOC xx:xx:xx:xx:xx:xx CH + * REASSOC xx:xx:xx:xx:xx:xx CH/FREQ * * Where "xx:xx:xx:xx:xx:xx" is the Hex-ASCII representation of the - * BSSID and CH is the ASCII representation of the channel. For - * example + * BSSID and CH/FREQ is the ASCII representation of the channel/frequency. + * For example * * REASSOC 00:0a:0b:11:22:33 48 + * REASSOC 00:0a:0b:11:22:33 2412 * * Return: 0 for success non-zero for failure */ static int hdd_parse_reassoc_v1(struct hdd_adapter *adapter, const char *command) { - uint8_t channel = 0; + qdf_freq_t freq = 0; tSirMacAddr bssid; int ret; - ret = hdd_parse_reassoc_command_v1_data(command, bssid, &channel); + ret = hdd_parse_reassoc_command_v1_data(command, bssid, &freq); if (ret) hdd_err("Failed to parse reassoc command data"); else - ret = hdd_reassoc(adapter, bssid, - wlan_chan_to_freq(channel), REASSOC); + ret = hdd_reassoc(adapter, bssid, freq, REASSOC); return ret; } @@ -678,6 +704,7 @@ static int hdd_parse_reassoc_v2(struct hdd_adapter *adapter, { struct android_wifi_reassoc_params params; tSirMacAddr bssid; + qdf_freq_t freq = 0; int ret; if (total_len < sizeof(params) + 8) { @@ -692,9 +719,18 @@ static int hdd_parse_reassoc_v2(struct hdd_adapter *adapter, hdd_err("MAC address parsing failed"); ret = -EINVAL; } else { - ret = hdd_reassoc(adapter, bssid, - wlan_chan_to_freq(params.channel), REASSOC); + /* + * In Reassoc command, user can send channel number or frequency + * along with BSSID. If params.channel param of REASSOC command + * is less than WNI_CFG_CURRENT_CHANNEL_STAMAX, then host + * consider this as channel number else frequency. + */ + if (!hdd_check_and_fill_freq(params.channel, &freq)) + return -EINVAL; + + ret = hdd_reassoc(adapter, bssid, freq, REASSOC); } + return ret; } @@ -720,7 +756,7 @@ static int hdd_parse_reassoc(struct hdd_adapter *adapter, const char *command, /* both versions start with "REASSOC " * v1 has a bssid and channel # as an ASCII string - * REASSOC xx:xx:xx:xx:xx:xx CH + * REASSOC xx:xx:xx:xx:xx:xx CH/FREQ * v2 has a C struct * REASSOC * @@ -762,7 +798,7 @@ void hdd_abort_roam_scan(struct hdd_context *hdd_ctx, uint8_t vdev_id) * hdd_sendactionframe() - send a userspace-supplied action frame * @adapter: Adapter upon which the command was received * @bssid: BSSID target of the action frame - * @channel: Channel upon which to send the frame + * @freq: Frequency upon which to send the frame * @dwell_time: Amount of time to dwell when the frame is sent * @payload_len:Length of the payload * @payload: Payload of the frame @@ -773,11 +809,10 @@ void hdd_abort_roam_scan(struct hdd_context *hdd_ctx, uint8_t vdev_id) */ static int hdd_sendactionframe(struct hdd_adapter *adapter, const uint8_t *bssid, - const uint8_t channel, const uint8_t dwell_time, + const qdf_freq_t freq, const uint8_t dwell_time, const int payload_len, const uint8_t *payload) { struct ieee80211_channel chan; - uint8_t conn_info_channel; int frame_len, ret = 0; uint8_t *frame; struct ieee80211_hdr_3addr *hdr; @@ -823,25 +858,22 @@ hdd_sendactionframe(struct hdd_adapter *adapter, const uint8_t *bssid, goto exit; } - chan.center_freq = sme_chn_to_freq(channel); + chan.center_freq = freq; /* Check if it is specific action frame */ if (vendor->category == SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY) { static const uint8_t oui[] = { 0x00, 0x00, 0xf0 }; if (!qdf_mem_cmp(vendor->Oui, oui, 3)) { - conn_info_channel = wlan_reg_freq_to_chan( - hdd_ctx->pdev, - sta_ctx->conn_info.chan_freq); /* - * if the channel number is different from operating - * channel then no need to send action frame + * if the freq number is different from operating + * freq then no need to send action frame */ - if (channel != 0) { - if (channel != conn_info_channel) { - hdd_warn("channel(%u) is different from operating channel(%u)", - channel, - conn_info_channel); + if (freq) { + if (freq != sta_ctx->conn_info.chan_freq) { + hdd_warn("freq(%u) is different from operating freq(%u)", + freq, + sta_ctx->conn_info.chan_freq); ret = -EINVAL; goto exit; } @@ -856,7 +888,7 @@ hdd_sendactionframe(struct hdd_adapter *adapter, const uint8_t *bssid, hdd_abort_roam_scan(hdd_ctx, adapter->vdev_id); } else { /* - * 0 is accepted as current home channel, + * 0 is accepted as current home frequency, * delayed transmission of action frame is ok. */ chan.center_freq = sta_ctx->conn_info.chan_freq; @@ -864,7 +896,7 @@ hdd_sendactionframe(struct hdd_adapter *adapter, const uint8_t *bssid, } } if (chan.center_freq == 0) { - hdd_err("Invalid channel number: %d", channel); + hdd_nofl_err("Invalid freq : %d", freq); ret = -EINVAL; goto exit; } @@ -930,20 +962,20 @@ exit: static int hdd_parse_sendactionframe_v1(struct hdd_adapter *adapter, const char *command) { - uint8_t channel = 0; + qdf_freq_t freq = 0; uint8_t dwell_time = 0; uint8_t payload_len = 0; uint8_t *payload = NULL; tSirMacAddr bssid; int ret; - ret = hdd_parse_send_action_frame_v1_data(command, bssid, &channel, + ret = hdd_parse_send_action_frame_v1_data(command, bssid, &freq, &dwell_time, &payload, &payload_len); if (ret) { - hdd_err("Failed to parse send action frame data"); + hdd_nofl_err("Failed to parse send action frame data"); } else { - ret = hdd_sendactionframe(adapter, bssid, channel, + ret = hdd_sendactionframe(adapter, bssid, freq, dwell_time, payload_len, payload); qdf_mem_free(payload); } @@ -972,6 +1004,7 @@ hdd_parse_sendactionframe_v2(struct hdd_adapter *adapter, tSirMacAddr bssid; int ret; int len_wo_payload = 0; + qdf_freq_t freq = 0; /* The params are located after "SENDACTIONFRAME " */ total_len -= 16; @@ -1005,8 +1038,13 @@ hdd_parse_sendactionframe_v2(struct hdd_adapter *adapter, return -EINVAL; } - ret = hdd_sendactionframe(adapter, bssid, params->channel, - params->dwell_time, params->len, params->data); + if (!hdd_check_and_fill_freq(params->channel, &freq)) { + hdd_err("Invalid channel: %d", params->channel); + return -EINVAL; + } + + ret = hdd_sendactionframe(adapter, bssid, freq, params->dwell_time, + params->len, params->data); return ret; } @@ -4302,8 +4340,7 @@ static int drv_cmd_fast_reassoc(struct hdd_adapter *adapter, { int ret = 0; uint8_t *value = command; - uint8_t channel = 0; - uint32_t ch_freq; + qdf_freq_t freq = 0; tSirMacAddr bssid; uint32_t roam_id = INVALID_ROAM_ID; tCsrRoamModifyProfileFields mod_fields; @@ -4329,7 +4366,7 @@ static int drv_cmd_fast_reassoc(struct hdd_adapter *adapter, } ret = hdd_parse_reassoc_command_v1_data(value, bssid, - &channel); + &freq); if (ret) { hdd_err("Failed to parse reassoc command data"); goto exit; @@ -4344,8 +4381,8 @@ static int drv_cmd_fast_reassoc(struct hdd_adapter *adapter, QDF_MAC_ADDR_SIZE)) { hdd_warn("Reassoc BSSID is same as currently associated AP bssid"); if (roaming_offload_enabled(hdd_ctx)) { - ch_freq = sta_ctx->conn_info.chan_freq; - hdd_wma_send_fastreassoc_cmd(adapter, bssid, ch_freq); + hdd_wma_send_fastreassoc_cmd( + adapter, bssid, sta_ctx->conn_info.chan_freq); } else { sme_get_modify_profile_fields(mac_handle, adapter->vdev_id, @@ -4356,20 +4393,19 @@ static int drv_cmd_fast_reassoc(struct hdd_adapter *adapter, return 0; } - /* Check channel number is a valid channel number */ - if (channel && (QDF_STATUS_SUCCESS != - wlan_hdd_validate_operation_channel(adapter, channel))) { - hdd_err("Invalid Channel [%d]", channel); + /* Check freq number is a valid freq number */ + if (freq && QDF_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(adapter, freq)) { + hdd_err("Invalid freq [%d]", freq); return -EINVAL; } - ch_freq = wlan_reg_chan_to_freq(hdd_ctx->pdev, channel); if (roaming_offload_enabled(hdd_ctx)) { - hdd_wma_send_fastreassoc_cmd(adapter, bssid, ch_freq); + hdd_wma_send_fastreassoc_cmd(adapter, bssid, freq); goto exit; } /* Proceed with reassoc */ - req.ch_freq = ch_freq; + req.ch_freq = freq; req.src = FASTREASSOC; qdf_mem_copy(req.bssid.bytes, bssid, sizeof(tSirMacAddr)); sme_handoff_request(mac_handle, adapter->vdev_id, &req);