int rtw_generate_ie(struct registry_priv *pregistrypriv) { u8 wireless_mode; int sz = 0, rateLen; WLAN_BSSID_EX* pdev_network = &pregistrypriv->dev_network; u8* ie = pdev_network->IEs; _func_enter_; //timestamp will be inserted by hardware sz += 8; ie += sz; //beacon interval : 2bytes *(u16*)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);//BCN_INTERVAL; sz += 2; ie += 2; //capability info *(u16*)ie = 0; *(u16*)ie |= cpu_to_le16(cap_IBSS); if(pregistrypriv->preamble == PREAMBLE_SHORT) *(u16*)ie |= cpu_to_le16(cap_ShortPremble); if (pdev_network->Privacy) *(u16*)ie |= cpu_to_le16(cap_Privacy); sz += 2; ie += 2; //SSID ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz); //supported rates if(pregistrypriv->wireless_mode == WIRELESS_11ABGN) { if(pdev_network->Configuration.DSConfig > 14) wireless_mode = WIRELESS_11A_5N; else wireless_mode = WIRELESS_11BG_24N; } else { wireless_mode = pregistrypriv->wireless_mode; } rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode) ; rateLen = rtw_get_rateset_len(pdev_network->SupportedRates); if (rateLen > 8) { ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz); //ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); } else { ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz); } //DS parameter set ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz); //IBSS Parameter Set ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz); if (rateLen > 8) { ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); } #ifdef CONFIG_80211N_HT //HT Cap. if(((pregistrypriv->wireless_mode&WIRELESS_11_5N)||(pregistrypriv->wireless_mode&WIRELESS_11_24N)) && (pregistrypriv->ht_enable==_TRUE)) { //todo: } #endif //CONFIG_80211N_HT //pdev_network->IELength = sz; //update IELength _func_exit_; //return _SUCCESS; return sz; }
int rtw_generate_ie(struct registry_priv *pregistrypriv) { u8 wireless_mode; int sz = 0, rateLen; struct wlan_bssid_ex*pdev_network = &pregistrypriv->dev_network; u8*ie = pdev_network->IEs; /* timestamp will be inserted by hardware */ sz += 8; ie += sz; /* beacon interval : 2bytes */ *(__le16*)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);/* BCN_INTERVAL; */ sz += 2; ie += 2; /* capability info */ *(u16*)ie = 0; *(__le16*)ie |= cpu_to_le16(cap_IBSS); if (pregistrypriv->preamble == PREAMBLE_SHORT) *(__le16*)ie |= cpu_to_le16(cap_ShortPremble); if (pdev_network->Privacy) *(__le16*)ie |= cpu_to_le16(cap_Privacy); sz += 2; ie += 2; /* SSID */ ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz); /* supported rates */ if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) { if (pdev_network->Configuration.DSConfig > 14) wireless_mode = WIRELESS_11A_5N; else wireless_mode = WIRELESS_11BG_24N; } else { wireless_mode = pregistrypriv->wireless_mode; } rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode) ; rateLen = rtw_get_rateset_len(pdev_network->SupportedRates); if (rateLen > 8) { ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz); /* ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */ } else { ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz); } /* DS parameter set */ ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz); /* IBSS Parameter Set */ ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz); if (rateLen > 8) { ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); } /* HT Cap. */ if (((pregistrypriv->wireless_mode&WIRELESS_11_5N)||(pregistrypriv->wireless_mode&WIRELESS_11_24N)) && (pregistrypriv->ht_enable ==true)) { /* todo: */ } /* pdev_network->IELength = sz; update IELength */ /* return _SUCCESS; */ return sz; }
int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) { int ret = _SUCCESS; u8 *p; u8 *pHT_caps_ie = NULL; u8 *pHT_info_ie = NULL; struct sta_info *psta = NULL; u16 cap, ht_cap = false; uint ie_len = 0; int group_cipher, pairwise_cipher; u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX]; int supportRateNum = 0; u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01}; u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; struct registry_priv *pregistrypriv = &padapter->registrypriv; struct security_priv *psecuritypriv = &padapter->securitypriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_bssid_ex *pbss_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; u8 *ie = pbss_network->ies; /* SSID */ /* Supported rates */ /* DS Params */ /* WLAN_EID_COUNTRY */ /* ERP Information element */ /* Extended supported rates */ /* WPA/WPA2 */ /* Wi-Fi Wireless Multimedia Extensions */ /* ht_capab, ht_oper */ /* WPS IE */ DBG_88E("%s, len =%d\n", __func__, len); if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) return _FAIL; if (len < 0 || len > MAX_IE_SZ) return _FAIL; pbss_network->ie_length = len; memset(ie, 0, MAX_IE_SZ); memcpy(ie, pbuf, pbss_network->ie_length); if (pbss_network->InfrastructureMode != Ndis802_11APMode) return _FAIL; pbss_network->Rssi = 0; ether_addr_copy(pbss_network->MacAddress, myid(&padapter->eeprompriv)); /* beacon interval */ p = rtw_get_beacon_interval_from_ie(ie);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */ pbss_network->Configuration.BeaconPeriod = get_unaligned_le16(p); /* capability */ cap = get_unaligned_le16(ie); /* SSID */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { memset(&pbss_network->Ssid, 0, sizeof(struct ndis_802_11_ssid)); memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len); pbss_network->Ssid.SsidLength = ie_len; } /* channel */ channel = 0; pbss_network->Configuration.Length = 0; p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) channel = *(p + 2); pbss_network->Configuration.DSConfig = channel; memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX); /* get supported rates */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p) { memcpy(supportRate, p + 2, ie_len); supportRateNum = ie_len; } /* get ext_supported rates */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->ie_length - _BEACON_IE_OFFSET_); if (p) { memcpy(supportRate + supportRateNum, p + 2, ie_len); supportRateNum += ie_len; } network_type = rtw_check_network_type(supportRate, supportRateNum, channel); rtw_set_supported_rate(pbss_network->SupportedRates, network_type); /* parsing ERP_IE */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) ERP_IE_handler(padapter, (struct ndis_802_11_var_ie *)p); /* update privacy/security */ if (cap & BIT(4)) pbss_network->Privacy = 1; else pbss_network->Privacy = 0; psecuritypriv->wpa_psk = 0; /* wpa2 */ group_cipher = 0; pairwise_cipher = 0; psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_; psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_; p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { if (rtw_parse_wpa2_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */ psecuritypriv->wpa_psk |= BIT(1); psecuritypriv->wpa2_group_cipher = group_cipher; psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher; } } /* wpa */ ie_len = 0; group_cipher = 0; pairwise_cipher = 0; psecuritypriv->wpa_group_cipher = _NO_PRIVACY_; psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_; for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) { p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2))); if ((p) && (!memcmp(p + 2, OUI1, 4))) { if (rtw_parse_wpa_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */ psecuritypriv->wpa_psk |= BIT(0); psecuritypriv->wpa_group_cipher = group_cipher; psecuritypriv->wpa_pairwise_cipher = pairwise_cipher; } break; } if ((!p) || (ie_len == 0)) break; } /* wmm */ ie_len = 0; pmlmepriv->qospriv.qos_option = 0; if (pregistrypriv->wmm_enable) { for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) { p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2))); if ((p) && !memcmp(p + 2, WMM_PARA_IE, 6)) { pmlmepriv->qospriv.qos_option = 1; /* QoS Info, support U-APSD */ *(p + 8) |= BIT(7); /* disable all ACM bits since the WMM * admission control is not supported */ *(p + 10) &= ~BIT(4); /* BE */ *(p + 14) &= ~BIT(4); /* BK */ *(p + 18) &= ~BIT(4); /* VI */ *(p + 22) &= ~BIT(4); /* VO */ break; } if ((!p) || (ie_len == 0)) break; } } /* parsing HT_CAP_IE */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p + 2); pHT_caps_ie = p; ht_cap = true; network_type |= WIRELESS_11_24N; if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (0x07 << 2)); else pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00); /* set Max Rx AMPDU size to 64K */ pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & 0x03); pht_cap->mcs.rx_mask[0] = 0xff; pht_cap->mcs.rx_mask[1] = 0x0; memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len); } /* parsing HT_INFO_IE */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) pHT_info_ie = p; switch (network_type) { case WIRELESS_11B: pbss_network->NetworkTypeInUse = Ndis802_11DS; break; case WIRELESS_11G: case WIRELESS_11BG: case WIRELESS_11G_24N: case WIRELESS_11BG_24N: pbss_network->NetworkTypeInUse = Ndis802_11OFDM24; break; case WIRELESS_11A: pbss_network->NetworkTypeInUse = Ndis802_11OFDM5; break; default: pbss_network->NetworkTypeInUse = Ndis802_11OFDM24; break; } pmlmepriv->cur_network.network_type = network_type; pmlmepriv->htpriv.ht_option = false; if ((psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) || (psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) { /* todo: */ /* ht_cap = false; */ } /* ht_cap */ if (pregistrypriv->ht_enable && ht_cap) { pmlmepriv->htpriv.ht_option = true; pmlmepriv->qospriv.qos_option = 1; if (pregistrypriv->ampdu_enable == 1) pmlmepriv->htpriv.ampdu_enable = true; HT_caps_handler(padapter, (struct ndis_802_11_var_ie *)pHT_caps_ie); HT_info_handler(padapter, (struct ndis_802_11_var_ie *)pHT_info_ie); } pbss_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pbss_network); /* issue beacon to start bss network */ start_bss_network(padapter, (u8 *)pbss_network); /* alloc sta_info for ap itself */ psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress); if (!psta) { psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress); if (!psta) return _FAIL; } /* fix bug of flush_cam_entry at STOP AP mode */ psta->state |= WIFI_AP_STATE; rtw_indicate_connect(padapter); pmlmepriv->cur_network.join_res = true;/* for check if already set beacon */ return ret; }