⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scan.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	struct ieeetypes_ibssparamset *pibss;	DECLARE_MAC_BUF(mac);	struct ieeetypes_countryinfoset *pcountryinfo;	u8 *pos, *end, *p;	u8 n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;	u16 beaconsize = 0;	int ret;	lbs_deb_enter(LBS_DEB_SCAN);	if (*bytesleft >= sizeof(beaconsize)) {		/* Extract & convert beacon size from the command buffer */		beaconsize = le16_to_cpu(get_unaligned((u16 *)*pbeaconinfo));		*bytesleft -= sizeof(beaconsize);		*pbeaconinfo += sizeof(beaconsize);	}	if (beaconsize == 0 || beaconsize > *bytesleft) {		*pbeaconinfo += *bytesleft;		*bytesleft = 0;		ret = -1;		goto done;	}	/* Initialize the current working beacon pointer for this BSS iteration */	pos = *pbeaconinfo;	end = pos + beaconsize;	/* Advance the return beacon pointer past the current beacon */	*pbeaconinfo += beaconsize;	*bytesleft -= beaconsize;	memcpy(bss->bssid, pos, ETH_ALEN);	lbs_deb_scan("process_bss: AP BSSID %s\n", print_mac(mac, bss->bssid));	pos += ETH_ALEN;	if ((end - pos) < 12) {		lbs_deb_scan("process_bss: Not enough bytes left\n");		ret = -1;		goto done;	}	/*	 * next 4 fields are RSSI, time stamp, beacon interval,	 *   and capability information	 */	/* RSSI is 1 byte long */	bss->rssi = *pos;	lbs_deb_scan("process_bss: RSSI=%02X\n", *pos);	pos++;	/* time stamp is 8 bytes long */	pos += 8;	/* beacon interval is 2 bytes long */	bss->beaconperiod = le16_to_cpup((void *) pos);	pos += 2;	/* capability information is 2 bytes long */	bss->capability = le16_to_cpup((void *) pos);	lbs_deb_scan("process_bss: capabilities = 0x%4X\n", bss->capability);	pos += 2;	if (bss->capability & WLAN_CAPABILITY_PRIVACY)		lbs_deb_scan("process_bss: AP WEP enabled\n");	if (bss->capability & WLAN_CAPABILITY_IBSS)		bss->mode = IW_MODE_ADHOC;	else		bss->mode = IW_MODE_INFRA;	/* rest of the current buffer are IE's */	lbs_deb_scan("process_bss: IE length for this AP = %zd\n", end - pos);	lbs_deb_hex(LBS_DEB_SCAN, "process_bss: IE info", pos, end - pos);	/* process variable IE */	while (pos <= end - 2) {		struct ieee80211_info_element * elem =			(struct ieee80211_info_element *) pos;		if (pos + elem->len > end) {			lbs_deb_scan("process_bss: error in processing IE, "			       "bytes left < IE length\n");			break;		}		switch (elem->id) {		case MFIE_TYPE_SSID:			bss->ssid_len = elem->len;			memcpy(bss->ssid, elem->data, elem->len);			lbs_deb_scan("ssid '%s', ssid length %u\n",			             escape_essid(bss->ssid, bss->ssid_len),			             bss->ssid_len);			break;		case MFIE_TYPE_RATES:			n_basic_rates = min_t(u8, MAX_RATES, elem->len);			memcpy(bss->rates, elem->data, n_basic_rates);			got_basic_rates = 1;			break;		case MFIE_TYPE_FH_SET:			pFH = (struct ieeetypes_fhparamset *) pos;			memmove(&bss->phyparamset.fhparamset, pFH,				sizeof(struct ieeetypes_fhparamset));#if 0 /* I think we can store these LE */			bss->phyparamset.fhparamset.dwelltime			    = le16_to_cpu(bss->phyparamset.fhparamset.dwelltime);#endif			break;		case MFIE_TYPE_DS_SET:			pDS = (struct ieeetypes_dsparamset *) pos;			bss->channel = pDS->currentchan;			memcpy(&bss->phyparamset.dsparamset, pDS,			       sizeof(struct ieeetypes_dsparamset));			break;		case MFIE_TYPE_CF_SET:			pCF = (struct ieeetypes_cfparamset *) pos;			memcpy(&bss->ssparamset.cfparamset, pCF,			       sizeof(struct ieeetypes_cfparamset));			break;		case MFIE_TYPE_IBSS_SET:			pibss = (struct ieeetypes_ibssparamset *) pos;			bss->atimwindow = le32_to_cpu(pibss->atimwindow);			memmove(&bss->ssparamset.ibssparamset, pibss,				sizeof(struct ieeetypes_ibssparamset));#if 0			bss->ssparamset.ibssparamset.atimwindow			    = le16_to_cpu(bss->ssparamset.ibssparamset.atimwindow);#endif			break;		case MFIE_TYPE_COUNTRY:			pcountryinfo = (struct ieeetypes_countryinfoset *) pos;			if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)			    || pcountryinfo->len > 254) {				lbs_deb_scan("process_bss: 11D- Err "				       "CountryInfo len =%d min=%zd max=254\n",				       pcountryinfo->len,				       sizeof(pcountryinfo->countrycode));				ret = -1;				goto done;			}			memcpy(&bss->countryinfo,			       pcountryinfo, pcountryinfo->len + 2);			lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo",				(u8 *) pcountryinfo,				(u32) (pcountryinfo->len + 2));			break;		case MFIE_TYPE_RATES_EX:			/* only process extended supported rate if data rate is			 * already found. Data rate IE should come before			 * extended supported rate IE			 */			if (!got_basic_rates)				break;			n_ex_rates = elem->len;			if (n_basic_rates + n_ex_rates > MAX_RATES)				n_ex_rates = MAX_RATES - n_basic_rates;			p = bss->rates + n_basic_rates;			memcpy(p, elem->data, n_ex_rates);			break;		case MFIE_TYPE_GENERIC:			if (elem->len >= 4 &&			    elem->data[0] == 0x00 &&			    elem->data[1] == 0x50 &&			    elem->data[2] == 0xf2 &&			    elem->data[3] == 0x01) {				bss->wpa_ie_len = min(elem->len + 2,				                      MAX_WPA_IE_LEN);				memcpy(bss->wpa_ie, elem, bss->wpa_ie_len);				lbs_deb_hex(LBS_DEB_SCAN, "process_bss: WPA IE", bss->wpa_ie,				            elem->len);			} else if (elem->len >= MARVELL_MESH_IE_LENGTH &&			    elem->data[0] == 0x00 &&			    elem->data[1] == 0x50 &&			    elem->data[2] == 0x43 &&			    elem->data[3] == 0x04) {				bss->mesh = 1;			}			break;		case MFIE_TYPE_RSN:			bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);			memcpy(bss->rsn_ie, elem, bss->rsn_ie_len);			lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", bss->rsn_ie, elem->len);			break;		default:			break;		}		pos += elem->len + 2;	}	/* Timestamp */	bss->last_scanned = jiffies;	libertas_unset_basic_rate_flags(bss->rates, sizeof(bss->rates));	ret = 0;done:	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);	return ret;}/** *  @brief This function finds a specific compatible BSSID in the scan list * *  Used in association code * *  @param adapter  A pointer to wlan_adapter *  @param bssid    BSSID to find in the scan list *  @param mode     Network mode: Infrastructure or IBSS * *  @return         index in BSSID list, or error return code (< 0) */struct bss_descriptor *libertas_find_bssid_in_list(wlan_adapter * adapter,		u8 * bssid, u8 mode){	struct bss_descriptor * iter_bss;	struct bss_descriptor * found_bss = NULL;	lbs_deb_enter(LBS_DEB_SCAN);	if (!bssid)		goto out;	lbs_deb_hex(LBS_DEB_SCAN, "looking for",		bssid, ETH_ALEN);	/* Look through the scan table for a compatible match.  The loop will	 *   continue past a matched bssid that is not compatible in case there	 *   is an AP with multiple SSIDs assigned to the same BSSID	 */	mutex_lock(&adapter->lock);	list_for_each_entry (iter_bss, &adapter->network_list, list) {		if (compare_ether_addr(iter_bss->bssid, bssid))			continue; /* bssid doesn't match */		switch (mode) {		case IW_MODE_INFRA:		case IW_MODE_ADHOC:			if (!is_network_compatible(adapter, iter_bss, mode))				break;			found_bss = iter_bss;			break;		default:			found_bss = iter_bss;			break;		}	}	mutex_unlock(&adapter->lock);out:	lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);	return found_bss;}/** *  @brief This function finds ssid in ssid list. * *  Used in association code * *  @param adapter  A pointer to wlan_adapter *  @param ssid     SSID to find in the list *  @param bssid    BSSID to qualify the SSID selection (if provided) *  @param mode     Network mode: Infrastructure or IBSS * *  @return         index in BSSID list */struct bss_descriptor * libertas_find_ssid_in_list(wlan_adapter * adapter,		   u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode,		   int channel){	u8 bestrssi = 0;	struct bss_descriptor * iter_bss = NULL;	struct bss_descriptor * found_bss = NULL;	struct bss_descriptor * tmp_oldest = NULL;	lbs_deb_enter(LBS_DEB_SCAN);	mutex_lock(&adapter->lock);	list_for_each_entry (iter_bss, &adapter->network_list, list) {		if (   !tmp_oldest		    || (iter_bss->last_scanned < tmp_oldest->last_scanned))			tmp_oldest = iter_bss;		if (libertas_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,		                      ssid, ssid_len) != 0)			continue; /* ssid doesn't match */		if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)			continue; /* bssid doesn't match */		if ((channel > 0) && (iter_bss->channel != channel))			continue; /* channel doesn't match */		switch (mode) {		case IW_MODE_INFRA:		case IW_MODE_ADHOC:			if (!is_network_compatible(adapter, iter_bss, mode))				break;			if (bssid) {				/* Found requested BSSID */				found_bss = iter_bss;				goto out;			}			if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {				bestrssi = SCAN_RSSI(iter_bss->rssi);				found_bss = iter_bss;			}			break;		case IW_MODE_AUTO:		default:			if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {				bestrssi = SCAN_RSSI(iter_bss->rssi);				found_bss = iter_bss;			}			break;		}	}out:	mutex_unlock(&adapter->lock);	lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);	return found_bss;}/** *  @brief This function finds the best SSID in the Scan List * *  Search the scan table for the best SSID that also matches the current *   adapter network preference (infrastructure or adhoc) * *  @param adapter  A pointer to wlan_adapter * *  @return         index in BSSID list */static struct bss_descriptor * libertas_find_best_ssid_in_list(wlan_adapter * adapter,		u8 mode){	u8 bestrssi = 0;	struct bss_descriptor * iter_bss;	struct bss_descriptor * best_bss = NULL;	lbs_deb_enter(LBS_DEB_SCAN);	mutex_lock(&adapter->lock);	list_for_each_entry (iter_bss, &adapter->network_list, list) {		switch (mode) {		case IW_MODE_INFRA:		case IW_MODE_ADHOC:			if (!is_network_compatible(adapter, iter_bss, mode))				break;			if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)				break;			bestrssi = SCAN_RSSI(iter_bss->rssi);			best_bss = iter_bss;			break;		case IW_MODE_AUTO:		default:			if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)				break;			bestrssi = SCAN_RSSI(iter_bss->rssi);			best_bss = iter_bss;			break;		}	}	mutex_unlock(&adapter->lock);	lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);	return best_bss;}/** *  @brief Find the AP with specific ssid in the scan list * *  Used from association worker. * *  @param priv         A pointer to wlan_private structure *  @param pSSID        A pointer to AP's ssid * *  @return             0--success, otherwise--fail */int libertas_find_best_network_ssid(wlan_private * priv,		u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode){	wlan_adapter *adapter = priv->adapter;	int ret = -1;	struct bss_descriptor * found;	lbs_deb_enter(LBS_DEB_SCAN);	wlan_scan_networks(priv, NULL, 1);	if (adapter->surpriseremoved)		goto out;	wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending);	found = libertas_find_best_ssid_in_list(adapter, preferred_mode);	if (found && (found->ssid_len > 0)) {		memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);		*out_ssid_len = found->ssid_len;		*out_mode = found->mode;		ret = 0;	}out:	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);	return ret;}/** *  @brief Scan Network * *  @param dev          A pointer to net_device structure *  @param info         A pointer to iw_request_info structure *  @param vwrq         A pointer to iw_param structure *  @param extra        A pointer to extra data buf * *  @return             0 --success, otherwise fail */int libertas_set_scan(struct net_device *dev, struct iw_request_info *info,		  struct iw_param *vwrq, char *extra){	wlan_private *priv = dev->priv;	wlan_adapter *adapter = priv->adapter;	lbs_deb_enter(LBS_DEB_SCAN);	if (!delayed_work_pending(&priv->scan_work)) {		queue_delayed_work(priv->work_thread, &priv->scan_work,		                   msecs_to_jiffies(50));	}	if (adapter->surpriseremoved)		return -1;	lbs_deb_leave(LBS_DEB_SCAN);	return 0;}/** *  @brief Send a scan command for all available channels filtered on a spec * *  Used in association code and from debugfs * *  @param priv             A pointer to wlan_private structure *  @param ssid             A pointer to the SSID to scan for *  @param ssid_len         Length of the SSID *  @param clear_ssid       Should existing scan results with this SSID *                          be cleared? *  @param prequestedssid   A pointer to AP's ssid *  @param keeppreviousscan Flag used to save/clear scan table before scan * *  @return                0-success, otherwise fail */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -