net/wireless/scan.c

Source file repositories/reference/linux-study-clean/net/wireless/scan.c

File Facts

System
Linux kernel
Corpus path
net/wireless/scan.c
Extension
.c
Size
107571 bytes
Lines
4024
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

struct colocated_ap_data {
	const struct element *ssid_elem;
	struct list_head ap_list;
	u32 s_ssid_tmp;
	int n_coloc;
};

static enum cfg80211_rnr_iter_ret
cfg80211_parse_colocated_ap_iter(void *_data, u8 type,
				 const struct ieee80211_neighbor_ap_info *info,
				 const u8 *tbtt_info, u8 tbtt_info_len)
{
	struct colocated_ap_data *data = _data;
	struct cfg80211_colocated_ap *entry;
	enum nl80211_band band;

	if (type != IEEE80211_TBTT_INFO_TYPE_TBTT)
		return RNR_ITER_CONTINUE;

	if (!ieee80211_operating_class_to_band(info->op_class, &band))
		return RNR_ITER_CONTINUE;

	/* TBTT info must include bss param + BSSID + (short SSID or
	 * same_ssid bit to be set). Ignore other options, and move to
	 * the next AP info
	 */
	if (band != NL80211_BAND_6GHZ ||
	    !(tbtt_info_len == offsetofend(struct ieee80211_tbtt_info_7_8_9,
					   bss_params) ||
	      tbtt_info_len == sizeof(struct ieee80211_tbtt_info_7_8_9) ||
	      tbtt_info_len >= offsetofend(struct ieee80211_tbtt_info_ge_11,
					   bss_params)))
		return RNR_ITER_CONTINUE;

	entry = kzalloc_obj(*entry, GFP_ATOMIC);
	if (!entry)
		return RNR_ITER_ERROR;

	entry->center_freq =
		ieee80211_channel_to_frequency(info->channel, band);

	if (!cfg80211_parse_ap_info(entry, tbtt_info, tbtt_info_len,
				    data->ssid_elem, data->s_ssid_tmp)) {
		struct cfg80211_colocated_ap *tmp;

		/* Don't add duplicate BSSIDs on the same channel. */
		list_for_each_entry(tmp, &data->ap_list, list) {
			if (ether_addr_equal(tmp->bssid, entry->bssid) &&
			    tmp->center_freq == entry->center_freq) {
				kfree(entry);
				return RNR_ITER_CONTINUE;
			}
		}

		data->n_coloc++;
		list_add_tail(&entry->list, &data->ap_list);
	} else {
		kfree(entry);
	}

	return RNR_ITER_CONTINUE;
}

VISIBLE_IF_CFG80211_KUNIT int
cfg80211_parse_colocated_ap(const struct cfg80211_bss_ies *ies,
			    struct list_head *list)
{
	struct colocated_ap_data data = {};
	int ret;

	INIT_LIST_HEAD(&data.ap_list);

	ret = cfg80211_calc_short_ssid(ies, &data.ssid_elem, &data.s_ssid_tmp);
	if (ret)
		return 0;

	if (!cfg80211_iter_rnr(ies->data, ies->len,
			       cfg80211_parse_colocated_ap_iter, &data)) {
		cfg80211_free_coloc_ap_list(&data.ap_list);
		return 0;
	}

	list_splice_tail(&data.ap_list, list);
	return data.n_coloc;
}
EXPORT_SYMBOL_IF_CFG80211_KUNIT(cfg80211_parse_colocated_ap);

static void cfg80211_scan_req_add_chan(struct cfg80211_scan_request *request,
				       struct ieee80211_channel *chan,
				       bool add_to_6ghz)

Annotation

Implementation Notes