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

📄 scan.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
int libertas_send_specific_ssid_scan(wlan_private * priv,			u8 *ssid, u8 ssid_len, u8 clear_ssid){	wlan_adapter *adapter = priv->adapter;	struct wlan_ioctl_user_scan_cfg scancfg;	int ret = 0;	lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d",		escape_essid(ssid, ssid_len), clear_ssid);	if (!ssid_len)		goto out;	memset(&scancfg, 0x00, sizeof(scancfg));	memcpy(scancfg.ssid, ssid, ssid_len);	scancfg.ssid_len = ssid_len;	scancfg.clear_ssid = clear_ssid;	wlan_scan_networks(priv, &scancfg, 1);	if (adapter->surpriseremoved) {		ret = -1;		goto out;	}	wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending);out:	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);	return ret;}/*********************************************************************//*                                                                   *//*  Support for Wireless Extensions                                  *//*                                                                   *//*********************************************************************/#define MAX_CUSTOM_LEN 64static inline char *libertas_translate_scan(wlan_private *priv,					char *start, char *stop,					struct bss_descriptor *bss){	wlan_adapter *adapter = priv->adapter;	struct chan_freq_power *cfp;	char *current_val;	/* For rates */	struct iw_event iwe;	/* Temporary buffer */	int j;#define PERFECT_RSSI ((u8)50)#define WORST_RSSI   ((u8)0)#define RSSI_DIFF    ((u8)(PERFECT_RSSI - WORST_RSSI))	u8 rssi;	lbs_deb_enter(LBS_DEB_SCAN);	cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, bss->channel);	if (!cfp) {		lbs_deb_scan("Invalid channel number %d\n", bss->channel);		start = NULL;		goto out;	}	/* First entry *MUST* be the AP BSSID */	iwe.cmd = SIOCGIWAP;	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;	memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN);	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);	/* SSID */	iwe.cmd = SIOCGIWESSID;	iwe.u.data.flags = 1;	iwe.u.data.length = min((u32) bss->ssid_len, (u32) IW_ESSID_MAX_SIZE);	start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);	/* Mode */	iwe.cmd = SIOCGIWMODE;	iwe.u.mode = bss->mode;	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);	/* Frequency */	iwe.cmd = SIOCGIWFREQ;	iwe.u.freq.m = (long)cfp->freq * 100000;	iwe.u.freq.e = 1;	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);	/* Add quality statistics */	iwe.cmd = IWEVQUAL;	iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;	iwe.u.qual.level = SCAN_RSSI(bss->rssi);	rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;	iwe.u.qual.qual =	    (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *	     (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /	    (RSSI_DIFF * RSSI_DIFF);	if (iwe.u.qual.qual > 100)		iwe.u.qual.qual = 100;	if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {		iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;	} else {		iwe.u.qual.noise =		    CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]);	}	/* Locally created ad-hoc BSSs won't have beacons if this is the	 * only station in the adhoc network; so get signal strength	 * from receive statistics.	 */	if ((adapter->mode == IW_MODE_ADHOC)	    && adapter->adhoccreate	    && !libertas_ssid_cmp(adapter->curbssparams.ssid,	                          adapter->curbssparams.ssid_len,	                          bss->ssid, bss->ssid_len)) {		int snr, nf;		snr = adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;		nf = adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;		iwe.u.qual.level = CAL_RSSI(snr, nf);	}	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);	/* Add encryption capability */	iwe.cmd = SIOCGIWENCODE;	if (bss->capability & WLAN_CAPABILITY_PRIVACY) {		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;	} else {		iwe.u.data.flags = IW_ENCODE_DISABLED;	}	iwe.u.data.length = 0;	start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);	current_val = start + IW_EV_LCP_LEN;	iwe.cmd = SIOCGIWRATE;	iwe.u.bitrate.fixed = 0;	iwe.u.bitrate.disabled = 0;	iwe.u.bitrate.value = 0;	for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) {		/* Bit rate given in 500 kb/s units */		iwe.u.bitrate.value = bss->rates[j] * 500000;		current_val = iwe_stream_add_value(start, current_val,					 stop, &iwe, IW_EV_PARAM_LEN);	}	if ((bss->mode == IW_MODE_ADHOC)	    && !libertas_ssid_cmp(adapter->curbssparams.ssid,	                          adapter->curbssparams.ssid_len,	                          bss->ssid, bss->ssid_len)	    && adapter->adhoccreate) {		iwe.u.bitrate.value = 22 * 500000;		current_val = iwe_stream_add_value(start, current_val,					 stop, &iwe, IW_EV_PARAM_LEN);	}	/* Check if we added any event */	if((current_val - start) > IW_EV_LCP_LEN)		start = current_val;	memset(&iwe, 0, sizeof(iwe));	if (bss->wpa_ie_len) {		char buf[MAX_WPA_IE_LEN];		memcpy(buf, bss->wpa_ie, bss->wpa_ie_len);		iwe.cmd = IWEVGENIE;		iwe.u.data.length = bss->wpa_ie_len;		start = iwe_stream_add_point(start, stop, &iwe, buf);	}	memset(&iwe, 0, sizeof(iwe));	if (bss->rsn_ie_len) {		char buf[MAX_WPA_IE_LEN];		memcpy(buf, bss->rsn_ie, bss->rsn_ie_len);		iwe.cmd = IWEVGENIE;		iwe.u.data.length = bss->rsn_ie_len;		start = iwe_stream_add_point(start, stop, &iwe, buf);	}	if (bss->mesh) {		char custom[MAX_CUSTOM_LEN];		char *p = custom;		iwe.cmd = IWEVCUSTOM;		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),		              "mesh-type: olpc");		iwe.u.data.length = p - custom;		if (iwe.u.data.length)			start = iwe_stream_add_point(start, stop, &iwe, custom);	}out:	lbs_deb_leave_args(LBS_DEB_SCAN, "start %p", start);	return start;}/** *  @brief  Handle Retrieve scan table ioctl * *  @param dev          A pointer to net_device structure *  @param info         A pointer to iw_request_info structure *  @param dwrq         A pointer to iw_point structure *  @param extra        A pointer to extra data buf * *  @return             0 --success, otherwise fail */int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,		  struct iw_point *dwrq, char *extra){#define SCAN_ITEM_SIZE 128	wlan_private *priv = dev->priv;	wlan_adapter *adapter = priv->adapter;	int err = 0;	char *ev = extra;	char *stop = ev + dwrq->length;	struct bss_descriptor * iter_bss;	struct bss_descriptor * safe;	lbs_deb_enter(LBS_DEB_SCAN);	/* Update RSSI if current BSS is a locally created ad-hoc BSS */	if ((adapter->mode == IW_MODE_ADHOC) && adapter->adhoccreate) {		libertas_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,					CMD_OPTION_WAITFORRSP, 0, NULL);	}	mutex_lock(&adapter->lock);	list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) {		char * next_ev;		unsigned long stale_time;		if (stop - ev < SCAN_ITEM_SIZE) {			err = -E2BIG;			break;		}		/* For mesh device, list only mesh networks */		if (dev == priv->mesh_dev && !iter_bss->mesh)			continue;		/* Prune old an old scan result */		stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;		if (time_after(jiffies, stale_time)) {			list_move_tail (&iter_bss->list,			                &adapter->network_free_list);			clear_bss_descriptor(iter_bss);			continue;		}		/* Translate to WE format this entry */		next_ev = libertas_translate_scan(priv, ev, stop, iter_bss);		if (next_ev == NULL)			continue;		ev = next_ev;	}	mutex_unlock(&adapter->lock);	dwrq->length = (ev - extra);	dwrq->flags = 0;	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", err);	return err;}/*********************************************************************//*                                                                   *//*  Command execution                                                *//*                                                                   *//*********************************************************************//** *  @brief Prepare a scan command to be sent to the firmware * *  Called from libertas_prepare_and_send_command() in cmd.c * *  Sends a fixed lenght data part (specifying the BSS type and BSSID filters) *  as well as a variable number/length of TLVs to the firmware. * *  @param priv       A pointer to wlan_private structure *  @param cmd        A pointer to cmd_ds_command structure to be sent to *                    firmware with the cmd_DS_801_11_SCAN structure *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used *                    to set the fields/TLVs for the command sent to firmware * *  @return           0 or -1 */int libertas_cmd_80211_scan(wlan_private * priv,			 struct cmd_ds_command *cmd, void *pdata_buf){	struct cmd_ds_802_11_scan *pscan = &cmd->params.scan;	struct wlan_scan_cmd_config *pscancfg = pdata_buf;	lbs_deb_enter(LBS_DEB_SCAN);	/* Set fixed field variables in scan command */	pscan->bsstype = pscancfg->bsstype;	memcpy(pscan->bssid, pscancfg->bssid, ETH_ALEN);	memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen);	cmd->command = cpu_to_le16(CMD_802_11_SCAN);	/* size is equal to the sizeof(fixed portions) + the TLV len + header */	cmd->size = cpu_to_le16(sizeof(pscan->bsstype) + ETH_ALEN				+ pscancfg->tlvbufferlen + S_DS_GEN);	lbs_deb_scan("SCAN_CMD: command 0x%04x, size %d, seqnum %d\n",		     le16_to_cpu(cmd->command), le16_to_cpu(cmd->size),		     le16_to_cpu(cmd->seqnum));	lbs_deb_leave(LBS_DEB_SCAN);	return 0;}static inline int is_same_network(struct bss_descriptor *src,				  struct bss_descriptor *dst){	/* A network is only a duplicate if the channel, BSSID, and ESSID	 * all match.  We treat all <hidden> with the same BSSID and channel	 * as one network */	return ((src->ssid_len == dst->ssid_len) &&		(src->channel == dst->channel) &&		!compare_ether_addr(src->bssid, dst->bssid) &&		!memcmp(src->ssid, dst->ssid, src->ssid_len));}/** *  @brief This function handles the command response of scan * *  Called from handle_cmd_response() in cmdrespc. * *   The response buffer for the scan command has the following *      memory layout: * *     .-----------------------------------------------------------. *     |  header (4 * sizeof(u16)):  Standard command response hdr | *     .-----------------------------------------------------------. *     |  bufsize (u16) : sizeof the BSS Description data          | *     .-----------------------------------------------------------. *     |  NumOfSet (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)     | *     .-----------------------------------------------------------. * *  @param priv    A pointer to wlan_private structure *  @param resp    A pointer to cmd_ds_command * *  @return        0 or -1 */int libertas_ret_80211_scan(wlan_private * priv, struct cmd_ds_command *resp){	wlan_adapter *adapter = priv->adapter;	struct cmd_ds_802_11_scan_rsp *pscan;	struct bss_descriptor * iter_bss;	struct bss_descriptor * safe;	u8 *pbssinfo;	u16 scanrespsize;	int bytesleft;	int idx;	int tlvbufsize;	int ret;	lbs_deb_enter(LBS_DEB_SCAN);	/* Prune old entries from scan table */	list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) {		unsigned long stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;		if (time_before(jiffies, stale_time))			continue;		list_move_tail (&iter_bss->list, &adapter->network_free_list);		clear_bss_descriptor(iter_bss);	}	pscan = &resp->params.scanresp;	if (pscan->nr_sets > MAX_NETWORK_COUNT) {		lbs_deb_scan(		       "SCAN_RESP: too many scan results (%d, max %d)!!\n",		       pscan->nr_sets, MAX_NETWORK_COUNT);		ret = -1;		goto done;	}	bytesleft = le16_to_cpu(get_unaligned((u16*)&pscan->bssdescriptsize));	lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);	scanrespsize = le16_to_cpu(get_unaligned((u16*)&resp->size));	lbs_deb_scan("SCAN_RESP: returned %d AP before parsing\n",	       pscan->nr_sets);	pbssinfo = pscan->bssdesc_and_tlvbuffer;	/* The size of the TLV buffer is equal to the entire command response	 *   size (scanrespsize) minus the fixed fields (sizeof()'s), the	 *   BSS Descriptions (bssdescriptsize as bytesLef) and the command	 *   response header (S_DS_GEN)	 */	tlvbufsize = scanrespsize - (bytesleft + sizeof(pscan->bssdescriptsize)				     + sizeof(pscan->nr_sets)				     + S_DS_GEN);	/*	 *  Process each scan response returned (pscan->nr_sets).  Save	 *    the information in the newbssentry and then insert into the	 *    driver scan table either as an update to an existing entry	 *    or as an addition at the end of the table	 */	for (idx = 0; idx < pscan->nr_sets && bytesleft; idx++) {		struct bss_descriptor new;		struct bss_descriptor * found = NULL;		struct bss_descriptor * oldest = NULL;		DECLARE_MAC_BUF(mac);		/* Process the data fields and IEs returned for this BSS */		memset(&new, 0, sizeof (struct bss_descriptor));		if (libertas_process_bss(&new, &pbssinfo, &bytesleft) != 0) {			/* error parsing the scan response, skipped */			lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n");			continue;		}		/* Try to find this bss in the scan table */		list_for_each_entry (iter_bss, &adapter->network_list, list) {			if (is_same_network(iter_bss, &new)) {				found = iter_bss;				break;			}			if ((oldest == NULL) ||			    (iter_bss->last_scanned < oldest->last_scanned))				oldest = iter_bss;		}		if (found) {			/* found, clear it */			clear_bss_descriptor(found);		} else if (!list_empty(&adapter->network_free_list)) {			/* Pull one from the free list */			found = list_entry(adapter->network_free_list.next,					   struct bss_descriptor, list);			list_move_tail(&found->list, &adapter->network_list);		} else if (oldest) {			/* If there are no more slots, expire the oldest */			found = oldest;			clear_bss_descriptor(found);			list_move_tail(&found->list, &adapter->network_list);		} else {			continue;		}		lbs_deb_scan("SCAN_RESP: BSSID = %s\n",			     print_mac(mac, new.bssid));		/* Copy the locally created newbssentry to the scan table */		memcpy(found, &new, offsetof(struct bss_descriptor, list));	}	ret = 0;done:	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);	return ret;}

⌨️ 快捷键说明

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