📄 ieee80211_output.c.svn-base
字号:
+ sizeof(struct ieee80211_wme_param) /* XXX !WPA1+WPA2 fits w/o a cluster */ + (vap->iv_flags & IEEE80211_F_WPA ? 2 * sizeof(struct ieee80211_ie_wpa) : 0) + sizeof(struct ieee80211_ie_athAdvCap) + vap->app_ie[IEEE80211_APPIE_FRAME_PROBE_RESP].length;#ifdef ATH_SUPERG_XR if (vap->iv_ath_cap & IEEE80211_ATHC_XR) frm_len += sizeof(struct ieee80211_xr_param);#endif skb = ieee80211_getmgtframe(&frm, frm_len); if (skb == NULL) senderr(ENOMEM, is_tx_nobuf); /* timestamp should be filled later */ memset(frm, 0, 8); frm += 8; /* beacon interval */ *(__le16 *)frm = htole16(vap->iv_bss->ni_intval); frm += 2; /* cap. info */ if (vap->iv_opmode == IEEE80211_M_IBSS) capinfo = IEEE80211_CAPINFO_IBSS; else capinfo = IEEE80211_CAPINFO_ESS; if (vap->iv_flags & IEEE80211_F_PRIVACY) capinfo |= IEEE80211_CAPINFO_PRIVACY; if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; if (ic->ic_flags & IEEE80211_F_SHSLOT) capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME; *(__le16 *)frm = htole16(capinfo); frm += 2; /* ssid */ frm = ieee80211_add_ssid(frm, vap->iv_bss->ni_essid, vap->iv_bss->ni_esslen); /* supported rates */ frm = ieee80211_add_rates(frm, &ni->ni_rates); /* XXX: FH/DS parameter set, correct ? */ if (ic->ic_phytype == IEEE80211_T_FH) { *frm++ = IEEE80211_ELEMID_FHPARMS; *frm++ = 5; *frm++ = ni->ni_fhdwell & 0x00ff; *frm++ = (ni->ni_fhdwell >> 8) & 0x00ff; *frm++ = IEEE80211_FH_CHANSET( ieee80211_chan2ieee(ic, ic->ic_curchan)); *frm++ = IEEE80211_FH_CHANPAT( ieee80211_chan2ieee(ic, ic->ic_curchan)); *frm++ = ni->ni_fhindex; } else { *frm++ = IEEE80211_ELEMID_DSPARMS; *frm++ = 1; *frm++ = ieee80211_chan2ieee(ic, ic->ic_curchan); } if (vap->iv_opmode == IEEE80211_M_IBSS) { *frm++ = IEEE80211_ELEMID_IBSSPARMS; *frm++ = 2; *frm++ = 0; *frm++ = 0; /* TODO: ATIM window */ } /* country code */ if ((ic->ic_flags & IEEE80211_F_DOTH) || (ic->ic_flags_ext & IEEE80211_FEXT_COUNTRYIE)) frm = ieee80211_add_country(frm, ic); /* power constraint */ if (ic->ic_flags & IEEE80211_F_DOTH) frm = ieee80211_add_pwrcnstr(frm, ic); /* ERP */ if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) frm = ieee80211_add_erp(frm, ic); /* Ext. Supp. Rates */ frm = ieee80211_add_xrates(frm, &ni->ni_rates); /* WME */ if (vap->iv_flags & IEEE80211_F_WME) frm = ieee80211_add_wme_param(frm, &ic->ic_wme, IEEE80211_VAP_UAPSD_ENABLED(vap)); /* WPA */ if (vap->iv_flags & IEEE80211_F_WPA) frm = ieee80211_add_wpa(frm, vap); /* AthAdvCaps */ if (vap->iv_bss && vap->iv_bss->ni_ath_flags) frm = ieee80211_add_athAdvCap(frm, vap->iv_bss->ni_ath_flags, vap->iv_bss->ni_ath_defkeyindex);#ifdef ATH_SUPERG_XR /* XR params */ if (vap->iv_xrvap && vap->iv_ath_cap & IEEE80211_ATHC_XR) frm = ieee80211_add_xr_param(frm, vap);#endif if (vap->app_ie[IEEE80211_APPIE_FRAME_PROBE_RESP].ie) { memcpy(frm, vap->app_ie[IEEE80211_APPIE_FRAME_PROBE_RESP].ie, vap->app_ie[IEEE80211_APPIE_FRAME_PROBE_RESP].length); frm += vap->app_ie[IEEE80211_APPIE_FRAME_PROBE_RESP].length; } skb_trim(skb, frm - skb->data); break; case IEEE80211_FC0_SUBTYPE_AUTH: status = arg >> 16; arg &= 0xffff; has_challenge = ((arg == IEEE80211_AUTH_SHARED_CHALLENGE || arg == IEEE80211_AUTH_SHARED_RESPONSE) && ni->ni_challenge != NULL); /* * Deduce whether we're doing open authentication or * shared key authentication. We do the latter if * we're in the middle of a shared key authentication * handshake or if we're initiating an authentication * request and configured to use shared key. */ is_shared_key = has_challenge || arg >= IEEE80211_AUTH_SHARED_RESPONSE || (arg == IEEE80211_AUTH_SHARED_REQUEST && vap->iv_bss->ni_authmode == IEEE80211_AUTH_SHARED); skb = ieee80211_getmgtframe(&frm, 3 * sizeof(u_int16_t) + (has_challenge && status == IEEE80211_STATUS_SUCCESS ? sizeof(u_int16_t)+IEEE80211_CHALLENGE_LEN : 0)); if (skb == NULL) senderr(ENOMEM, is_tx_nobuf); ((__le16 *)frm)[0] = (is_shared_key) ? htole16(IEEE80211_AUTH_ALG_SHARED) : htole16(IEEE80211_AUTH_ALG_OPEN); ((__le16 *)frm)[1] = htole16(arg); /* sequence number */ ((__le16 *)frm)[2] = htole16(status); /* status */ if (has_challenge && status == IEEE80211_STATUS_SUCCESS) { ((__le16 *)frm)[3] = htole16((IEEE80211_CHALLENGE_LEN << 8) | IEEE80211_ELEMID_CHALLENGE); memcpy(&((__le16 *)frm)[4], ni->ni_challenge, IEEE80211_CHALLENGE_LEN); if (arg == IEEE80211_AUTH_SHARED_RESPONSE) { IEEE80211_NOTE(vap, IEEE80211_MSG_AUTH, ni, "request encrypt frame (%s)", __func__); SKB_CB(skb)->flags |= M_LINK0; /* WEP-encrypt, please */ } } /* XXX not right for shared key */ if (status == IEEE80211_STATUS_SUCCESS) IEEE80211_NODE_STAT(ni, tx_auth); else IEEE80211_NODE_STAT(ni, tx_auth_fail); if (vap->iv_opmode == IEEE80211_M_STA) timer = IEEE80211_TRANS_WAIT; break; case IEEE80211_FC0_SUBTYPE_DEAUTH: IEEE80211_NOTE(vap, IEEE80211_MSG_AUTH, ni, "send station deauthenticate (reason %d)", arg); skb = ieee80211_getmgtframe(&frm, sizeof(u_int16_t)); if (skb == NULL) senderr(ENOMEM, is_tx_nobuf); *(__le16 *)frm = htole16(arg); /* reason */ IEEE80211_NODE_STAT(ni, tx_deauth); IEEE80211_NODE_STAT_SET(ni, tx_deauth_code, arg); ieee80211_node_unauthorize(ni); /* port closed */ break; case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: /* * asreq frame format * [2] capability information * [2] listen interval * [6*] current AP address (reassoc only) * [tlv] ssid * [tlv] supported rates * [4] power capability (802.11h) * [tlv] supported channels element (802.11h) * [tlv] extended supported rates * [tlv] WME [if enabled and AP capable] * [tlv] Atheros advanced capabilities * [tlv] user-specified IEs */ skb = ieee80211_getmgtframe(&frm, sizeof(u_int16_t) + sizeof(u_int16_t) + IEEE80211_ADDR_LEN + 2 + IEEE80211_NWID_LEN + 2 + IEEE80211_RATE_SIZE + 4 + (2 + ic->ic_sc_ie.sc_len) + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) + sizeof(struct ieee80211_ie_wme) + sizeof(struct ieee80211_ie_athAdvCap) + (vap->iv_opt_ie != NULL ? vap->iv_opt_ie_len : 0) + vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_REQ].length); if (skb == NULL) senderr(ENOMEM, is_tx_nobuf); capinfo = 0; if (vap->iv_opmode == IEEE80211_M_IBSS) capinfo |= IEEE80211_CAPINFO_IBSS; else /* IEEE80211_M_STA */ capinfo |= IEEE80211_CAPINFO_ESS; if (vap->iv_flags & IEEE80211_F_PRIVACY) capinfo |= IEEE80211_CAPINFO_PRIVACY; /* * NB: Some 11a APs reject the request when * short premable is set. */ /* Capability information */ if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) && (ic->ic_caps & IEEE80211_C_SHSLOT)) capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME; *(__le16 *)frm = htole16(capinfo); frm += 2; /* listen interval */ *(__le16 *)frm = htole16(ic->ic_lintval); frm += 2; /* Current AP address */ if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) { IEEE80211_ADDR_COPY(frm, vap->iv_bssid); frm += IEEE80211_ADDR_LEN; } /* ssid */ frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen); /* supported rates */ frm = ieee80211_add_rates(frm, &ni->ni_rates); /* power capability/supported channels */ if (ic->ic_flags & IEEE80211_F_DOTH) { frm = ieee80211_add_pwrcap(frm, ic); frm = ieee80211_add_suppchan(frm, ic); } /* ext. supp. rates */ frm = ieee80211_add_xrates(frm, &ni->ni_rates); /* wme */ if ((vap->iv_flags & IEEE80211_F_WME) && ni->ni_wme_ie != NULL) frm = ieee80211_add_wme(frm, ni); /* ath adv. cap */ if (ni->ni_ath_flags & vap->iv_ath_cap) { IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni, "Adding ath adv cap ie: ni_ath_flags = %02x, " "iv_ath_cap = %02x", ni->ni_ath_flags, vap->iv_ath_cap); /* Setup default key index for static wep case */ def_keyindex = IEEE80211_INVAL_DEFKEY; if (((vap->iv_flags & IEEE80211_F_WPA) == 0) && (ni->ni_authmode != IEEE80211_AUTH_8021X) && (vap->iv_def_txkey != IEEE80211_KEYIX_NONE)) def_keyindex = vap->iv_def_txkey; frm = ieee80211_add_athAdvCap(frm, ni->ni_ath_flags & vap->iv_ath_cap, def_keyindex); } /* User-spec */ if (vap->iv_opt_ie != NULL) { memcpy(frm, vap->iv_opt_ie, vap->iv_opt_ie_len); frm += vap->iv_opt_ie_len; } if (vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_REQ].ie) { memcpy(frm, vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_REQ].ie, vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_REQ].length); frm += vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_REQ].length; } skb_trim(skb, frm - skb->data); timer = IEEE80211_TRANS_WAIT; break; case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: /* * asreq frame format * [2] capability information * [2] status * [2] association ID * [tlv] supported rates * [tlv] extended supported rates * [tlv] WME (if enabled and STA enabled) * [tlv] Atheros Advanced Capabilities */ skb = ieee80211_getmgtframe(&frm, 3 * sizeof(u_int16_t) + 2 + IEEE80211_RATE_SIZE + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) + sizeof(struct ieee80211_wme_param) + (vap->iv_ath_cap ? sizeof(struct ieee80211_ie_athAdvCap):0) + vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_RESP].length); if (skb == NULL) senderr(ENOMEM, is_tx_nobuf); /* Capability Information */ capinfo = IEEE80211_CAPINFO_ESS; if (vap->iv_flags & IEEE80211_F_PRIVACY) capinfo |= IEEE80211_CAPINFO_PRIVACY; if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; if (ic->ic_flags & IEEE80211_F_SHSLOT) capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME; *(__le16 *)frm = htole16(capinfo); frm += 2; /* status */ *(__le16 *)frm = htole16(arg); frm += 2; /* Assoc ID */ if (arg == IEEE80211_STATUS_SUCCESS) { *(__le16 *)frm = htole16(ni->ni_associd); IEEE80211_NODE_STAT(ni, tx_assoc); } else IEEE80211_NODE_STAT(ni, tx_assoc_fail); frm += 2; /* supported rates */ frm = ieee80211_add_rates(frm, &ni->ni_rates); /* ext. suppo. rates */ frm = ieee80211_add_xrates(frm, &ni->ni_rates); /* wme */ if ((vap->iv_flags & IEEE80211_F_WME) && ni->ni_wme_ie != NULL) frm = ieee80211_add_wme_param(frm, &ic->ic_wme, IEEE80211_VAP_UAPSD_ENABLED(vap)); /* athAdvCap */ if (vap->iv_ath_cap) frm = ieee80211_add_athAdvCap(frm, vap->iv_ath_cap & ni->ni_ath_flags, ni->ni_ath_defkeyindex); if (vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_RESP].ie) { memcpy(frm, vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_RESP].ie, vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_RESP].length); frm += vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_RESP].length; } skb_trim(skb, frm - skb->data); break; case IEEE80211_FC0_SUBTYPE_DISASSOC: IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni, "send station disassociate (reason %d)", arg); skb = ieee80211_getmgtframe(&frm, sizeof(u_int16_t)); if (skb == NULL) senderr(ENOMEM, is_tx_nobuf); *(__le16 *)frm = htole16(arg); /* reason */ IEEE80211_NODE_STAT(ni, tx_disassoc); IEEE80211_NODE_STAT_SET(ni, tx_disassoc_code, arg); break; default: IEEE80211_NOTE(vap, IEEE80211_MSG_ANY, ni, "invalid mgmt frame type %u", type); senderr(EINVAL, is_tx_unknownmgt); /* NOTREACHED */ } ieee80211_mgmt_output(ieee80211_ref_node(ni), skb, type); if (timer) mod_timer(&vap->iv_mgtsend, jiffies + timer * HZ); return 0;bad: return ret;#undef senderr}/* * Send PS-POLL from to bss. Should only be called when as STA. */voidieee80211_send_pspoll(struct ieee80211_node *ni){ struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; struct sk_buff *skb; struct ieee80211_ctlframe_addr2 *wh; skb = ieee80211_dev_alloc_skb(sizeof(struct ieee80211_ctlframe_addr2)); if (skb == NULL) return; SKB_NI(skb) = ieee80211_ref_node(ni); skb->priority = WME_AC_VO; wh = (struct ieee80211_ctlframe_addr2 *)skb_put(skb, sizeof(struct ieee80211_ctlframe_addr2)); wh->i_aidordur = htole16(0xc000 | IEEE80211_NODE_AID(ni)); IEEE80211_ADDR_COPY(wh->i_addr1, vap->iv_bssid); IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr); wh->i_fc[0] = 0; wh->i_fc[1] = 0; wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL; if (IEEE80211_VAP_IS_SLEEPING(ni->ni_vap)) wh->i_fc[1] |= IEEE80211_FC1_PWR_MGT; (void) ic->ic_mgtstart(ic, skb); /* cheat */}#ifdef ATH_SUPERG_XR/* * constructs and returns a contention free frames. * currently used for Group poll in XR mode. */struct sk_buff *ieee80211_getcfframe(struct ieee80211vap *vap, int type){ u_int8_t *frm; struct sk_buff *skb; struct ieee80211_frame *wh; struct ieee80211com *ic = vap->iv_ic; skb = ieee80211_getmgtframe(&frm, 0); if (skb == NULL) return NULL; wh = (struct ieee80211_frame *) skb_push(skb, sizeof(struct ieee80211_frame)); if (type == IEEE80211_FC0_SUBTYPE_CFPOLL) { wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS; wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA | type; wh->i_dur = htole16(0x8000); } else if (type == IE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -