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

📄 scan.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/**  * Functions implementing wlan scan IOCTL and firmware command APIs  *  * IOCTL handlers as well as command preperation and response routines  *  for sending scan commands to the firmware.  */#include <linux/ctype.h>#include <linux/if.h>#include <linux/netdevice.h>#include <linux/wireless.h>#include <linux/etherdevice.h>#include <net/ieee80211.h>#include <net/iw_handler.h>#include <asm/unaligned.h>#include "host.h"#include "decl.h"#include "dev.h"#include "scan.h"#include "join.h"//! Approximate amount of data needed to pass a scan result back to iwlist#define MAX_SCAN_CELL_SIZE  (IW_EV_ADDR_LEN             \                             + IW_ESSID_MAX_SIZE        \                             + IW_EV_UINT_LEN           \                             + IW_EV_FREQ_LEN           \                             + IW_EV_QUAL_LEN           \                             + IW_ESSID_MAX_SIZE        \                             + IW_EV_PARAM_LEN          \                             + 40)	/* 40 for WPAIE *///! Memory needed to store a max sized channel List TLV for a firmware scan#define CHAN_TLV_MAX_SIZE  (sizeof(struct mrvlietypesheader)    \                            + (MRVDRV_MAX_CHANNELS_PER_SCAN     \                               * sizeof(struct chanscanparamset)))//! Memory needed to store a max number/size SSID TLV for a firmware scan#define SSID_TLV_MAX_SIZE  (1 * sizeof(struct mrvlietypes_ssidparamset))//! Maximum memory needed for a wlan_scan_cmd_config with all TLVs at max#define MAX_SCAN_CFG_ALLOC (sizeof(struct wlan_scan_cmd_config)  \                            + sizeof(struct mrvlietypes_numprobes)   \                            + CHAN_TLV_MAX_SIZE                 \                            + SSID_TLV_MAX_SIZE)//! The maximum number of channels the firmware can scan per command#define MRVDRV_MAX_CHANNELS_PER_SCAN   14/** * @brief Number of channels to scan per firmware scan command issuance. * *  Number restricted to prevent hitting the limit on the amount of scan data *  returned in a single firmware scan command. */#define MRVDRV_CHANNELS_PER_SCAN_CMD   4//! Scan time specified in the channel TLV for each channel for passive scans#define MRVDRV_PASSIVE_SCAN_CHAN_TIME  100//! Scan time specified in the channel TLV for each channel for active scans#define MRVDRV_ACTIVE_SCAN_CHAN_TIME   100static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };/*********************************************************************//*                                                                   *//*  Misc helper functions                                            *//*                                                                   *//*********************************************************************/static inline void clear_bss_descriptor (struct bss_descriptor * bss){	/* Don't blow away ->list, just BSS data */	memset(bss, 0, offsetof(struct bss_descriptor, list));}static inline int match_bss_no_security(struct wlan_802_11_security * secinfo,			struct bss_descriptor * match_bss){	if (   !secinfo->wep_enabled	    && !secinfo->WPAenabled	    && !secinfo->WPA2enabled	    && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC	    && match_bss->rsn_ie[0] != MFIE_TYPE_RSN	    && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {		return 1;	}	return 0;}static inline int match_bss_static_wep(struct wlan_802_11_security * secinfo,			struct bss_descriptor * match_bss){	if ( secinfo->wep_enabled	   && !secinfo->WPAenabled	   && !secinfo->WPA2enabled	   && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {		return 1;	}	return 0;}static inline int match_bss_wpa(struct wlan_802_11_security * secinfo,			struct bss_descriptor * match_bss){	if (  !secinfo->wep_enabled	   && secinfo->WPAenabled	   && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)	   /* privacy bit may NOT be set in some APs like LinkSys WRT54G	      && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {	    */	   ) {		return 1;	}	return 0;}static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo,			struct bss_descriptor * match_bss){	if (  !secinfo->wep_enabled	   && secinfo->WPA2enabled	   && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)	   /* privacy bit may NOT be set in some APs like LinkSys WRT54G	      && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {	    */	   ) {		return 1;	}	return 0;}static inline int match_bss_dynamic_wep(struct wlan_802_11_security * secinfo,			struct bss_descriptor * match_bss){	if (  !secinfo->wep_enabled	   && !secinfo->WPAenabled	   && !secinfo->WPA2enabled	   && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)	   && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)	   && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {		return 1;	}	return 0;}/** *  @brief Check if a scanned network compatible with the driver settings * *   WEP     WPA     WPA2    ad-hoc  encrypt                      Network * enabled enabled  enabled   AES     mode   privacy  WPA  WPA2  Compatible *    0       0        0       0      NONE      0      0    0   yes No security *    1       0        0       0      NONE      1      0    0   yes Static WEP *    0       1        0       0       x        1x     1    x   yes WPA *    0       0        1       0       x        1x     x    1   yes WPA2 *    0       0        0       1      NONE      1      0    0   yes Ad-hoc AES *    0       0        0       0     !=NONE     1      0    0   yes Dynamic WEP * * *  @param adapter A pointer to wlan_adapter *  @param index   Index in scantable to check against current driver settings *  @param mode    Network mode: Infrastructure or IBSS * *  @return        Index in scantable, or error code if negative */static int is_network_compatible(wlan_adapter * adapter,		struct bss_descriptor * bss, u8 mode){	int matched = 0;	lbs_deb_enter(LBS_DEB_SCAN);	if (bss->mode != mode)		goto done;	if ((matched = match_bss_no_security(&adapter->secinfo, bss))) {		goto done;	} else if ((matched = match_bss_static_wep(&adapter->secinfo, bss))) {		goto done;	} else if ((matched = match_bss_wpa(&adapter->secinfo, bss))) {		lbs_deb_scan(		       "is_network_compatible() WPA: wpa_ie=%#x "		       "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "		       "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0],		       adapter->secinfo.wep_enabled ? "e" : "d",		       adapter->secinfo.WPAenabled ? "e" : "d",		       adapter->secinfo.WPA2enabled ? "e" : "d",		       (bss->capability & WLAN_CAPABILITY_PRIVACY));		goto done;	} else if ((matched = match_bss_wpa2(&adapter->secinfo, bss))) {		lbs_deb_scan(		       "is_network_compatible() WPA2: wpa_ie=%#x "		       "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "		       "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0],		       adapter->secinfo.wep_enabled ? "e" : "d",		       adapter->secinfo.WPAenabled ? "e" : "d",		       adapter->secinfo.WPA2enabled ? "e" : "d",		       (bss->capability & WLAN_CAPABILITY_PRIVACY));		goto done;	} else if ((matched = match_bss_dynamic_wep(&adapter->secinfo, bss))) {		lbs_deb_scan(		       "is_network_compatible() dynamic WEP: "		       "wpa_ie=%#x wpa2_ie=%#x privacy=%#x\n",		       bss->wpa_ie[0], bss->rsn_ie[0],		       (bss->capability & WLAN_CAPABILITY_PRIVACY));		goto done;	}	/* bss security settings don't match those configured on card */	lbs_deb_scan(	       "is_network_compatible() FAILED: wpa_ie=%#x "	       "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s privacy=%#x\n",	       bss->wpa_ie[0], bss->rsn_ie[0],	       adapter->secinfo.wep_enabled ? "e" : "d",	       adapter->secinfo.WPAenabled ? "e" : "d",	       adapter->secinfo.WPA2enabled ? "e" : "d",	       (bss->capability & WLAN_CAPABILITY_PRIVACY));done:	lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);	return matched;}/** *  @brief Compare two SSIDs * *  @param ssid1    A pointer to ssid to compare *  @param ssid2    A pointer to ssid to compare * *  @return         0--ssid is same, otherwise is different */int libertas_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len){	if (ssid1_len != ssid2_len)		return -1;	return memcmp(ssid1, ssid2, ssid1_len);}/*********************************************************************//*                                                                   *//*  Main scanning support                                            *//*                                                                   *//*********************************************************************//** *  @brief Create a channel list for the driver to scan based on region info * *  Only used from wlan_scan_setup_scan_config() * *  Use the driver region/band information to construct a comprehensive list *    of channels to scan.  This routine is used for any scan that is not *    provided a specific channel list to scan. * *  @param priv          A pointer to wlan_private structure *  @param scanchanlist  Output parameter: resulting channel list to scan *  @param filteredscan  Flag indicating whether or not a BSSID or SSID filter *                       is being sent in the command to firmware.  Used to *                       increase the number of channels sent in a scan *                       command and to disable the firmware channel scan *                       filter. * *  @return              void */static void wlan_scan_create_channel_list(wlan_private * priv,					  struct chanscanparamset * scanchanlist,					  u8 filteredscan){	wlan_adapter *adapter = priv->adapter;	struct region_channel *scanregion;	struct chan_freq_power *cfp;	int rgnidx;	int chanidx;	int nextchan;	u8 scantype;	lbs_deb_enter_args(LBS_DEB_SCAN, "filteredscan %d", filteredscan);	chanidx = 0;	/* Set the default scan type to the user specified type, will later	 *   be changed to passive on a per channel basis if restricted by	 *   regulatory requirements (11d or 11h)	 */	scantype = CMD_SCAN_TYPE_ACTIVE;	for (rgnidx = 0; rgnidx < ARRAY_SIZE(adapter->region_channel); rgnidx++) {		if (priv->adapter->enable11d &&		    adapter->connect_status != LIBERTAS_CONNECTED) {			/* Scan all the supported chan for the first scan */			if (!adapter->universal_channel[rgnidx].valid)				continue;			scanregion = &adapter->universal_channel[rgnidx];			/* clear the parsed_region_chan for the first scan */			memset(&adapter->parsed_region_chan, 0x00,			       sizeof(adapter->parsed_region_chan));		} else {			if (!adapter->region_channel[rgnidx].valid)				continue;			scanregion = &adapter->region_channel[rgnidx];		}		for (nextchan = 0;		     nextchan < scanregion->nrcfp; nextchan++, chanidx++) {			cfp = scanregion->CFP + nextchan;			if (priv->adapter->enable11d) {				scantype =				    libertas_get_scan_type_11d(cfp->channel,							   &adapter->							   parsed_region_chan);			}			switch (scanregion->band) {			case BAND_B:			case BAND_G:			default:				scanchanlist[chanidx].radiotype =				    CMD_SCAN_RADIO_TYPE_BG;				break;			}			if (scantype == CMD_SCAN_TYPE_PASSIVE) {				scanchanlist[chanidx].maxscantime =				    cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME);				scanchanlist[chanidx].chanscanmode.passivescan =				    1;			} else {				scanchanlist[chanidx].maxscantime =				    cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME);				scanchanlist[chanidx].chanscanmode.passivescan =				    0;			}			scanchanlist[chanidx].channumber = cfp->channel;			if (filteredscan) {				scanchanlist[chanidx].chanscanmode.				    disablechanfilt = 1;			}		}	}}/* Delayed partial scan worker */void libertas_scan_worker(struct work_struct *work){	wlan_private *priv = container_of(work, wlan_private, scan_work.work);	wlan_scan_networks(priv, NULL, 0);}/** *  @brief Construct a wlan_scan_cmd_config structure to use in issue scan cmds * *  Application layer or other functions can invoke wlan_scan_networks *    with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct. *    This structure is used as the basis of one or many wlan_scan_cmd_config *    commands that are sent to the command processing module and sent to *    firmware. * *  Create a wlan_scan_cmd_config based on the following user supplied *    parameters (if present): *             - SSID filter *             - BSSID filter *             - Number of Probes to be sent *             - channel list * *  If the SSID or BSSID filter is not present, disable/clear the filter. *  If the number of probes is not set, use the adapter default setting *  Qualify the channel * *  @param priv             A pointer to wlan_private structure *  @param puserscanin      NULL or pointer to scan configuration parameters *  @param ppchantlvout     Output parameter: Pointer to the start of the *                          channel TLV portion of the output scan config *  @param pscanchanlist    Output parameter: Pointer to the resulting channel *                          list to scan *  @param pmaxchanperscan  Output parameter: Number of channels to scan for *                          each issuance of the firmware scan command *  @param pfilteredscan    Output parameter: Flag indicating whether or not *                          a BSSID or SSID filter is being sent in the *                          command to firmware.  Used to increase the number *                          of channels sent in a scan command and to *                          disable the firmware channel scan filter. *  @param pscancurrentonly Output parameter: Flag indicating whether or not *                          we are only scanning our current active channel * *  @return                 resulting scan configuration */static struct wlan_scan_cmd_config *wlan_scan_setup_scan_config(wlan_private * priv,			    const struct wlan_ioctl_user_scan_cfg * puserscanin,			    struct mrvlietypes_chanlistparamset ** ppchantlvout,			    struct chanscanparamset * pscanchanlist,			    int *pmaxchanperscan,			    u8 * pfilteredscan,			    u8 * pscancurrentonly){	struct mrvlietypes_numprobes *pnumprobestlv;	struct mrvlietypes_ssidparamset *pssidtlv;	struct wlan_scan_cmd_config * pscancfgout = NULL;	u8 *ptlvpos;	u16 numprobes;	int chanidx;	int scantype;	int scandur;	int channel;	int radiotype;	lbs_deb_enter(LBS_DEB_SCAN);	pscancfgout = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL);	if (pscancfgout == NULL)		goto out;	/* The tlvbufferlen is calculated for each scan command.  The TLVs added	 *   in this routine will be preserved since the routine that sends	 *   the command will append channelTLVs at *ppchantlvout.  The difference	 *   between the *ppchantlvout and the tlvbuffer start will be used	 *   to calculate the size of anything we add in this routine.	 */	pscancfgout->tlvbufferlen = 0;	/* Running tlv pointer.  Assigned to ppchantlvout at end of function	 *  so later routines know where channels can be added to the command buf	 */	ptlvpos = pscancfgout->tlvbuffer;	/*	 * Set the initial scan paramters for progressive scanning.  If a specific	 *   BSSID or SSID is used, the number of channels in the scan command	 *   will be increased to the absolute maximum	 */	*pmaxchanperscan = MRVDRV_CHANNELS_PER_SCAN_CMD;	/* Initialize the scan as un-filtered by firmware, set to TRUE below if	 *   a SSID or BSSID filter is sent in the command	 */	*pfilteredscan = 0;	/* Initialize the scan as not being only on the current channel.  If	 *   the channel list is customized, only contains one channel, and	 *   is the active channel, this is set true and data flow is not halted.	 */	*pscancurrentonly = 0;	if (puserscanin) {		/* Set the bss type scan filter, use adapter setting if unset */		pscancfgout->bsstype =		    puserscanin->bsstype ? puserscanin->bsstype : CMD_BSS_TYPE_ANY;		/* Set the number of probes to send, use adapter setting if unset */

⌨️ 快捷键说明

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