📄 ieee80211_output.c.svn-base
字号:
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 + -