int ieee80211_recv_probereq(struct ieee80211_node *ni, wbuf_t wbuf, int subtype) { struct ieee80211com *ic = ni->ni_ic; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_frame *wh; u_int8_t *frm, *efrm; u_int8_t *ssid, *rates, *ven; #if ATH_SUPPORT_AP_WDS_COMBO if (vap->iv_opmode == IEEE80211_M_STA || !ieee80211_vap_ready_is_set(vap) || vap->iv_no_beacon) { #else if (vap->iv_opmode == IEEE80211_M_STA || !ieee80211_vap_ready_is_set(vap)) { #endif vap->iv_stats.is_rx_mgtdiscard++; /* XXX stat */ return -EINVAL; } wh = (struct ieee80211_frame *) wbuf_header(wbuf); frm = (u_int8_t *)&wh[1]; efrm = wbuf_header(wbuf) + wbuf_get_pktlen(wbuf); /*zhaoyang1 add start for probe request REQUIREMENTS-340*/ if (vap->iv_probe_request) { switch (vap->iv_probe_request) { case IEEE80211_BROADCAST_PROBE: if (IEEE80211_IS_BROADCAST(wh->i_addr1)) { vap->iv_stats.is_rx_mgtdiscard++; /* XXX stat */ return -EINVAL; } break; case IEEE80211_ALL_PROBE: vap->iv_stats.is_rx_mgtdiscard++; /* XXX stat */ return -EINVAL; default: printk("Probe_req value is wrong, iv_probe_request = %d\n", vap->iv_probe_request); break; } } /*zhaoyang1 add end*/ if (IEEE80211_IS_MULTICAST(wh->i_addr2)) { /* frame must be directed */ vap->iv_stats.is_rx_mgtdiscard++; /* XXX stat */ return -EINVAL; } /* * prreq frame format * [tlv] ssid * [tlv] supported rates * [tlv] extended supported rates * [tlv] Atheros Advanced Capabilities */ ssid = rates = NULL; while (((frm+1) < efrm) && (frm + frm[1] + 1 < efrm)) { switch (*frm) { case IEEE80211_ELEMID_SSID: ssid = frm; break; case IEEE80211_ELEMID_RATES: rates = frm; break; case IEEE80211_ELEMID_VENDOR: if (vap->iv_venie && vap->iv_venie->ven_oui_set) { ven = frm; if (ven[2] == vap->iv_venie->ven_oui[0] && ven[3] == vap->iv_venie->ven_oui[1] && ven[4] == vap->iv_venie->ven_oui[2]) { vap->iv_venie->ven_ie_len = MIN(ven[1] + 2, IEEE80211_MAX_IE_LEN); OS_MEMCPY(vap->iv_venie->ven_ie, ven, vap->iv_venie->ven_ie_len); } } break; } frm += frm[1] + 2; } if (frm > efrm) { return -EINVAL; } IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN); IEEE80211_VERIFY_SSID(vap->iv_bss, ssid); if (IEEE80211_VAP_IS_HIDESSID_ENABLED(vap) && (ssid[1] == 0)) { IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, wh, ieee80211_mgt_subtype_name[ subtype >> IEEE80211_FC0_SUBTYPE_SHIFT], "%s", "no ssid with ssid suppression enabled"); vap->iv_stats.is_rx_ssidmismatch++; /*XXX*/ return -EINVAL; } /* * Skip Probe Requests received while the scan algorithm is setting a new * channel, or while in a foreign channel. * Trying to transmit a frame (Probe Response) during a channel change * (which includes a channel reset) can cause a NMI due to invalid HW * addresses. * Trying to transmit the Probe Response while in a foreign channel * wouldn't do us any good either. */ if (ieee80211_scan_can_transmit(ic->ic_scanner)) ieee80211_send_proberesp(ni, wh->i_addr2, NULL,0); return 0; }
static u_int8_t * ieee80211_beacon_init(struct ieee80211_node *ni, struct ieee80211_beacon_offsets *bo, u_int8_t *frm) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; u_int16_t capinfo; struct ieee80211_rateset *rs = &ni->ni_rates; struct ieee80211_rsnparms *rsn = &vap->iv_rsn; int enable_htrates; bool add_wpa_ie = true; /*Begin: Added by zhanghu for increasing rate*/ ic->ic_rate_mask_bak = ic->ic_rate_mask; ic->ic_mcs_mask_bak = ic->ic_mcs_mask; /*End: Added by zhanghu for increasing rate*/ KASSERT(vap->iv_bsschan != IEEE80211_CHAN_ANYC, ("no bss chan")); OS_MEMZERO(frm, 8); /* XXX timestamp is set by hardware/driver */ frm += 8; *(u_int16_t *)frm = htole16(ieee80211_node_get_beacon_interval(ni)); frm += 2; if (vap->iv_opmode == IEEE80211_M_IBSS) capinfo = IEEE80211_CAPINFO_IBSS; else capinfo = IEEE80211_CAPINFO_ESS; if (IEEE80211_VAP_IS_PRIVACY_ENABLED(vap)) capinfo |= IEEE80211_CAPINFO_PRIVACY; if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && IEEE80211_IS_CHAN_2GHZ(vap->iv_bsschan)) capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; if (ic->ic_flags & IEEE80211_F_SHSLOT) capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME; if (ieee80211_ic_doth_is_set(ic) && ieee80211_vap_doth_is_set(vap)) capinfo |= IEEE80211_CAPINFO_SPECTRUM_MGMT; if (IEEE80211_VAP_IS_PUREB_ENABLED(vap)) { capinfo &= ~IEEE80211_CAPINFO_SHORT_SLOTTIME; rs = &ic->ic_sup_rates[IEEE80211_MODE_11B]; } else if (IEEE80211_VAP_IS_PUREG_ENABLED(vap)) { ieee80211_setpuregbasicrates(rs); } bo->bo_caps = (u_int16_t *)frm; *(u_int16_t *)frm = htole16(capinfo); frm += 2; *frm++ = IEEE80211_ELEMID_SSID; if (IEEE80211_VAP_IS_HIDESSID_ENABLED(vap)) { *frm++ = 0; } else { /* AUTELAN-Added-Begin : &tuqiang for openessid */ #if 0 *frm++ = ni->ni_esslen; OS_MEMCPY(frm, ni->ni_essid, ni->ni_esslen); frm += ni->ni_esslen; #endif if(!(openessid_param & OPENESSID_ENABLE_MASK)){ /* openessid disable */ *frm++ = ni->ni_esslen; OS_MEMCPY(frm, ni->ni_essid, ni->ni_esslen); frm += ni->ni_esslen; } else { /* openessid enable */ int index; while(vap->iv_essid_be_cnt < 4) { index = vap->iv_essid_index[vap->iv_essid_be_cnt]; vap->iv_essid_be_cnt++; if(index < 0) continue; *frm++ = g_essid_table[index].len; OS_MEMCPY(frm, g_essid_table[index].essid, g_essid_table[index].len); frm += g_essid_table[index].len; break; /* break while */ } /* end while */ if(vap->iv_essid_be_cnt == 4){ vap->iv_essid_be_cnt = 0; } } /* AUTELAN-Added-End : [email protected] */ } frm = ieee80211_add_rates(frm, rs, ic); /* XXX better way to check this? */ if (!IEEE80211_IS_CHAN_FHSS(vap->iv_bsschan)) { *frm++ = IEEE80211_ELEMID_DSPARMS; *frm++ = 1; *frm++ = ieee80211_chan2ieee(ic, vap->iv_bsschan); } bo->bo_tim = frm; if (vap->iv_opmode == IEEE80211_M_IBSS) { *frm++ = IEEE80211_ELEMID_IBSSPARMS; *frm++ = 2; *frm++ = 0; *frm++ = 0; /* TODO: ATIM window */ bo->bo_tim_len = 0; } else { struct ieee80211_tim_ie *tie = (struct ieee80211_tim_ie *) frm; tie->tim_ie = IEEE80211_ELEMID_TIM; tie->tim_len = 4; /* length */ tie->tim_count = 0; /* DTIM count */ tie->tim_period = vap->iv_dtim_period; /* DTIM period */ tie->tim_bitctl = 0; /* bitmap control */ tie->tim_bitmap[0] = 0; /* Partial Virtual Bitmap */ frm += sizeof(struct ieee80211_tim_ie); bo->bo_tim_len = 1; } bo->bo_tim_trailer = frm; if (IEEE80211_IS_COUNTRYIE_ENABLED(ic)) { frm = ieee80211_add_country(frm, vap); } if (ieee80211_ic_doth_is_set(ic) && ieee80211_vap_doth_is_set(vap)) { *frm++ = IEEE80211_ELEMID_PWRCNSTR; *frm++ = 1; *frm++ = IEEE80211_PWRCONSTRAINT_VAL(vap); } bo->bo_chanswitch = frm; #if ATH_SUPPORT_IBSS_DFS if (vap->iv_opmode == IEEE80211_M_IBSS) { if (ieee80211_ibss_dfs_element_enable(vap, ic)) { ieee80211_build_ibss_dfs_ie(vap); bo->bo_ibssdfs = frm; frm = ieee80211_add_ibss_dfs(frm,vap); } else { bo->bo_ibssdfs = NULL; OS_MEMZERO(&vap->iv_ibssdfs_ie_data, sizeof(struct ieee80211_ibssdfs_ie)); } } #endif /* ATH_SUPPORT_IBSS_DFS */ enable_htrates = ieee80211vap_htallowed(vap); if (IEEE80211_IS_CHAN_ANYG(vap->iv_bsschan) || IEEE80211_IS_CHAN_11NG(vap->iv_bsschan)) { bo->bo_erp = frm; frm = ieee80211_add_erp(frm, ic); } /* * check if os shim has setup RSN IE it self. */ IEEE80211_VAP_LOCK(vap); if (vap->iv_app_ie[IEEE80211_FRAME_TYPE_BEACON].length) { add_wpa_ie = ieee80211_check_wpaie(vap, vap->iv_app_ie[IEEE80211_FRAME_TYPE_BEACON].ie, vap->iv_app_ie[IEEE80211_FRAME_TYPE_BEACON].length); } if (vap->iv_opt_ie.length) { add_wpa_ie = ieee80211_check_wpaie(vap, vap->iv_opt_ie.ie, vap->iv_opt_ie.length); } IEEE80211_VAP_UNLOCK(vap); /* XXX: put IEs in the order of element IDs. */ if (add_wpa_ie) { if (RSN_AUTH_IS_RSNA(rsn)) frm = ieee80211_setup_rsn_ie(vap, frm); } #if ATH_SUPPORT_WAPI if (RSN_AUTH_IS_WAI(rsn)) frm = ieee80211_setup_wapi_ie(vap, frm); #endif frm = ieee80211_add_xrates(frm, rs, ic); #ifdef E_CSA bo->bo_extchanswitch = frm; #endif /* E_CSA */ /* * HT cap. check for vap is done in ieee80211vap_htallowed. * TBD: remove iv_bsschan check to support multiple channel operation. */ if (IEEE80211_IS_CHAN_11N(vap->iv_bsschan) && enable_htrates) { bo->bo_htcap = frm; frm = ieee80211_add_htcap(frm, ni, IEEE80211_FC0_SUBTYPE_BEACON); bo->bo_htinfo = frm; frm = ieee80211_add_htinfo(frm, ni); if (!(ic->ic_flags & IEEE80211_F_COEXT_DISABLE)) { bo->bo_obss_scan = frm; frm = ieee80211_add_obss_scan(frm, ni); bo->bo_extcap = frm; frm = ieee80211_add_extcap(frm, ni); } } if (add_wpa_ie) { if (RSN_AUTH_IS_WPA(rsn)) frm = ieee80211_setup_wpa_ie(vap, frm); } if (ieee80211_vap_wme_is_set(vap) && (vap->iv_opmode == IEEE80211_M_HOSTAP || #if ATH_SUPPORT_IBSS_WMM vap->iv_opmode == IEEE80211_M_IBSS || #endif vap->iv_opmode == IEEE80211_M_BTAMP)) { bo->bo_wme = frm; frm = ieee80211_add_wme_param(frm, &ic->ic_wme, IEEE80211_VAP_IS_UAPSD_ENABLED(vap)); vap->iv_flags &= ~IEEE80211_F_WMEUPDATE; } if ((IEEE80211_IS_CHAN_11N(vap->iv_bsschan)) && IEEE80211_IS_HTVIE_ENABLED(ic) && enable_htrates) { frm = ieee80211_add_htcap_vendor_specific(frm, ni,IEEE80211_FC0_SUBTYPE_BEACON); bo->bo_htinfo_vendor_specific = frm; frm = ieee80211_add_htinfo_vendor_specific(frm, ni); } bo->bo_ath_caps = frm; 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); } else { frm = ieee80211_add_athAdvCap(frm, 0, IEEE80211_INVAL_DEFKEY); } /* Insert ieee80211_ie_ath_extcap IE to beacon */ if (ic->ic_ath_extcap) frm = ieee80211_add_athextcap(frm, ic->ic_ath_extcap, ic->ic_weptkipaggr_rxdelim); bo->bo_xr = frm; bo->bo_appie_buf = frm; bo->bo_appie_buf_len = 0; IEEE80211_VAP_LOCK(vap); if (vap->iv_opt_ie.length) { OS_MEMCPY(frm, vap->iv_opt_ie.ie, vap->iv_opt_ie.length); frm += vap->iv_opt_ie.length; } if (vap->iv_app_ie[IEEE80211_FRAME_TYPE_BEACON].length > 0) { OS_MEMCPY(frm,vap->iv_app_ie[IEEE80211_FRAME_TYPE_BEACON].ie, vap->iv_app_ie[IEEE80211_FRAME_TYPE_BEACON].length); frm += vap->iv_app_ie[IEEE80211_FRAME_TYPE_BEACON].length; bo->bo_appie_buf_len = vap->iv_app_ie[IEEE80211_FRAME_TYPE_BEACON].length; } /* Add the Application IE's */ frm = ieee80211_mlme_app_ie_append(vap, IEEE80211_FRAME_TYPE_BEACON, frm); bo->bo_appie_buf_len += vap->iv_app_ie_list[IEEE80211_FRAME_TYPE_BEACON].total_ie_len; IEEE80211_VAP_UNLOCK(vap); bo->bo_tim_trailerlen = frm - bo->bo_tim_trailer; bo->bo_chanswitch_trailerlen = frm - bo->bo_chanswitch; #ifdef E_CSA bo->bo_extchanswitch_trailerlen = frm - bo->bo_extchanswitch; #endif /* E_CSA */ #if ATH_SUPPORT_IBSS_DFS if (vap->iv_opmode == IEEE80211_M_IBSS && (bo->bo_ibssdfs != NULL)) { struct ieee80211_ibssdfs_ie * ibss_dfs_ie = (struct ieee80211_ibssdfs_ie *)bo->bo_ibssdfs; bo->bo_ibssdfs_trailerlen = frm - (bo->bo_ibssdfs + 2 + ibss_dfs_ie->len); } #endif /* ATH_SUPPORT_IBSS_DFS */ return frm; }