void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) { struct sta_info *psta = NULL; struct wlan_network *pwlan = NULL; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; struct wlan_network *tgt_network = &(pmlmepriv->cur_network); if (pcmd->res != H2C_SUCCESS) { RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: rtw_createbss_cmd_callback Fail ************\n\n.")); mod_timer(&pmlmepriv->assoc_timer, jiffies + msecs_to_jiffies(1)); } del_timer_sync(&pmlmepriv->assoc_timer); spin_lock_bh(&pmlmepriv->lock); if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress); if (!psta) { psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress); if (psta == NULL) { RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nCan't alloc sta_info when createbss_cmd_callback\n")); goto createbss_cmd_fail; } } rtw_indicate_connect(padapter); } else { pwlan = _rtw_alloc_network(pmlmepriv); spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); if (pwlan == NULL) { pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue); if (pwlan == NULL) { RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error: can't get pwlan in rtw_joinbss_event_callback\n")); spin_unlock_bh(&pmlmepriv->scanned_queue.lock); goto createbss_cmd_fail; } pwlan->last_scanned = jiffies; } else { list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); } pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork); memcpy(&(pwlan->network), pnetwork, pnetwork->Length); memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork))); _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); spin_unlock_bh(&pmlmepriv->scanned_queue.lock); /* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */ } createbss_cmd_fail: spin_unlock_bh(&pmlmepriv->lock); rtw_free_cmd_obj(pcmd); }
u8 rtw_do_join(_adapter * padapter) { _irqL irqL; _list *plist, *phead; u8* pibss = NULL; struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); _queue *queue = &(pmlmepriv->scanned_queue); u8 ret=_SUCCESS; _func_enter_; _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); phead = get_list_head(queue); plist = get_next(phead); RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("\n rtw_do_join: phead = %p; plist = %p \n\n\n", phead, plist)); pmlmepriv->cur_network.join_res = -2; set_fwstate(pmlmepriv, _FW_UNDER_LINKING); pmlmepriv->pscanned = plist; pmlmepriv->to_join = _TRUE; if(_rtw_queue_empty(queue)== _TRUE) { _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); //when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty //we try to issue sitesurvey firstly if (pmlmepriv->LinkDetectInfo.bBusyTraffic ==_FALSE || rtw_to_roaming(padapter) > 0 ) { RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_do_join(): site survey if scanned_queue is empty\n.")); // submit site_survey_cmd if(_SUCCESS!=(ret=rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)) ) { RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("rtw_do_join(): site survey return error\n.")); } } goto exit; } else { int select_ret; _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); if((select_ret=rtw_select_and_join_from_scanned_queue(pmlmepriv))==_SUCCESS) { pmlmepriv->to_join = _FALSE; _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT); } else if(ret == 2)//there is no need to wait for join { ret = _SUCCESS; _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); rtw_indicate_connect(padapter); } else { if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)==_TRUE) { // submit createbss_cmd to change to a ADHOC_MASTER //pmlmepriv->lock has been acquired by caller... WLAN_BSSID_EX *pdev_network = &(padapter->registrypriv.dev_network); pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE; pibss = padapter->registrypriv.dev_network.MacAddress; _rtw_memset(&pdev_network->Ssid, 0, sizeof(NDIS_802_11_SSID)); _rtw_memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(NDIS_802_11_SSID)); rtw_update_registrypriv_dev_network(padapter); rtw_generate_random_ibss(pibss); if(rtw_createbss_cmd(padapter)!=_SUCCESS) { RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("***Error=>do_goin: rtw_createbss_cmd status FAIL*** \n ")); ret = _FALSE; goto exit; } pmlmepriv->to_join = _FALSE; RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("***Error=> rtw_select_and_join_from_scanned_queue FAIL under STA_Mode*** \n ")); } else { // can't associate ; reset under-linking _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); #if 0 if((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)) { if(_rtw_memcmp(pmlmepriv->cur_network.network.Ssid.Ssid, pmlmepriv->assoc_ssid.Ssid, pmlmepriv->assoc_ssid.SsidLength)) { // for funk to do roaming // funk will reconnect, but funk will not sitesurvey before reconnect RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("for funk to do roaming")); if(pmlmepriv->sitesurveyctrl.traffic_busy==_FALSE) rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0); } } #endif //when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue //we try to issue sitesurvey firstly if(pmlmepriv->LinkDetectInfo.bBusyTraffic==_FALSE || rtw_to_roaming(padapter) > 0 ) { //DBG_871X("rtw_do_join() when no desired bss in scanning queue \n"); if( _SUCCESS!=(ret=rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)) ){ RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("do_join(): site survey return error\n.")); } } } } } exit: _func_exit_; return ret; }
u8 rtw_do_join(struct rtw_adapter *padapter) { struct list_head *plist, *phead; u8 *pibss = NULL; struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); struct __queue *queue = &(pmlmepriv->scanned_queue); u8 ret = _SUCCESS; _func_enter_; spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); phead = get_list_head(queue); plist = get_next(phead); RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("\n rtw_do_join: phead = %p; plist = %p\n\n\n", phead, plist)); pmlmepriv->cur_network.join_res = -2; set_fwstate(pmlmepriv, _FW_UNDER_LINKING); pmlmepriv->pscanned = plist; pmlmepriv->to_join = true; if (_rtw_queue_empty(queue) == true) { spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); /* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */ /* we try to issue sitesurvey firstly */ if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false || rtw_to_roaming(padapter) > 0) { RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("rtw_do_join(): site survey if scanned_queue is empty\n.")); /* submit site_survey_cmd */ ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0); if (_SUCCESS != ret) { RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("rtw_do_join(): site survey return error\n.")); } } goto exit; } else { int select_ret; spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv); if (select_ret == _SUCCESS) { pmlmepriv->to_join = false; _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT); } else if (ret == 2) { /* there is no need to wait for join */ ret = _SUCCESS; _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); rtw_indicate_connect(padapter); } else { if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) { /* submit createbss_cmd to change to a ADHOC_MASTER */ /* pmlmepriv->lock has been acquired by caller... */ struct wlan_bssid_ex *pdev_network = &(padapter->registrypriv.dev_network); pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE; pibss = padapter->registrypriv.dev_network.MacAddress; memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid)); memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid)); rtw_update_registrypriv_dev_network(padapter); rtw_generate_random_ibss(pibss); if (rtw_createbss_cmd(padapter) != _SUCCESS) { RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error=>do_goin: rtw_createbss_cmd status FAIL***\n ")); ret = false; goto exit; } pmlmepriv->to_join = false; RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("***Error=> rtw_select_and_join_from_scanned_queue FAIL under STA_Mode***\n ")); } else { /* can't associate; reset under-linking */ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); /* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */ /* we try to issue sitesurvey firstly */ if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false || rtw_to_roaming(padapter) > 0) { ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0); if (_SUCCESS != ret) RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("do_join(): site survey return error\n.")); } } } } exit: _func_exit_; return ret; }
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; }