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

📄 join.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/**  *  Functions implementing wlan infrastructure and adhoc join routines,  *  IOCTL handlers as well as command preperation and response routines  *  for sending adhoc start, adhoc join, and association commands  *  to the firmware.  */#include <linux/netdevice.h>#include <linux/if_arp.h>#include <linux/wireless.h>#include <linux/etherdevice.h>#include <net/iw_handler.h>#include "host.h"#include "decl.h"#include "join.h"#include "dev.h"#include "assoc.h"/* The firmware needs certain bits masked out of the beacon-derviced capability * field when associating/joining to BSSs. */#define CAPINFO_MASK	(~(0xda00))/** *  @brief This function finds common rates between rate1 and card rates. * * It will fill common rates in rate1 as output if found. * * NOTE: Setting the MSB of the basic rates need to be taken *   care, either before or after calling this function * *  @param adapter     A pointer to wlan_adapter structure *  @param rate1       the buffer which keeps input and output *  @param rate1_size  the size of rate1 buffer; new size of buffer on return * *  @return            0 or -1 */static int get_common_rates(wlan_adapter * adapter, u8 * rates, u16 *rates_size){	u8 *card_rates = libertas_bg_rates;	size_t num_card_rates = sizeof(libertas_bg_rates);	int ret = 0, i, j;	u8 tmp[30];	size_t tmp_size = 0;	/* For each rate in card_rates that exists in rate1, copy to tmp */	for (i = 0; card_rates[i] && (i < num_card_rates); i++) {		for (j = 0; rates[j] && (j < *rates_size); j++) {			if (rates[j] == card_rates[i])				tmp[tmp_size++] = card_rates[i];		}	}	lbs_deb_hex(LBS_DEB_JOIN, "AP rates    ", rates, *rates_size);	lbs_deb_hex(LBS_DEB_JOIN, "card rates  ", card_rates, num_card_rates);	lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);	lbs_deb_join("Tx datarate is currently 0x%X\n", adapter->cur_rate);	if (!adapter->auto_rate) {		for (i = 0; i < tmp_size; i++) {			if (tmp[i] == adapter->cur_rate)				goto done;		}		lbs_pr_alert("Previously set fixed data rate %#x isn't "		       "compatible with the network.\n", adapter->cur_rate);		ret = -1;		goto done;	}	ret = 0;done:	memset(rates, 0, *rates_size);	*rates_size = min_t(int, tmp_size, *rates_size);	memcpy(rates, tmp, *rates_size);	return ret;}/** *  @brief Sets the MSB on basic rates as the firmware requires * * Scan through an array and set the MSB for basic data rates. * *  @param rates     buffer of data rates *  @param len       size of buffer */static void libertas_set_basic_rate_flags(u8 * rates, size_t len){	int i;	for (i = 0; i < len; i++) {		if (rates[i] == 0x02 || rates[i] == 0x04 ||		    rates[i] == 0x0b || rates[i] == 0x16)			rates[i] |= 0x80;	}}/** *  @brief Unsets the MSB on basic rates * * Scan through an array and unset the MSB for basic data rates. * *  @param rates     buffer of data rates *  @param len       size of buffer */void libertas_unset_basic_rate_flags(u8 * rates, size_t len){	int i;	for (i = 0; i < len; i++)		rates[i] &= 0x7f;}/** *  @brief Associate to a specific BSS discovered in a scan * *  @param priv      A pointer to wlan_private structure *  @param pbssdesc  Pointer to the BSS descriptor to associate with. * *  @return          0-success, otherwise fail */int wlan_associate(wlan_private * priv, struct assoc_request * assoc_req){	wlan_adapter *adapter = priv->adapter;	int ret;	lbs_deb_enter(LBS_DEB_JOIN);	ret = libertas_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,				    0, CMD_OPTION_WAITFORRSP,				    0, assoc_req->bss.bssid);	if (ret)		goto done;	/* set preamble to firmware */	if (   (adapter->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)	    && (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))		adapter->preamble = CMD_TYPE_SHORT_PREAMBLE;	else		adapter->preamble = CMD_TYPE_LONG_PREAMBLE;	libertas_set_radio_control(priv);	ret = libertas_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,				    0, CMD_OPTION_WAITFORRSP, 0, assoc_req);done:	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);	return ret;}/** *  @brief Start an Adhoc Network * *  @param priv         A pointer to wlan_private structure *  @param adhocssid    The ssid of the Adhoc Network *  @return             0--success, -1--fail */int libertas_start_adhoc_network(wlan_private * priv, struct assoc_request * assoc_req){	wlan_adapter *adapter = priv->adapter;	int ret = 0;	adapter->adhoccreate = 1;	if (adapter->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {		lbs_deb_join("AdhocStart: Short preamble\n");		adapter->preamble = CMD_TYPE_SHORT_PREAMBLE;	} else {		lbs_deb_join("AdhocStart: Long preamble\n");		adapter->preamble = CMD_TYPE_LONG_PREAMBLE;	}	libertas_set_radio_control(priv);	lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);	lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);	ret = libertas_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,				    0, CMD_OPTION_WAITFORRSP, 0, assoc_req);	return ret;}/** *  @brief Join an adhoc network found in a previous scan * *  @param priv         A pointer to wlan_private structure *  @param pbssdesc     Pointer to a BSS descriptor found in a previous scan *                      to attempt to join * *  @return             0--success, -1--fail */int libertas_join_adhoc_network(wlan_private * priv, struct assoc_request * assoc_req){	wlan_adapter *adapter = priv->adapter;	struct bss_descriptor * bss = &assoc_req->bss;	int ret = 0;	lbs_deb_join("%s: Current SSID '%s', ssid length %u\n",	             __func__,	             escape_essid(adapter->curbssparams.ssid,	                          adapter->curbssparams.ssid_len),	             adapter->curbssparams.ssid_len);	lbs_deb_join("%s: requested ssid '%s', ssid length %u\n",	             __func__, escape_essid(bss->ssid, bss->ssid_len),	             bss->ssid_len);	/* check if the requested SSID is already joined */	if (   adapter->curbssparams.ssid_len	    && !libertas_ssid_cmp(adapter->curbssparams.ssid,	                          adapter->curbssparams.ssid_len,	                          bss->ssid, bss->ssid_len)	    && (adapter->mode == IW_MODE_ADHOC)	    && (adapter->connect_status == LIBERTAS_CONNECTED)) {		union iwreq_data wrqu;		lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "		             "current, not attempting to re-join");		/* Send the re-association event though, because the association		 * request really was successful, even if just a null-op.		 */		memset(&wrqu, 0, sizeof(wrqu));		memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid,		       ETH_ALEN);		wrqu.ap_addr.sa_family = ARPHRD_ETHER;		wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);		goto out;	}	/* Use shortpreamble only when both creator and card supports	   short preamble */	if (   !(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)	    || !(adapter->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {		lbs_deb_join("AdhocJoin: Long preamble\n");		adapter->preamble = CMD_TYPE_LONG_PREAMBLE;	} else {		lbs_deb_join("AdhocJoin: Short preamble\n");		adapter->preamble = CMD_TYPE_SHORT_PREAMBLE;	}	libertas_set_radio_control(priv);	lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);	lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);	adapter->adhoccreate = 0;	ret = libertas_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,				    0, CMD_OPTION_WAITFORRSP,				    OID_802_11_SSID, assoc_req);out:	return ret;}int libertas_stop_adhoc_network(wlan_private * priv){	return libertas_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,				     0, CMD_OPTION_WAITFORRSP, 0, NULL);}/** *  @brief Send Deauthentication Request * *  @param priv      A pointer to wlan_private structure *  @return          0--success, -1--fail */int libertas_send_deauthentication(wlan_private * priv){	return libertas_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,				     0, CMD_OPTION_WAITFORRSP, 0, NULL);}/** *  @brief This function prepares command of authenticate. * *  @param priv      A pointer to wlan_private structure *  @param cmd       A pointer to cmd_ds_command structure *  @param pdata_buf Void cast of pointer to a BSSID to authenticate with * *  @return         0 or -1 */int libertas_cmd_80211_authenticate(wlan_private * priv,				 struct cmd_ds_command *cmd,				 void *pdata_buf){	wlan_adapter *adapter = priv->adapter;	struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;	int ret = -1;	u8 *bssid = pdata_buf;	DECLARE_MAC_BUF(mac);	lbs_deb_enter(LBS_DEB_JOIN);	cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE);	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)	                        + S_DS_GEN);	/* translate auth mode to 802.11 defined wire value */	switch (adapter->secinfo.auth_mode) {	case IW_AUTH_ALG_OPEN_SYSTEM:		pauthenticate->authtype = 0x00;		break;	case IW_AUTH_ALG_SHARED_KEY:		pauthenticate->authtype = 0x01;		break;	case IW_AUTH_ALG_LEAP:		pauthenticate->authtype = 0x80;		break;	default:		lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",		             adapter->secinfo.auth_mode);		goto out;	}	memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);	lbs_deb_join("AUTH_CMD: BSSID is : %s auth=0x%X\n",	             print_mac(mac, bssid), pauthenticate->authtype);	ret = 0;out:	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);	return ret;}int libertas_cmd_80211_deauthenticate(wlan_private * priv,				   struct cmd_ds_command *cmd){	wlan_adapter *adapter = priv->adapter;	struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;	lbs_deb_enter(LBS_DEB_JOIN);	cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE);	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +			     S_DS_GEN);	/* set AP MAC address */	memmove(dauth->macaddr, adapter->curbssparams.bssid, ETH_ALEN);	/* Reason code 3 = Station is leaving */#define REASON_CODE_STA_LEAVING 3	dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);	lbs_deb_leave(LBS_DEB_JOIN);	return 0;}int libertas_cmd_80211_associate(wlan_private * priv,			      struct cmd_ds_command *cmd, void *pdata_buf){	wlan_adapter *adapter = priv->adapter;	struct cmd_ds_802_11_associate *passo = &cmd->params.associate;	int ret = 0;	struct assoc_request * assoc_req = pdata_buf;	struct bss_descriptor * bss = &assoc_req->bss;	u8 *pos;	u16 tmpcap, tmplen;	struct mrvlietypes_ssidparamset *ssid;	struct mrvlietypes_phyparamset *phy;	struct mrvlietypes_ssparamset *ss;	struct mrvlietypes_ratesparamset *rates;	struct mrvlietypes_rsnparamset *rsn;	lbs_deb_enter(LBS_DEB_JOIN);	pos = (u8 *) passo;	if (!adapter) {		ret = -1;		goto done;	}	cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE);	memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));	pos += sizeof(passo->peerstaaddr);	/* set the listen interval */	passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);	pos += sizeof(passo->capability);	pos += sizeof(passo->listeninterval);	pos += sizeof(passo->bcnperiod);	pos += sizeof(passo->dtimperiod);	ssid = (struct mrvlietypes_ssidparamset *) pos;	ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);	tmplen = bss->ssid_len;	ssid->header.len = cpu_to_le16(tmplen);	memcpy(ssid->ssid, bss->ssid, tmplen);	pos += sizeof(ssid->header) + tmplen;	phy = (struct mrvlietypes_phyparamset *) pos;	phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);	tmplen = sizeof(phy->fh_ds.dsparamset);	phy->header.len = cpu_to_le16(tmplen);	memcpy(&phy->fh_ds.dsparamset,	       &bss->phyparamset.dsparamset.currentchan,	       tmplen);	pos += sizeof(phy->header) + tmplen;	ss = (struct mrvlietypes_ssparamset *) pos;	ss->header.type = cpu_to_le16(TLV_TYPE_CF);	tmplen = sizeof(ss->cf_ibss.cfparamset);	ss->header.len = cpu_to_le16(tmplen);	pos += sizeof(ss->header) + tmplen;	rates = (struct mrvlietypes_ratesparamset *) pos;	rates->header.type = cpu_to_le16(TLV_TYPE_RATES);	memcpy(&rates->rates, &bss->rates, MAX_RATES);	tmplen = MAX_RATES;	if (get_common_rates(adapter, rates->rates, &tmplen)) {		ret = -1;		goto done;	}	pos += sizeof(rates->header) + tmplen;	rates->header.len = cpu_to_le16(tmplen);	lbs_deb_join("ASSOC_CMD: num rates = %u\n", tmplen);	/* Copy the infra. association rates into Current BSS state structure */	memset(&adapter->curbssparams.rates, 0, sizeof(adapter->curbssparams.rates));	memcpy(&adapter->curbssparams.rates, &rates->rates, tmplen);	/* Set MSB on basic rates as the firmware requires, but _after_	 * copying to current bss rates.	 */	libertas_set_basic_rate_flags(rates->rates, tmplen);	if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {		rsn = (struct mrvlietypes_rsnparamset *) pos;		/* WPA_IE or WPA2_IE */		rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);		tmplen = (u16) assoc_req->wpa_ie[1];		rsn->header.len = cpu_to_le16(tmplen);		memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);		lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn,			sizeof(rsn->header) + tmplen);		pos += sizeof(rsn->header) + tmplen;	}	/* update curbssparams */	adapter->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;	if (libertas_parse_dnld_countryinfo_11d(priv, bss)) {		ret = -1;		goto done;	}	cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);	/* set the capability info */	tmpcap = (bss->capability & CAPINFO_MASK);

⌨️ 快捷键说明

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