diff --git a/umac/scan/core/src/wlan_scan_cache_db.c b/umac/scan/core/src/wlan_scan_cache_db.c index 9e1f4d65f7..1f703821a5 100644 --- a/umac/scan/core/src/wlan_scan_cache_db.c +++ b/umac/scan/core/src/wlan_scan_cache_db.c @@ -50,6 +50,7 @@ #include "wlan_scan_cache_db_i.h" #include "wlan_reg_services_api.h" #include "wlan_reg_ucfg_api.h" +#include /** * scm_del_scan_node() - API to remove scan node from the list @@ -747,6 +748,11 @@ QDF_STATUS scm_handle_bcn_probe(struct scheduler_msg *msg) goto free_nbuf; } + if (bcn->frm_type == MGMT_SUBTYPE_BEACON && + utils_is_dfs_ch(pdev, bcn->rx_data->channel)) { + util_scan_add_hidden_ssid(pdev, bcn->buf); + } + scan_list = util_scan_unpack_beacon_frame(pdev, qdf_nbuf_data(bcn->buf), qdf_nbuf_len(bcn->buf), bcn->frm_type, diff --git a/umac/scan/core/src/wlan_scan_main.h b/umac/scan/core/src/wlan_scan_main.h index d138799099..4a293357fb 100644 --- a/umac/scan/core/src/wlan_scan_main.h +++ b/umac/scan/core/src/wlan_scan_main.h @@ -200,11 +200,15 @@ struct scan_requester_info { * @wide_band_scan: wide band scan capability * @last_scan_time: time of last scan start on this pdev * @custom_chan_list: scan only these channels + * @conf_bssid: configured bssid of the hidden AP + * @conf_ssid: configured desired ssid */ struct pdev_scan_info { bool wide_band_scan; qdf_time_t last_scan_time; struct chan_list custom_chan_list; + uint8_t conf_bssid[QDF_MAC_ADDR_SIZE]; + struct wlan_ssid conf_ssid; }; /** diff --git a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h index 79be46a9ec..2a9b55018c 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h @@ -252,7 +252,29 @@ bool ucfg_scan_get_wide_band_scan(struct wlan_objmgr_pdev *pdev); */ QDF_STATUS ucfg_scan_set_custom_scan_chan_list( struct wlan_objmgr_pdev *pdev, struct chan_list *chan_list); - +/** + * ucfg_scan_set_ssid_bssid_hidden_ssid_beacon() - API to configure + * ssid, bssid of hidden beacon + * @pdev: psoc on which ssid bssid need to configure + * @bssid: bssid of the hidden AP + * @ssid: desired ssid + * + * Return: QDF_STATUS. + */ +#ifdef WLAN_DFS_CHAN_HIDDEN_SSID +QDF_STATUS +ucfg_scan_config_hidden_ssid_for_bssid(struct wlan_objmgr_pdev *pdev, + uint8_t *bssid, + struct wlan_ssid *ssid); +#else +static inline QDF_STATUS +ucfg_scan_config_hidden_ssid_for_bssid(struct wlan_objmgr_pdev *pdev, + uint8_t *bssid, + struct wlan_ssid *ssid) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* WLAN_DFS_CHAN_HIDDEN_SSID */ /** * ucfg_scan_cancel() - Public API to stop a scan * @req: stop scan request params diff --git a/umac/scan/dispatcher/inc/wlan_scan_utils_api.h b/umac/scan/dispatcher/inc/wlan_scan_utils_api.h index 0dbe8d3f75..d68246669f 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_utils_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_utils_api.h @@ -62,6 +62,24 @@ qdf_list_t *util_scan_unpack_beacon_frame( uint8_t *frame, qdf_size_t frame_len, uint32_t frm_subtype, struct mgmt_rx_event_params *rx_param); +/** + * util_scan_add_hidden_ssid() - func to add hidden ssid + * @pdev: pdev pointer + * @frame: beacon buf + * + * Return: + */ +#ifdef WLAN_DFS_CHAN_HIDDEN_SSID +QDF_STATUS +util_scan_add_hidden_ssid(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t bcnbuf); +#else +static inline QDF_STATUS +util_scan_add_hidden_ssid(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t bcnbuf) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* WLAN_DFS_CHAN_HIDDEN_SSID */ + /** * util_scan_get_ev_type_name() - converts enum event to printable string * @event: event of type scan_event_type diff --git a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c index fb7b45b8bd..87f66e7542 100644 --- a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c @@ -1041,6 +1041,34 @@ bool ucfg_scan_get_wide_band_scan(struct wlan_objmgr_pdev *pdev) return scan_obj->pdev_info[pdev_id].wide_band_scan; } +#ifdef WLAN_DFS_CHAN_HIDDEN_SSID +QDF_STATUS +ucfg_scan_config_hidden_ssid_for_bssid(struct wlan_objmgr_pdev *pdev, + uint8_t *bssid, struct wlan_ssid *ssid) +{ + uint8_t pdev_id; + struct wlan_scan_obj *scan_obj; + + if (!pdev) { + scm_warn("null vdev"); + return QDF_STATUS_E_NULL_VALUE; + } + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + scan_obj = wlan_pdev_get_scan_obj(pdev); + + scm_debug("Configure bsssid:%pM ssid:%.*s", + bssid, ssid->length, ssid->ssid); + qdf_mem_copy(scan_obj->pdev_info[pdev_id].conf_bssid, + bssid, QDF_MAC_ADDR_SIZE); + scan_obj->pdev_info[pdev_id].conf_ssid.length = ssid->length; + qdf_mem_copy(scan_obj->pdev_info[pdev_id].conf_ssid.ssid, + ssid->ssid, + scan_obj->pdev_info[pdev_id].conf_ssid.length); + + return QDF_STATUS_SUCCESS; +} +#endif /* WLAN_DFS_CHAN_HIDDEN_SSID */ + QDF_STATUS ucfg_scan_cancel(struct scan_cancel_request *req) { diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index bad4ec45dd..f89c61a98f 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -826,6 +826,141 @@ static int util_scan_scm_calc_nss_supported_by_ap( return 1; } +#ifdef WLAN_DFS_CHAN_HIDDEN_SSID +QDF_STATUS +util_scan_add_hidden_ssid(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t bcnbuf) +{ + struct wlan_frame_hdr *hdr; + struct wlan_bcn_frame *bcn; + struct wlan_scan_obj *scan_obj; + struct wlan_ssid *conf_ssid; + struct ie_header *ie; + uint32_t frame_len = qdf_nbuf_len(bcnbuf); + uint16_t bcn_ie_offset, ssid_ie_start_offset, ssid_ie_end_offset; + uint16_t tmplen, ie_length; + uint8_t *pbeacon, *tmp; + bool set_ssid_flag = false; + struct ie_ssid *ssid; + uint8_t pdev_id; + + if (!pdev) { + scm_warn("pdev: 0x%pK is NULL", pdev); + return QDF_STATUS_E_NULL_VALUE; + } + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + scan_obj = wlan_pdev_get_scan_obj(pdev); + + conf_ssid = &scan_obj->pdev_info[pdev_id].conf_ssid; + + hdr = (struct wlan_frame_hdr *)qdf_nbuf_data(bcnbuf); + + /* received bssid does not match configured bssid */ + if (qdf_mem_cmp(hdr->i_addr3, scan_obj->pdev_info[pdev_id].conf_bssid, + QDF_MAC_ADDR_SIZE) || + conf_ssid->length == 0) { + return QDF_STATUS_SUCCESS; + } + + bcn = (struct wlan_bcn_frame *)(qdf_nbuf_data(bcnbuf) + sizeof(*hdr)); + pbeacon = (uint8_t *)bcn; + + ie = (struct ie_header *)(pbeacon + + offsetof(struct wlan_bcn_frame, ie)); + + bcn_ie_offset = offsetof(struct wlan_bcn_frame, ie); + ie_length = (uint16_t)(frame_len - sizeof(*hdr) - + bcn_ie_offset); + + while (ie_length >= sizeof(struct ie_header)) { + ie_length -= sizeof(struct ie_header); + + bcn_ie_offset += sizeof(struct ie_header); + + if (ie_length < ie->ie_len) { + scm_debug("Incomplete corrupted IE:%x", ie->ie_id); + return QDF_STATUS_E_INVAL; + } + if (ie->ie_id == WLAN_ELEMID_SSID) { + if (ie->ie_len > (sizeof(struct ie_ssid) - + sizeof(struct ie_header))) { + return QDF_STATUS_E_INVAL; + } + ssid = (struct ie_ssid *)ie; + if (util_scan_is_hidden_ssid(ssid)) { + set_ssid_flag = true; + ssid_ie_start_offset = bcn_ie_offset - + sizeof(struct ie_header); + ssid_ie_end_offset = bcn_ie_offset + + ie->ie_len; + } + } + if (ie->ie_len == 0) { + ie += 1; /* next IE */ + continue; + } + if (ie->ie_id == WLAN_ELEMID_VENDOR && + is_wps_oui((uint8_t *)ie)) { + set_ssid_flag = false; + break; + } + /* Consume info element */ + ie_length -= ie->ie_len; + /* Go to next IE */ + ie = (struct ie_header *)(((uint8_t *)ie) + + sizeof(struct ie_header) + + ie->ie_len); + } + + if (set_ssid_flag) { + /* Hidden SSID if the Length is 0 */ + if (!ssid->ssid_len) { + /* increase the taillength by length of ssid */ + if (qdf_nbuf_put_tail(bcnbuf, + conf_ssid->length) == NULL) { + scm_debug("No enough tailroom"); + return QDF_STATUS_E_NOMEM; + } + /* length of the buffer to be copied */ + tmplen = frame_len - + sizeof(*hdr) - ssid_ie_end_offset; + /* + * tmp memory to copy the beacon info + * after ssid ie. + */ + tmp = qdf_mem_malloc(tmplen * sizeof(u_int8_t)); + if (!tmp) { + scm_debug("tmp memory alloc failed"); + return QDF_STATUS_E_NOMEM; + } + /* Copy beacon data after ssid ie to tmp */ + qdf_nbuf_copy_bits(bcnbuf, (sizeof(*hdr) + + ssid_ie_end_offset), tmplen, tmp); + /* Add ssid length */ + *(pbeacon + (ssid_ie_start_offset + 1)) + = conf_ssid->length; + /* Insert the SSID string */ + qdf_mem_copy((pbeacon + ssid_ie_end_offset), + conf_ssid->ssid, conf_ssid->length); + /* Copy rest of the beacon data */ + qdf_mem_copy((pbeacon + ssid_ie_end_offset + + conf_ssid->length), tmp, tmplen); + qdf_mem_free(tmp); + + /* Hidden ssid with all 0's */ + } else if (ssid->ssid_len == conf_ssid->length) { + /* Insert the SSID string */ + qdf_mem_copy((pbeacon + ssid_ie_start_offset + + sizeof(struct ie_header)), + conf_ssid->ssid, conf_ssid->length); + } else { + scm_debug("mismatch in hidden ssid length"); + return QDF_STATUS_E_INVAL; + } + } + return QDF_STATUS_SUCCESS; +} +#endif /* WLAN_DFS_CHAN_HIDDEN_SSID */ + qdf_list_t * util_scan_unpack_beacon_frame(struct wlan_objmgr_pdev *pdev, uint8_t *frame, qdf_size_t frame_len, uint32_t frm_subtype,