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

📄 ieee80211_output.c.svn-base

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
		llc = (struct llc *)skb_push(skb, LLC_SNAPFRAMELEN);		llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;		llc->llc_control = LLC_UI;		llc->llc_snap.org_code[0] = 0;		llc->llc_snap.org_code[1] = 0;		llc->llc_snap.org_code[2] = 0;		llc->llc_snap.ether_type = eh.ether_type;		eh_inter = (struct ether_header *)skb_push(skb, sizeof(struct ether_header));		memcpy(eh_inter, &eh, sizeof(struct ether_header) - sizeof eh.ether_type);		eh_inter->ether_type = htons(payload);		/* overall ff encap header */		/* XXX: the offset of 2, below, should be computed. but... it will not		 *      practically ever change.		 */		ffhdr = (struct athl2p_tunnel_hdr *)skb_push(skb, sizeof(struct athl2p_tunnel_hdr) + 2);		memset(ffhdr, 0, sizeof(struct athl2p_tunnel_hdr) + 2);		/*		 * add second skb tunnel hdrs		 */		payload = skb2->len + LLC_SNAPFRAMELEN;		llc = (struct llc *)skb_push(skb2, LLC_SNAPFRAMELEN);		if (llc == NULL) {			IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPG,				"%s: failed to push llc for 2nd skb (%p)\n",				__func__, skb);			return NULL;		}		llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;		llc->llc_control = LLC_UI;		llc->llc_snap.org_code[0] = 0;		llc->llc_snap.org_code[1] = 0;		llc->llc_snap.org_code[2] = 0;		llc->llc_snap.ether_type = eh2.ether_type;		eh_inter = (struct ether_header *)skb_push(skb2, sizeof(struct ether_header));		if (eh_inter == NULL) {			IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPG,				"%s: failed to push eth hdr for 2nd skb (%p)\n",				__func__, skb);			return NULL;		}		memcpy(eh_inter, &eh2, sizeof(struct ether_header) - sizeof eh2.ether_type);		eh_inter->ether_type = htons(payload);		/* variable length pad */		skb_push(skb2, roundup(padded_len, 4) - padded_len);	}#endif	llc = (struct llc *)skb_push(skb, LLC_SNAPFRAMELEN);	llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;	llc->llc_control = LLC_UI;#ifndef ATH_SUPERG_FF	llc->llc_snap.org_code[0] = 0;	llc->llc_snap.org_code[1] = 0;	llc->llc_snap.org_code[2] = 0;	llc->llc_snap.ether_type = eh.ether_type;#else /* ATH_SUPERG_FF */	if (isff) {		llc->llc_snap.org_code[0] = ATH_SNAP_ORGCODE_0;		llc->llc_snap.org_code[1] = ATH_SNAP_ORGCODE_1;		llc->llc_snap.org_code[2] = ATH_SNAP_ORGCODE_2;		llc->llc_snap.ether_type = htons(ATH_ETH_TYPE);	} else {		llc->llc_snap.org_code[0] = 0;		llc->llc_snap.org_code[1] = 0;		llc->llc_snap.org_code[2] = 0;		llc->llc_snap.ether_type = eh.ether_type;	}#endif /* ATH_SUPERG_FF */	datalen = skb->len;			/* NB: w/o 802.11 header */	wh = (struct ieee80211_frame *)skb_push(skb, hdrsize);	wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;	wh->i_dur = 0;	if (use4addr) {		wh->i_fc[1] = IEEE80211_FC1_DIR_DSTODS;		IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);		IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);		IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);		IEEE80211_ADDR_COPY(WH4(wh)->i_addr4, eh.ether_shost);	} else {		switch (vap->iv_opmode) {		case IEEE80211_M_IBSS:		case IEEE80211_M_AHDEMO:			wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;			IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);			IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);			/*			 * NB: always use the bssid from iv_bssid as the			 *     neighbor's may be stale after an ibss merge			 */			IEEE80211_ADDR_COPY(wh->i_addr3, vap->iv_bssid);			break;		case IEEE80211_M_STA:			wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;			IEEE80211_ADDR_COPY(wh->i_addr1, vap->iv_bssid);			IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);			IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);			break;		case IEEE80211_M_HOSTAP:			wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;			IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);			IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_bssid);			IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);			if (M_PWR_SAV_GET(skb)) {				if (IEEE80211_NODE_SAVEQ_QLEN(ni)) {					wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;					M_PWR_SAV_CLR(skb);				}			}			break;		case IEEE80211_M_WDS:			wh->i_fc[1] = IEEE80211_FC1_DIR_DSTODS;			IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);			IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);			IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);			IEEE80211_ADDR_COPY(WH4(wh)->i_addr4, eh.ether_shost);			break;		case IEEE80211_M_MONITOR:			goto bad;		}	}	if (IEEE80211_VAP_IS_SLEEPING(vap))		wh->i_fc[1] |= IEEE80211_FC1_PWR_MGT;	if (addqos) {		struct ieee80211_qosframe *qwh =			(struct ieee80211_qosframe *)wh;		u_int8_t *qos;		int tid;		qos = &qwh->i_qos[0];		if (use4addr)			qos += IEEE80211_ADDR_LEN;		/* map from access class/queue to 11e header priority value */		tid = WME_AC_TO_TID(skb->priority);		qos[0] = tid & IEEE80211_QOS_TID;		if (ic->ic_wme.wme_wmeChanParams.cap_wmeParams[skb->priority].wmep_noackPolicy)			qos[0] |= (1 << IEEE80211_QOS_ACKPOLICY_S) & IEEE80211_QOS_ACKPOLICY;		qos[1] = 0;		qwh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS;		*(__le16 *)&wh->i_seq[0] =			htole16(ni->ni_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);		ni->ni_txseqs[tid]++;	} else {		*(__le16 *)wh->i_seq =			htole16(ni->ni_txseqs[0] << IEEE80211_SEQ_SEQ_SHIFT);		ni->ni_txseqs[0]++;	}	/* Is transmit fragmentation needed? */	if (skb->len > vap->iv_fragthreshold &&	    !IEEE80211_IS_MULTICAST(wh->i_addr1)) {		int pktlen, skbcnt, tailsize, ciphdrsize;		struct ieee80211_cipher *cip;		pktlen = skb->len;		ciphdrsize = 0;		tailsize = IEEE80211_CRC_LEN;		if (key != NULL) {			cip = (struct ieee80211_cipher *)key->wk_cipher;			ciphdrsize = cip->ic_header;			tailsize += (cip->ic_trailer + cip->ic_miclen);			/* Add the 8 bytes MIC length. */			if (cip->ic_cipher == IEEE80211_CIPHER_TKIP)				pktlen += IEEE80211_WEP_MICLEN;		}		pdusize = vap->iv_fragthreshold - (hdrsize_nopad + ciphdrsize);		fragcnt = *framecnt =			((pktlen - hdrsize_nopad) / pdusize) +			(((pktlen - hdrsize_nopad) % pdusize == 0) ? 0 : 1);		/*		 * Allocate sk_buff for each subsequent fragment; First fragment		 * reuses input skb.		 */		for (skbcnt = 1; skbcnt < fragcnt; skbcnt++) {			tskb = ieee80211_dev_alloc_skb(hdrsize + ciphdrsize + pdusize + tailsize);			if (tskb == NULL)				break;			tskb->next = framelist;			framelist = tskb;		}		if (skbcnt != fragcnt)			goto bad;	}	else		*framecnt = fragcnt;	if (key != NULL) {		/*		 * IEEE 802.1X: send EAPOL frames always in the clear.		 * WPA/WPA2: encrypt EAPOL keys when pairwise keys are set.		 */		if (eh.ether_type != __constant_htons(ETHERTYPE_PAE) ||		    ((vap->iv_flags & IEEE80211_F_WPA) &&		    (vap->iv_opmode == IEEE80211_M_STA ?		    !KEY_UNDEFINED(*key) : !KEY_UNDEFINED(ni->ni_ucastkey)))) {			int force_swmic = (fragcnt > 1) ? 1 : 0;			wh->i_fc[1] |= IEEE80211_FC1_PROT;			if (!ieee80211_crypto_enmic(vap, key, skb, force_swmic)) {				IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_OUTPUT,					eh.ether_dhost,					"%s", "enmic failed, discard frame");				vap->iv_stats.is_crypto_enmicfail++;				goto bad;			}		}	}	if (fragcnt > 1) {		int fragnum, offset, pdulen;		void *pdu;		fragnum = 0;		wh = twh = (struct ieee80211_frame *)skb->data;		/*		** Setup WLAN headers as fragment headers		*/		wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;		*(__le16 *)&wh->i_seq[0] |=			htole16((fragnum & IEEE80211_SEQ_FRAG_MASK) <<				IEEE80211_SEQ_FRAG_SHIFT);		fragnum++;		offset = hdrsize + pdusize;		datalen = (skb->len - hdrsize) - pdusize;		IEEE80211_NODE_STAT(ni, tx_data);		IEEE80211_NODE_STAT_ADD(ni, tx_bytes, pdusize);		for (tskb = framelist; tskb != NULL; tskb = tskb->next) {			/*			 * Copy WLAN header into each frag header skb			 */			twh = (struct ieee80211_frame *)skb_put(tskb, hdrsize);			memcpy((void *)twh, (void *)wh, hdrsize);			*(__le16 *)&twh->i_seq[0] |=				htole16((fragnum & IEEE80211_SEQ_FRAG_MASK) <<					IEEE80211_SEQ_FRAG_SHIFT);			fragnum++;			if (pdusize <= datalen)				pdulen = pdusize;			else				pdulen = datalen;			/*			 * Copy fragment payload from input skb.			 * Doing copies isn't intuitive from 			 * a performance perspective, however,			 * for this case, it is believed to be 			 * more efficient than cloning skbs.			 */			pdu = skb_put(tskb, pdulen);			memcpy(pdu, (void *)skb->data + offset, pdulen);			offset += pdusize;			datalen -= pdusize;			IEEE80211_NODE_STAT(ni, tx_data);			IEEE80211_NODE_STAT_ADD(ni, tx_bytes, pdulen);		}		twh->i_fc[1] &= ~IEEE80211_FC1_MORE_FRAG;		skb_trim(skb, hdrsize + pdusize);		skb->next = framelist;	} else {		IEEE80211_NODE_STAT(ni, tx_data);		IEEE80211_NODE_STAT_ADD(ni, tx_bytes, datalen);#ifdef ATH_SUPERG_FF		/* Account for a second skb in the same packet when FF is on */		if (skb->next) {			datalen = skb->next->len;			IEEE80211_NODE_STAT(ni, tx_data);			IEEE80211_NODE_STAT_ADD(ni, tx_bytes, datalen);		}#endif	}	return skb;bad:	if (framelist != NULL) {		ieee80211_dev_kfree_skb_list(&framelist);	}	if (skb != NULL) {		ieee80211_dev_kfree_skb_list(&skb);	}	return NULL;#undef WH4}EXPORT_SYMBOL(ieee80211_encap);#undef KEY_UNDEFINED/* * Add a supported rates element id to a frame. */u_int8_t *ieee80211_add_rates(u_int8_t *frm, const struct ieee80211_rateset *rs){	int nrates;	*frm++ = IEEE80211_ELEMID_RATES;	nrates = rs->rs_nrates;	if (nrates > IEEE80211_RATE_SIZE)		nrates = IEEE80211_RATE_SIZE;	*frm++ = nrates;	memcpy(frm, rs->rs_rates, nrates);	return frm + nrates;}/* * Add an extended supported rates element id to a frame. */u_int8_t *ieee80211_add_xrates(u_int8_t *frm, const struct ieee80211_rateset *rs){	/*	 * Add an extended supported rates element if operating in 11g mode.	 */	if (rs->rs_nrates > IEEE80211_RATE_SIZE) {		int nrates = rs->rs_nrates - IEEE80211_RATE_SIZE;		*frm++ = IEEE80211_ELEMID_XRATES;		*frm++ = nrates;		memcpy(frm, rs->rs_rates + IEEE80211_RATE_SIZE, nrates);		frm += nrates;	}	return frm;}/* * Add an ssid elemet to a frame. */static u_int8_t *ieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len){	*frm++ = IEEE80211_ELEMID_SSID;	*frm++ = len;	memcpy(frm, ssid, len);	return frm + len;}/* * Add an erp element to a frame. */u_int8_t *ieee80211_add_erp(u_int8_t *frm, struct ieee80211com *ic){	u_int8_t erp;	*frm++ = IEEE80211_ELEMID_ERP;	*frm++ = 1;	erp = 0;	if (ic->ic_nonerpsta != 0)		erp |= IEEE80211_ERP_NON_ERP_PRESENT;	if (ic->ic_flags & IEEE80211_F_USEPROT)		erp |= IEEE80211_ERP_USE_PROTECTION;	if ((ic->ic_flags & IEEE80211_F_USEBARKER) || (ic->ic_nonerpsta > 0))		erp |= IEEE80211_ERP_LONG_PREAMBLE;	*frm++ = erp;	return frm;}/* * Add a country information element to a frame. */u_int8_t *ieee80211_add_country(u_int8_t *frm, struct ieee80211com *ic){	/* add country code */	memcpy(frm, (u_int8_t *)&ic->ic_country_ie,		ic->ic_country_ie.country_len + 2);	frm +=  ic->ic_country_ie.country_len + 2;	return frm;}/* * Add Power Constraint information element */u_int8_t *ieee80211_add_pwrcnstr(u_int8_t *frm, struct ieee80211com *ic){	struct ieee80211_ie_pwrcnstr *ie =		(struct ieee80211_ie_pwrcnstr *)frm;	ie->pc_id = IEEE80211_ELEMID_PWRCNSTR;	ie->pc_len = 1;	ie->pc_lpc = IEEE80211_PWRCONSTRAINT_VAL(ic);	frm += sizeof(*ie);	return frm;}/* * Add Power Capability information element */static u_int8_t *ieee80211_add_pwrcap(u_int8_t *frm, struct ieee80211com *ic){	struct ieee80211_ie_pwrcap *ie =		(struct ieee80211_ie_pwrcap *)frm;	ie->pc_id = IEEE80211_ELEMID_PWRCAP;	ie->pc_len = 2;	ie->pc_mintxpow = ic->ic_bsschan->ic_minpower;	ie->pc_maxtxpow = ic->ic_bsschan->ic_maxpower;	frm += sizeof(*ie);	return frm;}/* * Add Supported Channels information element */static u_int8_t *ieee80211_add_suppchan(u_int8_t *frm, struct ieee80211com *ic){	memcpy(frm, (u_int8_t *)&ic->ic_sc_ie,			ic->ic_sc_ie.sc_len + 2);	frm += ic->ic_sc_ie.sc_len + 2;	return frm;}static u_int8_t *ieee80211_setup_wpa_ie(struct ieee80211vap *vap, u_int8_t *ie){#define	WPA_OUI_BYTES		0x00, 0x50, 0xf2#define	ADDSHORT(frm, v) do {			\	frm[0] = (v) & 0xff;			\	frm[1] = (v) >> 8;			\	frm += 2;				\} while (0)#define	ADDSELECTOR(frm, sel) do {		\	memcpy(frm, sel, 4);			\	frm += 4;				\

⌨️ 快捷键说明

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