diff options
author | Luca Ceresoli <luca@lucaceresoli.net> | 2015-06-12 00:20:43 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-06-12 17:22:05 -0700 |
commit | 4e1023445343541731f45debf718090310cff632 (patch) | |
tree | 43f04a095d9eca6d22ec990dcfe39ad60ab0a240 /drivers/staging/rtl8188eu | |
parent | 5ee35ea7759ae4a6e25f58ff19d8a60b48510aa5 (diff) |
staging: rtl8188eu: rtw_mlme_ext.c: reorder message callbacks and tables
The message handling stored in mlme_sta_tbl and OnAction_tbl are internal and
will be declared static, and their declaration removed from rtw_mlme_ext.h, in
a later commit.
This would break compilation, since they are are referenced before their
definition.
Reorder these functions and the structures that hold them so that symbols are
defined before they are referenced, without the need for forward declarations.
This commit only reorders code, there is no content change.
Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net>
Cc: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/rtl8188eu')
-rw-r--r-- | drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 3291 |
1 files changed, 1645 insertions, 1646 deletions
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 052d0f456956..0d1d4bfc6474 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -29,42 +29,6 @@ #include <mlme_osdep.h> #include <recv_osdep.h> -static struct mlme_handler mlme_sta_tbl[] = { - {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq}, - {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp}, - {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq}, - {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp}, - {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq}, - {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp}, - - /*---------------------------------------------------------- - below 2 are reserved - -----------------------------------------------------------*/ - {0, "DoReserved", &DoReserved}, - {0, "DoReserved", &DoReserved}, - {WIFI_BEACON, "OnBeacon", &OnBeacon}, - {WIFI_ATIM, "OnATIM", &OnAtim}, - {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc}, - {WIFI_AUTH, "OnAuth", &OnAuthClient}, - {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth}, - {WIFI_ACTION, "OnAction", &OnAction}, -}; - -static struct action_handler OnAction_tbl[] = { - {RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct}, - {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos}, - {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls}, - {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back}, - {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public}, - {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved}, - {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &DoReserved}, - {RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht}, - {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved}, - {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm}, - {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p}, -}; - - static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; /************************************************** @@ -195,1616 +159,6 @@ int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch) return i; } -/**************************************************************************** - -Following are the initialization functions for WiFi MLME - -*****************************************************************************/ - -int init_hw_mlme_ext(struct adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - return _SUCCESS; -} - -static void init_mlme_ext_priv_value(struct adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - unsigned char mixed_datarate[NumRates] = { - _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, - _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, - _48M_RATE_, _54M_RATE_, 0xff - }; - unsigned char mixed_basicrate[NumRates] = { - _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, - _12M_RATE_, _24M_RATE_, 0xff, - }; - - atomic_set(&pmlmeext->event_seq, 0); - pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */ - - pmlmeext->cur_channel = padapter->registrypriv.channel; - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pmlmeext->oper_channel = pmlmeext->cur_channel; - pmlmeext->oper_bwmode = pmlmeext->cur_bwmode; - pmlmeext->oper_ch_offset = pmlmeext->cur_ch_offset; - pmlmeext->retry = 0; - - pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode; - - memcpy(pmlmeext->datarate, mixed_datarate, NumRates); - memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates); - - pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; - - pmlmeext->sitesurvey_res.state = SCAN_DISABLE; - pmlmeext->sitesurvey_res.channel_idx = 0; - pmlmeext->sitesurvey_res.bss_cnt = 0; - pmlmeext->scan_abort = false; - - pmlmeinfo->state = WIFI_FW_NULL_STATE; - pmlmeinfo->reauth_count = 0; - pmlmeinfo->reassoc_count = 0; - pmlmeinfo->link_count = 0; - pmlmeinfo->auth_seq = 0; - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; - pmlmeinfo->key_index = 0; - pmlmeinfo->iv = 0; - - pmlmeinfo->enc_algo = _NO_PRIVACY_; - pmlmeinfo->authModeToggle = 0; - - memset(pmlmeinfo->chg_txt, 0, 128); - - pmlmeinfo->slotTime = SHORT_SLOT_TIME; - pmlmeinfo->preamble_mode = PREAMBLE_AUTO; - - pmlmeinfo->dialogToken = 0; - - pmlmeext->action_public_rxseq = 0xffff; - pmlmeext->action_public_dialog_token = 0xff; -} - -static int has_channel(struct rt_channel_info *channel_set, - u8 chanset_size, - u8 chan) { - int i; - - for (i = 0; i < chanset_size; i++) { - if (channel_set[i].ChannelNum == chan) - return 1; - } - return 0; -} - -static void init_channel_list(struct adapter *padapter, struct rt_channel_info *channel_set, - u8 chanset_size, - struct p2p_channels *channel_list) { - struct p2p_oper_class_map op_class[] = { - { IEEE80211G, 81, 1, 13, 1, BW20 }, - { IEEE80211G, 82, 14, 14, 1, BW20 }, - { -1, 0, 0, 0, 0, BW20 } - }; - - int cla, op; - - cla = 0; - - for (op = 0; op_class[op].op_class; op++) { - u8 ch; - struct p2p_oper_class_map *o = &op_class[op]; - struct p2p_reg_class *reg = NULL; - - for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { - if (!has_channel(channel_set, chanset_size, ch)) { - continue; - } - - if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc)) - continue; - - if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) && - ((BW40MINUS == o->bw) || (BW40PLUS == o->bw))) - continue; - - if (reg == NULL) { - reg = &channel_list->reg_class[cla]; - cla++; - reg->reg_class = o->op_class; - reg->channels = 0; - } - reg->channel[reg->channels] = ch; - reg->channels++; - } - } - channel_list->reg_classes = cla; -} - -static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set) -{ - u8 index, chanset_size = 0; - u8 b2_4GBand = false; - u8 Index2G = 0; - - memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM); - - if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) { - DBG_88E("ChannelPlan ID %x error !!!!!\n", ChannelPlan); - return chanset_size; - } - - if (padapter->registrypriv.wireless_mode & WIRELESS_11G) { - b2_4GBand = true; - if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan) - Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G; - else - Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G; - } - - if (b2_4GBand) { - for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) { - channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index]; - - if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */ - (RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == ChannelPlan)) { - if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11) - channel_set[chanset_size].ScanType = SCAN_ACTIVE; - else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14)) - channel_set[chanset_size].ScanType = SCAN_PASSIVE; - } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan || - RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {/* channel 12~13, passive scan */ - if (channel_set[chanset_size].ChannelNum <= 11) - channel_set[chanset_size].ScanType = SCAN_ACTIVE; - else - channel_set[chanset_size].ScanType = SCAN_PASSIVE; - } else { - channel_set[chanset_size].ScanType = SCAN_ACTIVE; - } - - chanset_size++; - } - } - return chanset_size; -} - -int init_mlme_ext_priv(struct adapter *padapter) -{ - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - pmlmeext->padapter = padapter; - - init_mlme_ext_priv_value(padapter); - pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq; - - init_mlme_ext_timer(padapter); - -#ifdef CONFIG_88EU_AP_MODE - init_mlme_ap_info(padapter); -#endif - - pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set); - init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list); - - pmlmeext->chan_scan_time = SURVEY_TO; - pmlmeext->mlmeext_init = true; - - - pmlmeext->active_keep_alive_check = true; - - return _SUCCESS; -} - -void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext) -{ - struct adapter *padapter = pmlmeext->padapter; - - if (!padapter) - return; - - if (padapter->bDriverStopped) { - del_timer_sync(&pmlmeext->survey_timer); - del_timer_sync(&pmlmeext->link_timer); - } -} - -static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, struct recv_frame *precv_frame) -{ - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - u8 *pframe = precv_frame->rx_data; - - if (ptable->func) { - /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ - if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && - memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) - return; - ptable->func(padapter, precv_frame); - } -} - -void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame) -{ - int index; - struct mlme_handler *ptable; -#ifdef CONFIG_88EU_AP_MODE - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; -#endif /* CONFIG_88EU_AP_MODE */ - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - u8 *pframe = precv_frame->rx_data; - struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe)); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("+mgt_dispatcher: type(0x%x) subtype(0x%x)\n", - GetFrameType(pframe), GetFrameSubType(pframe))); - - if (GetFrameType(pframe) != WIFI_MGT_TYPE) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("mgt_dispatcher: type(0x%x) error!\n", GetFrameType(pframe))); - return; - } - - /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ - if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && - memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) - return; - - ptable = mlme_sta_tbl; - - index = GetFrameSubType(pframe) >> 4; - - if (index > 13) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Currently we do not support reserved sub-fr-type=%d\n", index)); - return; - } - ptable += index; - - if (psta != NULL) { - if (GetRetry(pframe)) { - if (precv_frame->attrib.seq_num == - psta->RxMgmtFrameSeqNum) { - /* drop the duplicate management frame */ - DBG_88E("Drop duplicate management frame with seq_num=%d.\n", - precv_frame->attrib.seq_num); - return; - } - } - psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num; - } - -#ifdef CONFIG_88EU_AP_MODE - switch (GetFrameSubType(pframe)) { - case WIFI_AUTH: - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - ptable->func = &OnAuth; - else - ptable->func = &OnAuthClient; - /* fall through */ - case WIFI_ASSOCREQ: - case WIFI_REASSOCREQ: - case WIFI_PROBEREQ: - case WIFI_BEACON: - case WIFI_ACTION: - _mgt_dispatcher(padapter, ptable, precv_frame); - break; - default: - _mgt_dispatcher(padapter, ptable, precv_frame); - break; - } -#else - _mgt_dispatcher(padapter, ptable, precv_frame); -#endif -} - -/**************************************************************************** - -Following are the callback functions for each subtype of the management frames - -*****************************************************************************/ - -unsigned int OnProbeReq(struct adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned int ielen; - unsigned char *p; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct wlan_bssid_ex *cur = &(pmlmeinfo->network); - u8 *pframe = precv_frame->rx_data; - uint len = precv_frame->len; - u8 is_valid_p2p_probereq = false; - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - return _SUCCESS; - - if (!check_fwstate(pmlmepriv, _FW_LINKED) && - !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) - return _SUCCESS; - - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen, - len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); - - /* check (wildcard) SSID */ - if (p != NULL) { - if (is_valid_p2p_probereq) - goto _issue_probersp; - - if ((ielen != 0 && memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) || - (ielen == 0 && pmlmeinfo->hidden_ssid_mode)) - return _SUCCESS; - -_issue_probersp: - - if (check_fwstate(pmlmepriv, _FW_LINKED) && - pmlmepriv->cur_network.join_res) - issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq); - } - return _SUCCESS; -} - -unsigned int OnProbeRsp(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - report_survey_event(padapter, precv_frame); - return _SUCCESS; - } - - return _SUCCESS; -} - -unsigned int OnBeacon(struct adapter *padapter, struct recv_frame *precv_frame) -{ - int cam_idx; - struct sta_info *psta; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 *pframe = precv_frame->rx_data; - uint len = precv_frame->len; - struct wlan_bssid_ex *pbss; - int ret = _SUCCESS; - struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - report_survey_event(padapter, precv_frame); - return _SUCCESS; - } - - if (!memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) { - if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { - /* we should update current network before auth, or some IE is wrong */ - pbss = (struct wlan_bssid_ex *)rtw_malloc(sizeof(struct wlan_bssid_ex)); - if (pbss) { - if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) { - update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true); - rtw_get_bcn_info(&(pmlmepriv->cur_network)); - } - kfree(pbss); - } - - /* check the vendor of the assoc AP */ - pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr), len-sizeof(struct rtw_ieee80211_hdr_3addr)); - - /* update TSF Value */ - update_TSF(pmlmeext, pframe, len); - - /* start auth */ - start_clnt_auth(padapter); - - return _SUCCESS; - } - - if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) { - psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); - if (psta != NULL) { - ret = rtw_check_bcn_info(padapter, pframe, len); - if (!ret) { - DBG_88E_LEVEL(_drv_info_, "ap has changed, disconnect now\n "); - receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 65535); - return _SUCCESS; - } - /* update WMM, ERP in the beacon */ - /* todo: the timer is used instead of the number of the beacon received */ - if ((sta_rx_pkts(psta) & 0xf) == 0) - update_beacon_info(padapter, pframe, len, psta); - } - } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { - psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); - if (psta != NULL) { - /* update WMM, ERP in the beacon */ - /* todo: the timer is used instead of the number of the beacon received */ - if ((sta_rx_pkts(psta) & 0xf) == 0) - update_beacon_info(padapter, pframe, len, psta); - } else { - /* allocate a new CAM entry for IBSS station */ - cam_idx = allocate_fw_sta_entry(padapter); - if (cam_idx == NUM_STA) - goto _END_ONBEACON_; - - /* get supported rate */ - if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) { - pmlmeinfo->FW_sta_info[cam_idx].status = 0; - goto _END_ONBEACON_; - } - - /* update TSF Value */ - update_TSF(pmlmeext, pframe, len); - - /* report sta add event */ - report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx); - } - } - } - -_END_ONBEACON_: - - return _SUCCESS; -} - -unsigned int OnAuth(struct adapter *padapter, struct recv_frame *precv_frame) -{ -#ifdef CONFIG_88EU_AP_MODE - unsigned int auth_mode, ie_len; - u16 seq; - unsigned char *sa, *p; - u16 algorithm; - int status; - static struct sta_info stat; - struct sta_info *pstat = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 *pframe = precv_frame->rx_data; - uint len = precv_frame->len; - - if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) - return _FAIL; - - DBG_88E("+OnAuth\n"); - - sa = GetAddr2Ptr(pframe); - - auth_mode = psecuritypriv->dot11AuthAlgrthm; - seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + 2)); - algorithm = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN)); - - DBG_88E("auth alg=%x, seq=%X\n", algorithm, seq); - - if (auth_mode == 2 && psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ && - psecuritypriv->dot11PrivacyAlgrthm != _WEP104_) - auth_mode = 0; - - if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */ - (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */ - DBG_88E("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n", - algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); - - status = _STATS_NO_SUPP_ALG_; - - goto auth_fail; - } - - if (!rtw_access_ctrl(padapter, sa)) { - status = _STATS_UNABLE_HANDLE_STA_; - goto auth_fail; - } - - pstat = rtw_get_stainfo(pstapriv, sa); - if (pstat == NULL) { - /* allocate a new one */ - DBG_88E("going to alloc stainfo for sa=%pM\n", sa); - pstat = rtw_alloc_stainfo(pstapriv, sa); - if (pstat == NULL) { - DBG_88E(" Exceed the upper limit of supported clients...\n"); - status = _STATS_UNABLE_HANDLE_STA_; - goto auth_fail; - } - - pstat->state = WIFI_FW_AUTH_NULL; - pstat->auth_seq = 0; - } else { - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&pstat->asoc_list)) { - list_del_init(&pstat->asoc_list); - pstapriv->asoc_list_cnt--; - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - if (seq == 1) { - /* TODO: STA re_auth and auth timeout */ - } - } - - spin_lock_bh(&pstapriv->auth_list_lock); - if (list_empty(&pstat->auth_list)) { - list_add_tail(&pstat->auth_list, &pstapriv->auth_list); - pstapriv->auth_list_cnt++; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - if (pstat->auth_seq == 0) - pstat->expire_to = pstapriv->auth_to; - - if ((pstat->auth_seq + 1) != seq) { - DBG_88E("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", - seq, pstat->auth_seq+1); - status = _STATS_OUT_OF_AUTH_SEQ_; - goto auth_fail; - } - - if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) { - if (seq == 1) { - pstat->state &= ~WIFI_FW_AUTH_NULL; - pstat->state |= WIFI_FW_AUTH_SUCCESS; - pstat->expire_to = pstapriv->assoc_to; - pstat->authalg = algorithm; - } else { - DBG_88E("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", - seq, pstat->auth_seq+1); - status = _STATS_OUT_OF_AUTH_SEQ_; - goto auth_fail; - } - } else { /* shared system or auto authentication */ - if (seq == 1) { - /* prepare for the challenging txt... */ - - pstat->state &= ~WIFI_FW_AUTH_NULL; - pstat->state |= WIFI_FW_AUTH_STATE; - pstat->authalg = algorithm; - pstat->auth_seq = 2; - } else if (seq == 3) { - /* checking for challenging txt... */ - DBG_88E("checking for challenging txt...\n"); - - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_ , _CHLGETXT_IE_, (int *)&ie_len, - len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); - - if ((p == NULL) || (ie_len <= 0)) { - DBG_88E("auth rejected because challenge failure!(1)\n"); - status = _STATS_CHALLENGE_FAIL_; - goto auth_fail; - } - - if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) { - pstat->state &= (~WIFI_FW_AUTH_STATE); - pstat->state |= WIFI_FW_AUTH_SUCCESS; - /* challenging txt is correct... */ - pstat->expire_to = pstapriv->assoc_to; - } else { - DBG_88E("auth rejected because challenge failure!\n"); - status = _STATS_CHALLENGE_FAIL_; - goto auth_fail; - } - } else { - DBG_88E("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", - seq, pstat->auth_seq+1); - status = _STATS_OUT_OF_AUTH_SEQ_; - goto auth_fail; - } - } - - /* Now, we are going to issue_auth... */ - pstat->auth_seq = seq + 1; - - issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_)); - - if (pstat->state & WIFI_FW_AUTH_SUCCESS) - pstat->auth_seq = 0; - - return _SUCCESS; - -auth_fail: - - if (pstat) - rtw_free_stainfo(padapter, pstat); - - pstat = &stat; - memset((char *)pstat, '\0', sizeof(stat)); - pstat->auth_seq = 2; - memcpy(pstat->hwaddr, sa, 6); - - issue_auth(padapter, pstat, (unsigned short)status); - -#endif /* CONFIG_88EU_AP_MODE */ - return _FAIL; -} - -unsigned int OnAuthClient(struct adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned int seq, len, status, offset; - unsigned char *p; - unsigned int go2asoc = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 *pframe = precv_frame->rx_data; - uint pkt_len = precv_frame->len; - - DBG_88E("%s\n", __func__); - - /* check A1 matches or not */ - if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN)) - return _SUCCESS; - - if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE)) - return _SUCCESS; - - offset = (GetPrivacy(pframe)) ? 4 : 0; - - seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 2)); - status = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 4)); - - if (status != 0) { - DBG_88E("clnt auth fail, status: %d\n", status); - if (status == 13) { /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */ - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; - else - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; - } - - set_link_timer(pmlmeext, 1); - goto authclnt_fail; - } - - if (seq == 2) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { - /* legendary shared system */ - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len, - pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_); - - if (p == NULL) - goto authclnt_fail; - - memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len); - pmlmeinfo->auth_seq = 3; - issue_auth(padapter, NULL, 0); - set_link_timer(pmlmeext, REAUTH_TO); - - return _SUCCESS; - } else { - /* open system */ - go2asoc = 1; - } - } else if (seq == 4) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) - go2asoc = 1; - else - goto authclnt_fail; - } else { - /* this is also illegal */ - goto authclnt_fail; - } - - if (go2asoc) { - DBG_88E_LEVEL(_drv_info_, "auth success, start assoc\n"); - start_clnt_assoc(padapter); - return _SUCCESS; - } -authclnt_fail: - return _FAIL; -} - -unsigned int OnAssocReq(struct adapter *padapter, struct recv_frame *precv_frame) -{ -#ifdef CONFIG_88EU_AP_MODE - u16 capab_info; - struct rtw_ieee802_11_elems elems; - struct sta_info *pstat; - unsigned char reassoc, *p, *pos, *wpa_ie; - unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; - int i, ie_len, wpa_ie_len, left; - unsigned char supportRate[16]; - int supportRateNum; - unsigned short status = _STATS_SUCCESSFUL_; - unsigned short frame_type, ie_offset = 0; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct wlan_bssid_ex *cur = &(pmlmeinfo->network); - struct sta_priv *pstapriv = &padapter->stapriv; - u8 *pframe = precv_frame->rx_data; - uint pkt_len = precv_frame->len; - - if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) - return _FAIL; - - frame_type = GetFrameSubType(pframe); - if (frame_type == WIFI_ASSOCREQ) { - reassoc = 0; - ie_offset = _ASOCREQ_IE_OFFSET_; - } else { /* WIFI_REASSOCREQ */ - reassoc = 1; - ie_offset = _REASOCREQ_IE_OFFSET_; - } - - - if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) { - DBG_88E("handle_assoc(reassoc=%d) - too short payload (len=%lu)" - "\n", reassoc, (unsigned long)pkt_len); - return _FAIL; - } - - pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); - if (pstat == NULL) { - status = _RSON_CLS2_; - goto asoc_class2_error; - } - - capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN); - - left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset); - pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset); - - - DBG_88E("%s\n", __func__); - - /* check if this stat has been successfully authenticated/assocated */ - if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) { - if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) { - status = _RSON_CLS2_; - goto asoc_class2_error; - } else { - pstat->state &= (~WIFI_FW_ASSOC_SUCCESS); - pstat->state |= WIFI_FW_ASSOC_STATE; - } - } else { - pstat->state &= (~WIFI_FW_AUTH_SUCCESS); - pstat->state |= WIFI_FW_ASSOC_STATE; - } - pstat->capability = capab_info; - /* now parse all ieee802_11 ie to point to elems */ - if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed || - !elems.ssid) { - DBG_88E("STA %pM sent invalid association request\n", - pstat->hwaddr); - status = _STATS_FAILURE_; - goto OnAssocReqFail; - } - - - /* now we should check all the fields... */ - /* checking SSID */ - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len, - pkt_len - WLAN_HDR_A3_LEN - ie_offset); - if (p == NULL) - status = _STATS_FAILURE_; - - if (ie_len == 0) { /* broadcast ssid, however it is not allowed in assocreq */ - status = _STATS_FAILURE_; - } else { - /* check if ssid match */ - if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength)) - status = _STATS_FAILURE_; - - if (ie_len != cur->Ssid.SsidLength) - status = _STATS_FAILURE_; - } - - if (_STATS_SUCCESSFUL_ != status) - goto OnAssocReqFail; - - /* check if the supported rate is ok */ - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); - if (p == NULL) { - DBG_88E("Rx a sta assoc-req which supported rate is empty!\n"); - /* use our own rate set as statoin used */ - /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */ - /* supportRateNum = AP_BSSRATE_LEN; */ - - status = _STATS_FAILURE_; - goto OnAssocReqFail; - } else { - memcpy(supportRate, p+2, ie_len); - supportRateNum = ie_len; - - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_ , &ie_len, - pkt_len - WLAN_HDR_A3_LEN - ie_offset); - if (p != NULL) { - if (supportRateNum <= sizeof(supportRate)) { - memcpy(supportRate+supportRateNum, p+2, ie_len); - supportRateNum += ie_len; - } - } - } - - /* todo: mask supportRate between AP & STA -> move to update raid */ - /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */ - - /* update station supportRate */ - pstat->bssratelen = supportRateNum; - memcpy(pstat->bssrateset, supportRate, supportRateNum); - UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen); - - /* check RSN/WPA/WPS */ - pstat->dot8021xalg = 0; - pstat->wpa_psk = 0; - pstat->wpa_group_cipher = 0; - pstat->wpa2_group_cipher = 0; - pstat->wpa_pairwise_cipher = 0; - pstat->wpa2_pairwise_cipher = 0; - memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie)); - if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) { - int group_cipher = 0, pairwise_cipher = 0; - - wpa_ie = elems.rsn_ie; - wpa_ie_len = elems.rsn_ie_len; - - if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { - pstat->dot8021xalg = 1;/* psk, todo:802.1x */ - pstat->wpa_psk |= BIT(1); - - pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher; - pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher; - - if (!pstat->wpa2_group_cipher) - status = WLAN_STATUS_INVALID_GROUP_CIPHER; - - if (!pstat->wpa2_pairwise_cipher) - status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER; - } else { - status = WLAN_STATUS_INVALID_IE; - } - } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) { - int group_cipher = 0, pairwise_cipher = 0; - - wpa_ie = elems.wpa_ie; - wpa_ie_len = elems.wpa_ie_len; - - if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { - pstat->dot8021xalg = 1;/* psk, todo:802.1x */ - pstat->wpa_psk |= BIT(0); - - pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher; - pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher; - - if (!pstat->wpa_group_cipher) - status = WLAN_STATUS_INVALID_GROUP_CIPHER; - - if (!pstat->wpa_pairwise_cipher) - status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER; - } else { - status = WLAN_STATUS_INVALID_IE; - } - } else { - wpa_ie = NULL; - wpa_ie_len = 0; - } - - if (_STATS_SUCCESSFUL_ != status) - goto OnAssocReqFail; - - pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); - if (wpa_ie == NULL) { - if (elems.wps_ie) { - DBG_88E("STA included WPS IE in " - "(Re)Association Request - assume WPS is " - "used\n"); - pstat->flags |= WLAN_STA_WPS; - /* wpabuf_free(sta->wps_ie); */ - /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */ - /* elems.wps_ie_len - 4); */ - } else { - DBG_88E("STA did not include WPA/RSN IE " - "in (Re)Association Request - possible WPS " - "use\n"); - pstat->flags |= WLAN_STA_MAYBE_WPS; - } - - - /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */ - /* that the selected registrar of AP is _FLASE */ - if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) { - if (pmlmepriv->wps_beacon_ie) { - u8 selected_registrar = 0; - - rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR , &selected_registrar, NULL); - - if (!selected_registrar) { - DBG_88E("selected_registrar is false , or AP is not ready to do WPS\n"); - - status = _STATS_UNABLE_HANDLE_STA_; - - goto OnAssocReqFail; - } - } - } - } else { - int copy_len; - - if (psecuritypriv->wpa_psk == 0) { - DBG_88E("STA %pM: WPA/RSN IE in association " - "request, but AP don't support WPA/RSN\n", pstat->hwaddr); - - status = WLAN_STATUS_INVALID_IE; - - goto OnAssocReqFail; - } - - if (elems.wps_ie) { - DBG_88E("STA included WPS IE in " - "(Re)Association Request - WPS is " - "used\n"); - pstat->flags |= WLAN_STA_WPS; - copy_len = 0; - } else { - copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)) : (wpa_ie_len+2); - } - if (copy_len > 0) - memcpy(pstat->wpa_ie, wpa_ie-2, copy_len); - } - /* check if there is WMM IE & support WWM-PS */ - pstat->flags &= ~WLAN_STA_WME; - pstat->qos_option = 0; - pstat->qos_info = 0; - pstat->has_legacy_ac = true; - pstat->uapsd_vo = 0; - pstat->uapsd_vi = 0; - pstat->uapsd_be = 0; - pstat->uapsd_bk = 0; - if (pmlmepriv->qospriv.qos_option) { - p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0; - for (;;) { - p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); - if (p != NULL) { - if (!memcmp(p+2, WMM_IE, 6)) { - pstat->flags |= WLAN_STA_WME; - - pstat->qos_option = 1; - pstat->qos_info = *(p+8); - - pstat->max_sp_len = (pstat->qos_info>>5)&0x3; - - if ((pstat->qos_info&0xf) != 0xf) - pstat->has_legacy_ac = true; - else - pstat->has_legacy_ac = false; - - if (pstat->qos_info&0xf) { - if (pstat->qos_info&BIT(0)) - pstat->uapsd_vo = BIT(0)|BIT(1); - else - pstat->uapsd_vo = 0; - - if (pstat->qos_info&BIT(1)) - pstat->uapsd_vi = BIT(0)|BIT(1); - else - pstat->uapsd_vi = 0; - - if (pstat->qos_info&BIT(2)) - pstat->uapsd_bk = BIT(0)|BIT(1); - else - pstat->uapsd_bk = 0; - - if (pstat->qos_info&BIT(3)) - pstat->uapsd_be = BIT(0)|BIT(1); - else - pstat->uapsd_be = 0; - } - break; - } - } else { - break; - } - p = p + ie_len + 2; - } - } - - /* save HT capabilities in the sta object */ - memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap)); - if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) { - pstat->flags |= WLAN_STA_HT; - - pstat->flags |= WLAN_STA_WME; - - memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap)); - } else { - pstat->flags &= ~WLAN_STA_HT; - } - if ((!pmlmepriv->htpriv.ht_option) && (pstat->flags&WLAN_STA_HT)) { - status = _STATS_FAILURE_; - goto OnAssocReqFail; - } - - if ((pstat->flags & WLAN_STA_HT) && - ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) || - (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) { - DBG_88E("HT: %pM tried to " - "use TKIP with HT association\n", pstat->hwaddr); - - /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */ - /* goto OnAssocReqFail; */ - } - - pstat->flags |= WLAN_STA_NONERP; - for (i = 0; i < pstat->bssratelen; i++) { - if ((pstat->bssrateset[i] & 0x7f) > 22) { - pstat->flags &= ~WLAN_STA_NONERP; - break; - } - } - - if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - pstat->flags |= WLAN_STA_SHORT_PREAMBLE; - else - pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE; - - - - if (status != _STATS_SUCCESSFUL_) - goto OnAssocReqFail; - - /* TODO: identify_proprietary_vendor_ie(); */ - /* Realtek proprietary IE */ - /* identify if this is Broadcom sta */ - /* identify if this is ralink sta */ - /* Customer proprietary IE */ - - /* get a unique AID */ - if (pstat->aid > 0) { - DBG_88E(" old AID %d\n", pstat->aid); - } else { - for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) - if (pstapriv->sta_aid[pstat->aid - 1] == NULL) - break; - - /* if (pstat->aid > NUM_STA) { */ - if (pstat->aid > pstapriv->max_num_sta) { - pstat->aid = 0; - - DBG_88E(" no room for more AIDs\n"); - - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - - goto OnAssocReqFail; - } else { - pstapriv->sta_aid[pstat->aid - 1] = pstat; - DBG_88E("allocate new AID=(%d)\n", pstat->aid); - } - } - - pstat->state &= (~WIFI_FW_ASSOC_STATE); - pstat->state |= WIFI_FW_ASSOC_SUCCESS; - - spin_lock_bh(&pstapriv->auth_list_lock); - if (!list_empty(&pstat->auth_list)) { - list_del_init(&pstat->auth_list); - pstapriv->auth_list_cnt--; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (list_empty(&pstat->asoc_list)) { - pstat->expire_to = pstapriv->expire_to; - list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list); - pstapriv->asoc_list_cnt++; - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - /* now the station is qualified to join our BSS... */ - if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) { - /* 1 bss_cap_update & sta_info_update */ - bss_cap_update_on_sta_join(padapter, pstat); - sta_info_update(padapter, pstat); - - /* issue assoc rsp before notify station join event. */ - if (frame_type == WIFI_ASSOCREQ) - issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); - else - issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); - - /* 2 - report to upper layer */ - DBG_88E("indicate_sta_join_event to upper layer - hostapd\n"); - rtw_indicate_sta_assoc_event(padapter, pstat); - - /* 3-(1) report sta add event */ - report_add_sta_event(padapter, pstat->hwaddr, pstat->aid); - } - - return _SUCCESS; - -asoc_class2_error: - - issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status); - - return _FAIL; - -OnAssocReqFail: - - pstat->aid = 0; - if (frame_type == WIFI_ASSOCREQ) - issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); - else - issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); - -#endif /* CONFIG_88EU_AP_MODE */ - - return _FAIL; -} - -unsigned int OnAssocRsp(struct adapter *padapter, struct recv_frame *precv_frame) -{ - uint i; - int res; - unsigned short status; - struct ndis_802_11_var_ie *pIE; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */ - u8 *pframe = precv_frame->rx_data; - uint pkt_len = precv_frame->len; - - DBG_88E("%s\n", __func__); - - /* check A1 matches or not */ - if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN)) - return _SUCCESS; - - if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE))) - return _SUCCESS; - - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) - return _SUCCESS; - - del_timer_sync(&pmlmeext->link_timer); - - /* status */ - status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2)); - if (status > 0) { - DBG_88E("assoc reject, status code: %d\n", status); - pmlmeinfo->state = WIFI_FW_NULL_STATE; - res = -4; - goto report_assoc_result; - } - - /* get capabilities */ - pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); - - /* set slot time */ - pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20; - - /* AID */ - pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff); - res = pmlmeinfo->aid; - - /* following are moved to join event callback function */ - /* to handle HT, WMM, rate adaptive, update MAC reg */ - /* for not to handle the synchronous IO in the tasklet */ - for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) { - pIE = (struct ndis_802_11_var_ie *)(pframe + i); - - switch (pIE->ElementID) { - case _VENDOR_SPECIFIC_IE_: - if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */ - WMM_param_handler(padapter, pIE); - break; - case _HT_CAPABILITY_IE_: /* HT caps */ - HT_caps_handler(padapter, pIE); - break; - case _HT_EXTRA_INFO_IE_: /* HT info */ - HT_info_handler(padapter, pIE); - break; - case _ERPINFO_IE_: - ERP_IE_handler(padapter, pIE); - default: - break; - } - - i += (pIE->Length + 2); - } - - pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE); - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - - /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */ - UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates); - -report_assoc_result: - if (res > 0) { - rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len); - } else { - rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len); - } - - report_join_res(padapter, res); - - return _SUCCESS; -} - -unsigned int OnDeAuth(struct adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned short reason; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 *pframe = precv_frame->rx_data; - struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); - - /* check A3 */ - if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) - return _SUCCESS; - - reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); - - DBG_88E("%s Reason code(%d)\n", __func__, reason); - -#ifdef CONFIG_88EU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - DBG_88E_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n", - reason, GetAddr2Ptr(pframe)); - - psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); - if (psta) { - u8 updated = 0; - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&psta->asoc_list)) { - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta(padapter, psta, false, reason); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - associated_clients_update(padapter, updated); - } - - - return _SUCCESS; - } else -#endif - { - DBG_88E_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM\n", - reason, GetAddr3Ptr(pframe)); - - receive_disconnect(padapter, GetAddr3Ptr(pframe) , reason); - } - pmlmepriv->LinkDetectInfo.bBusyTraffic = false; - return _SUCCESS; -} - -unsigned int OnDisassoc(struct adapter *padapter, struct recv_frame *precv_frame) -{ - u16 reason; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 *pframe = precv_frame->rx_data; - struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); - - /* check A3 */ - if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) - return _SUCCESS; - - reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); - - DBG_88E("%s Reason code(%d)\n", __func__, reason); - -#ifdef CONFIG_88EU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n", - reason, GetAddr2Ptr(pframe)); - - psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); - if (psta) { - u8 updated = 0; - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&psta->asoc_list)) { - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta(padapter, psta, false, reason); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - associated_clients_update(padapter, updated); - } - - return _SUCCESS; - } else -#endif - { - DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n", - reason, GetAddr3Ptr(pframe)); - - receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); - } - pmlmepriv->LinkDetectInfo.bBusyTraffic = false; - return _SUCCESS; -} - -unsigned int OnAtim(struct adapter *padapter, struct recv_frame *precv_frame) -{ - DBG_88E("%s\n", __func__); - return _SUCCESS; -} - -unsigned int on_action_spct(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 *pframe = precv_frame->rx_data; - u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); - u8 category; - u8 action; - - DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev)); - - psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); - - if (!psta) - goto exit; - - category = frame_body[0]; - if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT) - goto exit; - - action = frame_body[1]; - switch (action) { - case RTW_WLAN_ACTION_SPCT_MSR_REQ: - case RTW_WLAN_ACTION_SPCT_MSR_RPRT: - case RTW_WLAN_ACTION_SPCT_TPC_REQ: - case RTW_WLAN_ACTION_SPCT_TPC_RPRT: - break; - case RTW_WLAN_ACTION_SPCT_CHL_SWITCH: - break; - default: - break; - } - -exit: - return _FAIL; -} - -unsigned int OnAction_qos(struct adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -unsigned int OnAction_dls(struct adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -unsigned int OnAction_back(struct adapter *padapter, struct recv_frame *precv_frame) -{ - u8 *addr; - struct sta_info *psta = NULL; - struct recv_reorder_ctrl *preorder_ctrl; - unsigned char *frame_body; - unsigned char category, action; - unsigned short tid, status, reason_code = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 *pframe = precv_frame->rx_data; - struct sta_priv *pstapriv = &padapter->stapriv; - /* check RA matches or not */ - if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), - ETH_ALEN))/* for if1, sta/ap mode */ - return _SUCCESS; - - DBG_88E("%s\n", __func__); - - if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) - if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) - return _SUCCESS; - - addr = GetAddr2Ptr(pframe); - psta = rtw_get_stainfo(pstapriv, addr); - - if (psta == NULL) - return _SUCCESS; - - frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); - - category = frame_body[0]; - if (category == RTW_WLAN_CATEGORY_BACK) { /* representing Block Ack */ - if (!pmlmeinfo->HT_enable) - return _SUCCESS; - action = frame_body[1]; - DBG_88E("%s, action=%d\n", __func__, action); - switch (action) { - case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */ - memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request)); - process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr); - - if (pmlmeinfo->bAcceptAddbaReq) - issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0); - else - issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */ - break; - case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */ - status = get_unaligned_le16(&frame_body[3]); - tid = (frame_body[5] >> 2) & 0x7; - if (status == 0) { /* successful */ - DBG_88E("agg_enable for TID=%d\n", tid); - psta->htpriv.agg_enable_bitmap |= 1 << tid; - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - } else { - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - } - break; - case RTW_WLAN_ACTION_DELBA: /* DELBA */ - if ((frame_body[3] & BIT(3)) == 0) { - psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf)); - psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf)); - reason_code = get_unaligned_le16(&frame_body[4]); - } else if ((frame_body[3] & BIT(3)) == BIT(3)) { - tid = (frame_body[3] >> 4) & 0x0F; - preorder_ctrl = &psta->recvreorder_ctrl[tid]; - preorder_ctrl->enable = false; - preorder_ctrl->indicate_seq = 0xffff; - } - DBG_88E("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code); - /* todo: how to notify the host while receiving DELETE BA */ - break; - default: - break; - } - } - return _SUCCESS; -} - -static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token) -{ - struct adapter *adapter = recv_frame->adapter; - struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv); - u8 *frame = recv_frame->rx_data; - u16 seq_ctrl = ((recv_frame->attrib.seq_num&0xffff) << 4) | - (recv_frame->attrib.frag_num & 0xf); - - if (GetRetry(frame)) { - if (token >= 0) { - if ((seq_ctrl == mlmeext->action_public_rxseq) && (token == mlmeext->action_public_dialog_token)) { - DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n", - FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token); - return _FAIL; - } - } else { - if (seq_ctrl == mlmeext->action_public_rxseq) { - DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n", - FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq); - return _FAIL; - } - } - } - - mlmeext->action_public_rxseq = seq_ctrl; - - if (token >= 0) - mlmeext->action_public_dialog_token = token; - - return _SUCCESS; -} - -static unsigned int on_action_public_p2p(struct recv_frame *precv_frame) -{ - u8 *pframe = precv_frame->rx_data; - u8 *frame_body; - u8 dialogToken = 0; - frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); - - dialogToken = frame_body[7]; - - if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL) - return _FAIL; - - return _SUCCESS; -} - -static unsigned int on_action_public_vendor(struct recv_frame *precv_frame) -{ - unsigned int ret = _FAIL; - u8 *pframe = precv_frame->rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); - - if (!memcmp(frame_body + 2, P2P_OUI, 4)) - ret = on_action_public_p2p(precv_frame); - - return ret; -} - -static unsigned int on_action_public_default(struct recv_frame *precv_frame, u8 action) -{ - unsigned int ret = _FAIL; - u8 *pframe = precv_frame->rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); - u8 token; - - token = frame_body[2]; - - if (rtw_action_public_decache(precv_frame, token) == _FAIL) - goto exit; - - ret = _SUCCESS; - -exit: - return ret; -} - -unsigned int on_action_public(struct adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned int ret = _FAIL; - u8 *pframe = precv_frame->rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); - u8 category, action; - - /* check RA matches or not */ - if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN)) - goto exit; - - category = frame_body[0]; - if (category != RTW_WLAN_CATEGORY_PUBLIC) - goto exit; - - action = frame_body[1]; - switch (action) { - case ACT_PUBLIC_VENDOR: - ret = on_action_public_vendor(precv_frame); - break; - default: - ret = on_action_public_default(precv_frame, action); - break; - } - -exit: - return ret; -} - -unsigned int OnAction_ht(struct adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -unsigned int OnAction_wmm(struct adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -unsigned int OnAction_p2p(struct adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -unsigned int OnAction(struct adapter *padapter, struct recv_frame *precv_frame) -{ - int i; - unsigned char category; - struct action_handler *ptable; - unsigned char *frame_body; - u8 *pframe = precv_frame->rx_data; - - frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); - - category = frame_body[0]; - - for (i = 0; i < sizeof(OnAction_tbl)/sizeof(struct action_handler); i++) { - ptable = &OnAction_tbl[i]; - if (category == ptable->num) - ptable->func(padapter, precv_frame); - } - return _SUCCESS; -} - -unsigned int DoReserved(struct adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv) { struct xmit_frame *pmgntframe; @@ -4211,6 +2565,1651 @@ static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid /**************************************************************************** +Following are the callback functions for each subtype of the management frames + +*****************************************************************************/ + +unsigned int OnProbeReq(struct adapter *padapter, struct recv_frame *precv_frame) +{ + unsigned int ielen; + unsigned char *p; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *cur = &(pmlmeinfo->network); + u8 *pframe = precv_frame->rx_data; + uint len = precv_frame->len; + u8 is_valid_p2p_probereq = false; + + if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) + return _SUCCESS; + + if (!check_fwstate(pmlmepriv, _FW_LINKED) && + !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) + return _SUCCESS; + + p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen, + len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); + + /* check (wildcard) SSID */ + if (p != NULL) { + if (is_valid_p2p_probereq) + goto _issue_probersp; + + if ((ielen != 0 && memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) || + (ielen == 0 && pmlmeinfo->hidden_ssid_mode)) + return _SUCCESS; + +_issue_probersp: + + if (check_fwstate(pmlmepriv, _FW_LINKED) && + pmlmepriv->cur_network.join_res) + issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq); + } + return _SUCCESS; +} + +unsigned int OnProbeRsp(struct adapter *padapter, struct recv_frame *precv_frame) +{ + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + + if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { + report_survey_event(padapter, precv_frame); + return _SUCCESS; + } + + return _SUCCESS; +} + +unsigned int OnBeacon(struct adapter *padapter, struct recv_frame *precv_frame) +{ + int cam_idx; + struct sta_info *psta; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct sta_priv *pstapriv = &padapter->stapriv; + u8 *pframe = precv_frame->rx_data; + uint len = precv_frame->len; + struct wlan_bssid_ex *pbss; + int ret = _SUCCESS; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); + + if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { + report_survey_event(padapter, precv_frame); + return _SUCCESS; + } + + if (!memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) { + if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { + /* we should update current network before auth, or some IE is wrong */ + pbss = (struct wlan_bssid_ex *)rtw_malloc(sizeof(struct wlan_bssid_ex)); + if (pbss) { + if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) { + update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true); + rtw_get_bcn_info(&(pmlmepriv->cur_network)); + } + kfree(pbss); + } + + /* check the vendor of the assoc AP */ + pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr), len-sizeof(struct rtw_ieee80211_hdr_3addr)); + + /* update TSF Value */ + update_TSF(pmlmeext, pframe, len); + + /* start auth */ + start_clnt_auth(padapter); + + return _SUCCESS; + } + + if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) { + psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); + if (psta != NULL) { + ret = rtw_check_bcn_info(padapter, pframe, len); + if (!ret) { + DBG_88E_LEVEL(_drv_info_, "ap has changed, disconnect now\n "); + receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 65535); + return _SUCCESS; + } + /* update WMM, ERP in the beacon */ + /* todo: the timer is used instead of the number of the beacon received */ + if ((sta_rx_pkts(psta) & 0xf) == 0) + update_beacon_info(padapter, pframe, len, psta); + } + } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { + psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); + if (psta != NULL) { + /* update WMM, ERP in the beacon */ + /* todo: the timer is used instead of the number of the beacon received */ + if ((sta_rx_pkts(psta) & 0xf) == 0) + update_beacon_info(padapter, pframe, len, psta); + } else { + /* allocate a new CAM entry for IBSS station */ + cam_idx = allocate_fw_sta_entry(padapter); + if (cam_idx == NUM_STA) + goto _END_ONBEACON_; + + /* get supported rate */ + if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) { + pmlmeinfo->FW_sta_info[cam_idx].status = 0; + goto _END_ONBEACON_; + } + + /* update TSF Value */ + update_TSF(pmlmeext, pframe, len); + + /* report sta add event */ + report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx); + } + } + } + +_END_ONBEACON_: + + return _SUCCESS; +} + +unsigned int OnAuth(struct adapter *padapter, struct recv_frame *precv_frame) +{ +#ifdef CONFIG_88EU_AP_MODE + unsigned int auth_mode, ie_len; + u16 seq; + unsigned char *sa, *p; + u16 algorithm; + int status; + static struct sta_info stat; + struct sta_info *pstat = NULL; + struct sta_priv *pstapriv = &padapter->stapriv; + struct security_priv *psecuritypriv = &padapter->securitypriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + u8 *pframe = precv_frame->rx_data; + uint len = precv_frame->len; + + if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) + return _FAIL; + + DBG_88E("+OnAuth\n"); + + sa = GetAddr2Ptr(pframe); + + auth_mode = psecuritypriv->dot11AuthAlgrthm; + seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + 2)); + algorithm = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN)); + + DBG_88E("auth alg=%x, seq=%X\n", algorithm, seq); + + if (auth_mode == 2 && psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ && + psecuritypriv->dot11PrivacyAlgrthm != _WEP104_) + auth_mode = 0; + + if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */ + (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */ + DBG_88E("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n", + algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); + + status = _STATS_NO_SUPP_ALG_; + + goto auth_fail; + } + + if (!rtw_access_ctrl(padapter, sa)) { + status = _STATS_UNABLE_HANDLE_STA_; + goto auth_fail; + } + + pstat = rtw_get_stainfo(pstapriv, sa); + if (pstat == NULL) { + /* allocate a new one */ + DBG_88E("going to alloc stainfo for sa=%pM\n", sa); + pstat = rtw_alloc_stainfo(pstapriv, sa); + if (pstat == NULL) { + DBG_88E(" Exceed the upper limit of supported clients...\n"); + status = _STATS_UNABLE_HANDLE_STA_; + goto auth_fail; + } + + pstat->state = WIFI_FW_AUTH_NULL; + pstat->auth_seq = 0; + } else { + spin_lock_bh(&pstapriv->asoc_list_lock); + if (!list_empty(&pstat->asoc_list)) { + list_del_init(&pstat->asoc_list); + pstapriv->asoc_list_cnt--; + } + spin_unlock_bh(&pstapriv->asoc_list_lock); + + if (seq == 1) { + /* TODO: STA re_auth and auth timeout */ + } + } + + spin_lock_bh(&pstapriv->auth_list_lock); + if (list_empty(&pstat->auth_list)) { + list_add_tail(&pstat->auth_list, &pstapriv->auth_list); + pstapriv->auth_list_cnt++; + } + spin_unlock_bh(&pstapriv->auth_list_lock); + + if (pstat->auth_seq == 0) + pstat->expire_to = pstapriv->auth_to; + + if ((pstat->auth_seq + 1) != seq) { + DBG_88E("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", + seq, pstat->auth_seq+1); + status = _STATS_OUT_OF_AUTH_SEQ_; + goto auth_fail; + } + + if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) { + if (seq == 1) { + pstat->state &= ~WIFI_FW_AUTH_NULL; + pstat->state |= WIFI_FW_AUTH_SUCCESS; + pstat->expire_to = pstapriv->assoc_to; + pstat->authalg = algorithm; + } else { + DBG_88E("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", + seq, pstat->auth_seq+1); + status = _STATS_OUT_OF_AUTH_SEQ_; + goto auth_fail; + } + } else { /* shared system or auto authentication */ + if (seq == 1) { + /* prepare for the challenging txt... */ + + pstat->state &= ~WIFI_FW_AUTH_NULL; + pstat->state |= WIFI_FW_AUTH_STATE; + pstat->authalg = algorithm; + pstat->auth_seq = 2; + } else if (seq == 3) { + /* checking for challenging txt... */ + DBG_88E("checking for challenging txt...\n"); + + p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_ , _CHLGETXT_IE_, (int *)&ie_len, + len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); + + if ((p == NULL) || (ie_len <= 0)) { + DBG_88E("auth rejected because challenge failure!(1)\n"); + status = _STATS_CHALLENGE_FAIL_; + goto auth_fail; + } + + if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) { + pstat->state &= (~WIFI_FW_AUTH_STATE); + pstat->state |= WIFI_FW_AUTH_SUCCESS; + /* challenging txt is correct... */ + pstat->expire_to = pstapriv->assoc_to; + } else { + DBG_88E("auth rejected because challenge failure!\n"); + status = _STATS_CHALLENGE_FAIL_; + goto auth_fail; + } + } else { + DBG_88E("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", + seq, pstat->auth_seq+1); + status = _STATS_OUT_OF_AUTH_SEQ_; + goto auth_fail; + } + } + + /* Now, we are going to issue_auth... */ + pstat->auth_seq = seq + 1; + + issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_)); + + if (pstat->state & WIFI_FW_AUTH_SUCCESS) + pstat->auth_seq = 0; + + return _SUCCESS; + +auth_fail: + + if (pstat) + rtw_free_stainfo(padapter, pstat); + + pstat = &stat; + memset((char *)pstat, '\0', sizeof(stat)); + pstat->auth_seq = 2; + memcpy(pstat->hwaddr, sa, 6); + + issue_auth(padapter, pstat, (unsigned short)status); + +#endif /* CONFIG_88EU_AP_MODE */ + return _FAIL; +} + +unsigned int OnAuthClient(struct adapter *padapter, struct recv_frame *precv_frame) +{ + unsigned int seq, len, status, offset; + unsigned char *p; + unsigned int go2asoc = 0; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + u8 *pframe = precv_frame->rx_data; + uint pkt_len = precv_frame->len; + + DBG_88E("%s\n", __func__); + + /* check A1 matches or not */ + if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN)) + return _SUCCESS; + + if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE)) + return _SUCCESS; + + offset = (GetPrivacy(pframe)) ? 4 : 0; + + seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 2)); + status = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 4)); + + if (status != 0) { + DBG_88E("clnt auth fail, status: %d\n", status); + if (status == 13) { /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */ + if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) + pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; + else + pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; + } + + set_link_timer(pmlmeext, 1); + goto authclnt_fail; + } + + if (seq == 2) { + if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { + /* legendary shared system */ + p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len, + pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_); + + if (p == NULL) + goto authclnt_fail; + + memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len); + pmlmeinfo->auth_seq = 3; + issue_auth(padapter, NULL, 0); + set_link_timer(pmlmeext, REAUTH_TO); + + return _SUCCESS; + } else { + /* open system */ + go2asoc = 1; + } + } else if (seq == 4) { + if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) + go2asoc = 1; + else + goto authclnt_fail; + } else { + /* this is also illegal */ + goto authclnt_fail; + } + + if (go2asoc) { + DBG_88E_LEVEL(_drv_info_, "auth success, start assoc\n"); + start_clnt_assoc(padapter); + return _SUCCESS; + } +authclnt_fail: + return _FAIL; +} + +unsigned int OnAssocReq(struct adapter *padapter, struct recv_frame *precv_frame) +{ +#ifdef CONFIG_88EU_AP_MODE + u16 capab_info; + struct rtw_ieee802_11_elems elems; + struct sta_info *pstat; + unsigned char reassoc, *p, *pos, *wpa_ie; + unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; + int i, ie_len, wpa_ie_len, left; + unsigned char supportRate[16]; + int supportRateNum; + unsigned short status = _STATS_SUCCESSFUL_; + unsigned short frame_type, ie_offset = 0; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct security_priv *psecuritypriv = &padapter->securitypriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *cur = &(pmlmeinfo->network); + struct sta_priv *pstapriv = &padapter->stapriv; + u8 *pframe = precv_frame->rx_data; + uint pkt_len = precv_frame->len; + + if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) + return _FAIL; + + frame_type = GetFrameSubType(pframe); + if (frame_type == WIFI_ASSOCREQ) { + reassoc = 0; + ie_offset = _ASOCREQ_IE_OFFSET_; + } else { /* WIFI_REASSOCREQ */ + reassoc = 1; + ie_offset = _REASOCREQ_IE_OFFSET_; + } + + + if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) { + DBG_88E("handle_assoc(reassoc=%d) - too short payload (len=%lu)" + "\n", reassoc, (unsigned long)pkt_len); + return _FAIL; + } + + pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); + if (pstat == NULL) { + status = _RSON_CLS2_; + goto asoc_class2_error; + } + + capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN); + + left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset); + pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset); + + + DBG_88E("%s\n", __func__); + + /* check if this stat has been successfully authenticated/assocated */ + if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) { + if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) { + status = _RSON_CLS2_; + goto asoc_class2_error; + } else { + pstat->state &= (~WIFI_FW_ASSOC_SUCCESS); + pstat->state |= WIFI_FW_ASSOC_STATE; + } + } else { + pstat->state &= (~WIFI_FW_AUTH_SUCCESS); + pstat->state |= WIFI_FW_ASSOC_STATE; + } + pstat->capability = capab_info; + /* now parse all ieee802_11 ie to point to elems */ + if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed || + !elems.ssid) { + DBG_88E("STA %pM sent invalid association request\n", + pstat->hwaddr); + status = _STATS_FAILURE_; + goto OnAssocReqFail; + } + + + /* now we should check all the fields... */ + /* checking SSID */ + p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len, + pkt_len - WLAN_HDR_A3_LEN - ie_offset); + if (p == NULL) + status = _STATS_FAILURE_; + + if (ie_len == 0) { /* broadcast ssid, however it is not allowed in assocreq */ + status = _STATS_FAILURE_; + } else { + /* check if ssid match */ + if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength)) + status = _STATS_FAILURE_; + + if (ie_len != cur->Ssid.SsidLength) + status = _STATS_FAILURE_; + } + + if (_STATS_SUCCESSFUL_ != status) + goto OnAssocReqFail; + + /* check if the supported rate is ok */ + p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); + if (p == NULL) { + DBG_88E("Rx a sta assoc-req which supported rate is empty!\n"); + /* use our own rate set as statoin used */ + /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */ + /* supportRateNum = AP_BSSRATE_LEN; */ + + status = _STATS_FAILURE_; + goto OnAssocReqFail; + } else { + memcpy(supportRate, p+2, ie_len); + supportRateNum = ie_len; + + p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_ , &ie_len, + pkt_len - WLAN_HDR_A3_LEN - ie_offset); + if (p != NULL) { + if (supportRateNum <= sizeof(supportRate)) { + memcpy(supportRate+supportRateNum, p+2, ie_len); + supportRateNum += ie_len; + } + } + } + + /* todo: mask supportRate between AP & STA -> move to update raid */ + /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */ + + /* update station supportRate */ + pstat->bssratelen = supportRateNum; + memcpy(pstat->bssrateset, supportRate, supportRateNum); + UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen); + + /* check RSN/WPA/WPS */ + pstat->dot8021xalg = 0; + pstat->wpa_psk = 0; + pstat->wpa_group_cipher = 0; + pstat->wpa2_group_cipher = 0; + pstat->wpa_pairwise_cipher = 0; + pstat->wpa2_pairwise_cipher = 0; + memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie)); + if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) { + int group_cipher = 0, pairwise_cipher = 0; + + wpa_ie = elems.rsn_ie; + wpa_ie_len = elems.rsn_ie_len; + + if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + pstat->dot8021xalg = 1;/* psk, todo:802.1x */ + pstat->wpa_psk |= BIT(1); + + pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher; + pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher; + + if (!pstat->wpa2_group_cipher) + status = WLAN_STATUS_INVALID_GROUP_CIPHER; + + if (!pstat->wpa2_pairwise_cipher) + status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER; + } else { + status = WLAN_STATUS_INVALID_IE; + } + } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) { + int group_cipher = 0, pairwise_cipher = 0; + + wpa_ie = elems.wpa_ie; + wpa_ie_len = elems.wpa_ie_len; + + if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + pstat->dot8021xalg = 1;/* psk, todo:802.1x */ + pstat->wpa_psk |= BIT(0); + + pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher; + pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher; + + if (!pstat->wpa_group_cipher) + status = WLAN_STATUS_INVALID_GROUP_CIPHER; + + if (!pstat->wpa_pairwise_cipher) + status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER; + } else { + status = WLAN_STATUS_INVALID_IE; + } + } else { + wpa_ie = NULL; + wpa_ie_len = 0; + } + + if (_STATS_SUCCESSFUL_ != status) + goto OnAssocReqFail; + + pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); + if (wpa_ie == NULL) { + if (elems.wps_ie) { + DBG_88E("STA included WPS IE in " + "(Re)Association Request - assume WPS is " + "used\n"); + pstat->flags |= WLAN_STA_WPS; + /* wpabuf_free(sta->wps_ie); */ + /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */ + /* elems.wps_ie_len - 4); */ + } else { + DBG_88E("STA did not include WPA/RSN IE " + "in (Re)Association Request - possible WPS " + "use\n"); + pstat->flags |= WLAN_STA_MAYBE_WPS; + } + + + /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */ + /* that the selected registrar of AP is _FLASE */ + if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) { + if (pmlmepriv->wps_beacon_ie) { + u8 selected_registrar = 0; + + rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR , &selected_registrar, NULL); + + if (!selected_registrar) { + DBG_88E("selected_registrar is false , or AP is not ready to do WPS\n"); + + status = _STATS_UNABLE_HANDLE_STA_; + + goto OnAssocReqFail; + } + } + } + } else { + int copy_len; + + if (psecuritypriv->wpa_psk == 0) { + DBG_88E("STA %pM: WPA/RSN IE in association " + "request, but AP don't support WPA/RSN\n", pstat->hwaddr); + + status = WLAN_STATUS_INVALID_IE; + + goto OnAssocReqFail; + } + + if (elems.wps_ie) { + DBG_88E("STA included WPS IE in " + "(Re)Association Request - WPS is " + "used\n"); + pstat->flags |= WLAN_STA_WPS; + copy_len = 0; + } else { + copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)) : (wpa_ie_len+2); + } + if (copy_len > 0) + memcpy(pstat->wpa_ie, wpa_ie-2, copy_len); + } + /* check if there is WMM IE & support WWM-PS */ + pstat->flags &= ~WLAN_STA_WME; + pstat->qos_option = 0; + pstat->qos_info = 0; + pstat->has_legacy_ac = true; + pstat->uapsd_vo = 0; + pstat->uapsd_vi = 0; + pstat->uapsd_be = 0; + pstat->uapsd_bk = 0; + if (pmlmepriv->qospriv.qos_option) { + p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0; + for (;;) { + p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); + if (p != NULL) { + if (!memcmp(p+2, WMM_IE, 6)) { + pstat->flags |= WLAN_STA_WME; + + pstat->qos_option = 1; + pstat->qos_info = *(p+8); + + pstat->max_sp_len = (pstat->qos_info>>5)&0x3; + + if ((pstat->qos_info&0xf) != 0xf) + pstat->has_legacy_ac = true; + else + pstat->has_legacy_ac = false; + + if (pstat->qos_info&0xf) { + if (pstat->qos_info&BIT(0)) + pstat->uapsd_vo = BIT(0)|BIT(1); + else + pstat->uapsd_vo = 0; + + if (pstat->qos_info&BIT(1)) + pstat->uapsd_vi = BIT(0)|BIT(1); + else + pstat->uapsd_vi = 0; + + if (pstat->qos_info&BIT(2)) + pstat->uapsd_bk = BIT(0)|BIT(1); + else + pstat->uapsd_bk = 0; + + if (pstat->qos_info&BIT(3)) + pstat->uapsd_be = BIT(0)|BIT(1); + else + pstat->uapsd_be = 0; + } + break; + } + } else { + break; + } + p = p + ie_len + 2; + } + } + + /* save HT capabilities in the sta object */ + memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap)); + if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) { + pstat->flags |= WLAN_STA_HT; + + pstat->flags |= WLAN_STA_WME; + + memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap)); + } else { + pstat->flags &= ~WLAN_STA_HT; + } + if ((!pmlmepriv->htpriv.ht_option) && (pstat->flags&WLAN_STA_HT)) { + status = _STATS_FAILURE_; + goto OnAssocReqFail; + } + + if ((pstat->flags & WLAN_STA_HT) && + ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) || + (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) { + DBG_88E("HT: %pM tried to " + "use TKIP with HT association\n", pstat->hwaddr); + + /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */ + /* goto OnAssocReqFail; */ + } + + pstat->flags |= WLAN_STA_NONERP; + for (i = 0; i < pstat->bssratelen; i++) { + if ((pstat->bssrateset[i] & 0x7f) > 22) { + pstat->flags &= ~WLAN_STA_NONERP; + break; + } + } + + if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + pstat->flags |= WLAN_STA_SHORT_PREAMBLE; + else + pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE; + + + + if (status != _STATS_SUCCESSFUL_) + goto OnAssocReqFail; + + /* TODO: identify_proprietary_vendor_ie(); */ + /* Realtek proprietary IE */ + /* identify if this is Broadcom sta */ + /* identify if this is ralink sta */ + /* Customer proprietary IE */ + + /* get a unique AID */ + if (pstat->aid > 0) { + DBG_88E(" old AID %d\n", pstat->aid); + } else { + for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) + if (pstapriv->sta_aid[pstat->aid - 1] == NULL) + break; + + /* if (pstat->aid > NUM_STA) { */ + if (pstat->aid > pstapriv->max_num_sta) { + pstat->aid = 0; + + DBG_88E(" no room for more AIDs\n"); + + status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + + goto OnAssocReqFail; + } else { + pstapriv->sta_aid[pstat->aid - 1] = pstat; + DBG_88E("allocate new AID=(%d)\n", pstat->aid); + } + } + + pstat->state &= (~WIFI_FW_ASSOC_STATE); + pstat->state |= WIFI_FW_ASSOC_SUCCESS; + + spin_lock_bh(&pstapriv->auth_list_lock); + if (!list_empty(&pstat->auth_list)) { + list_del_init(&pstat->auth_list); + pstapriv->auth_list_cnt--; + } + spin_unlock_bh(&pstapriv->auth_list_lock); + + spin_lock_bh(&pstapriv->asoc_list_lock); + if (list_empty(&pstat->asoc_list)) { + pstat->expire_to = pstapriv->expire_to; + list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list); + pstapriv->asoc_list_cnt++; + } + spin_unlock_bh(&pstapriv->asoc_list_lock); + + /* now the station is qualified to join our BSS... */ + if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) { + /* 1 bss_cap_update & sta_info_update */ + bss_cap_update_on_sta_join(padapter, pstat); + sta_info_update(padapter, pstat); + + /* issue assoc rsp before notify station join event. */ + if (frame_type == WIFI_ASSOCREQ) + issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); + else + issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); + + /* 2 - report to upper layer */ + DBG_88E("indicate_sta_join_event to upper layer - hostapd\n"); + rtw_indicate_sta_assoc_event(padapter, pstat); + + /* 3-(1) report sta add event */ + report_add_sta_event(padapter, pstat->hwaddr, pstat->aid); + } + + return _SUCCESS; + +asoc_class2_error: + + issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status); + + return _FAIL; + +OnAssocReqFail: + + pstat->aid = 0; + if (frame_type == WIFI_ASSOCREQ) + issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); + else + issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); + +#endif /* CONFIG_88EU_AP_MODE */ + + return _FAIL; +} + +unsigned int OnAssocRsp(struct adapter *padapter, struct recv_frame *precv_frame) +{ + uint i; + int res; + unsigned short status; + struct ndis_802_11_var_ie *pIE; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */ + u8 *pframe = precv_frame->rx_data; + uint pkt_len = precv_frame->len; + + DBG_88E("%s\n", __func__); + + /* check A1 matches or not */ + if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN)) + return _SUCCESS; + + if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE))) + return _SUCCESS; + + if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) + return _SUCCESS; + + del_timer_sync(&pmlmeext->link_timer); + + /* status */ + status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2)); + if (status > 0) { + DBG_88E("assoc reject, status code: %d\n", status); + pmlmeinfo->state = WIFI_FW_NULL_STATE; + res = -4; + goto report_assoc_result; + } + + /* get capabilities */ + pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); + + /* set slot time */ + pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20; + + /* AID */ + pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff); + res = pmlmeinfo->aid; + + /* following are moved to join event callback function */ + /* to handle HT, WMM, rate adaptive, update MAC reg */ + /* for not to handle the synchronous IO in the tasklet */ + for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) { + pIE = (struct ndis_802_11_var_ie *)(pframe + i); + + switch (pIE->ElementID) { + case _VENDOR_SPECIFIC_IE_: + if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */ + WMM_param_handler(padapter, pIE); + break; + case _HT_CAPABILITY_IE_: /* HT caps */ + HT_caps_handler(padapter, pIE); + break; + case _HT_EXTRA_INFO_IE_: /* HT info */ + HT_info_handler(padapter, pIE); + break; + case _ERPINFO_IE_: + ERP_IE_handler(padapter, pIE); + default: + break; + } + + i += (pIE->Length + 2); + } + + pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE); + pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; + + /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */ + UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates); + +report_assoc_result: + if (res > 0) { + rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len); + } else { + rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len); + } + + report_join_res(padapter, res); + + return _SUCCESS; +} + +unsigned int OnDeAuth(struct adapter *padapter, struct recv_frame *precv_frame) +{ + unsigned short reason; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + u8 *pframe = precv_frame->rx_data; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); + + /* check A3 */ + if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) + return _SUCCESS; + + reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); + + DBG_88E("%s Reason code(%d)\n", __func__, reason); + +#ifdef CONFIG_88EU_AP_MODE + if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { + struct sta_info *psta; + struct sta_priv *pstapriv = &padapter->stapriv; + + DBG_88E_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n", + reason, GetAddr2Ptr(pframe)); + + psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); + if (psta) { + u8 updated = 0; + + spin_lock_bh(&pstapriv->asoc_list_lock); + if (!list_empty(&psta->asoc_list)) { + list_del_init(&psta->asoc_list); + pstapriv->asoc_list_cnt--; + updated = ap_free_sta(padapter, psta, false, reason); + } + spin_unlock_bh(&pstapriv->asoc_list_lock); + + associated_clients_update(padapter, updated); + } + + + return _SUCCESS; + } else +#endif + { + DBG_88E_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM\n", + reason, GetAddr3Ptr(pframe)); + + receive_disconnect(padapter, GetAddr3Ptr(pframe) , reason); + } + pmlmepriv->LinkDetectInfo.bBusyTraffic = false; + return _SUCCESS; +} + +unsigned int OnDisassoc(struct adapter *padapter, struct recv_frame *precv_frame) +{ + u16 reason; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + u8 *pframe = precv_frame->rx_data; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); + + /* check A3 */ + if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) + return _SUCCESS; + + reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); + + DBG_88E("%s Reason code(%d)\n", __func__, reason); + +#ifdef CONFIG_88EU_AP_MODE + if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { + struct sta_info *psta; + struct sta_priv *pstapriv = &padapter->stapriv; + + DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n", + reason, GetAddr2Ptr(pframe)); + + psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); + if (psta) { + u8 updated = 0; + + spin_lock_bh(&pstapriv->asoc_list_lock); + if (!list_empty(&psta->asoc_list)) { + list_del_init(&psta->asoc_list); + pstapriv->asoc_list_cnt--; + updated = ap_free_sta(padapter, psta, false, reason); + } + spin_unlock_bh(&pstapriv->asoc_list_lock); + + associated_clients_update(padapter, updated); + } + + return _SUCCESS; + } else +#endif + { + DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n", + reason, GetAddr3Ptr(pframe)); + + receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); + } + pmlmepriv->LinkDetectInfo.bBusyTraffic = false; + return _SUCCESS; +} + +unsigned int OnAtim(struct adapter *padapter, struct recv_frame *precv_frame) +{ + DBG_88E("%s\n", __func__); + return _SUCCESS; +} + +unsigned int on_action_spct(struct adapter *padapter, struct recv_frame *precv_frame) +{ + struct sta_info *psta = NULL; + struct sta_priv *pstapriv = &padapter->stapriv; + u8 *pframe = precv_frame->rx_data; + u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + u8 category; + u8 action; + + DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev)); + + psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); + + if (!psta) + goto exit; + + category = frame_body[0]; + if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT) + goto exit; + + action = frame_body[1]; + switch (action) { + case RTW_WLAN_ACTION_SPCT_MSR_REQ: + case RTW_WLAN_ACTION_SPCT_MSR_RPRT: + case RTW_WLAN_ACTION_SPCT_TPC_REQ: + case RTW_WLAN_ACTION_SPCT_TPC_RPRT: + break; + case RTW_WLAN_ACTION_SPCT_CHL_SWITCH: + break; + default: + break; + } + +exit: + return _FAIL; +} + +unsigned int OnAction_qos(struct adapter *padapter, struct recv_frame *precv_frame) +{ + return _SUCCESS; +} + +unsigned int OnAction_dls(struct adapter *padapter, struct recv_frame *precv_frame) +{ + return _SUCCESS; +} + +unsigned int OnAction_back(struct adapter *padapter, struct recv_frame *precv_frame) +{ + u8 *addr; + struct sta_info *psta = NULL; + struct recv_reorder_ctrl *preorder_ctrl; + unsigned char *frame_body; + unsigned char category, action; + unsigned short tid, status, reason_code = 0; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + u8 *pframe = precv_frame->rx_data; + struct sta_priv *pstapriv = &padapter->stapriv; + /* check RA matches or not */ + if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), + ETH_ALEN))/* for if1, sta/ap mode */ + return _SUCCESS; + + DBG_88E("%s\n", __func__); + + if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) + if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) + return _SUCCESS; + + addr = GetAddr2Ptr(pframe); + psta = rtw_get_stainfo(pstapriv, addr); + + if (psta == NULL) + return _SUCCESS; + + frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + + category = frame_body[0]; + if (category == RTW_WLAN_CATEGORY_BACK) { /* representing Block Ack */ + if (!pmlmeinfo->HT_enable) + return _SUCCESS; + action = frame_body[1]; + DBG_88E("%s, action=%d\n", __func__, action); + switch (action) { + case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */ + memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request)); + process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr); + + if (pmlmeinfo->bAcceptAddbaReq) + issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0); + else + issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */ + break; + case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */ + status = get_unaligned_le16(&frame_body[3]); + tid = (frame_body[5] >> 2) & 0x7; + if (status == 0) { /* successful */ + DBG_88E("agg_enable for TID=%d\n", tid); + psta->htpriv.agg_enable_bitmap |= 1 << tid; + psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); + } else { + psta->htpriv.agg_enable_bitmap &= ~BIT(tid); + } + break; + case RTW_WLAN_ACTION_DELBA: /* DELBA */ + if ((frame_body[3] & BIT(3)) == 0) { + psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf)); + psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf)); + reason_code = get_unaligned_le16(&frame_body[4]); + } else if ((frame_body[3] & BIT(3)) == BIT(3)) { + tid = (frame_body[3] >> 4) & 0x0F; + preorder_ctrl = &psta->recvreorder_ctrl[tid]; + preorder_ctrl->enable = false; + preorder_ctrl->indicate_seq = 0xffff; + } + DBG_88E("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code); + /* todo: how to notify the host while receiving DELETE BA */ + break; + default: + break; + } + } + return _SUCCESS; +} + +static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token) +{ + struct adapter *adapter = recv_frame->adapter; + struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv); + u8 *frame = recv_frame->rx_data; + u16 seq_ctrl = ((recv_frame->attrib.seq_num&0xffff) << 4) | + (recv_frame->attrib.frag_num & 0xf); + + if (GetRetry(frame)) { + if (token >= 0) { + if ((seq_ctrl == mlmeext->action_public_rxseq) && (token == mlmeext->action_public_dialog_token)) { + DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n", + FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token); + return _FAIL; + } + } else { + if (seq_ctrl == mlmeext->action_public_rxseq) { + DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n", + FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq); + return _FAIL; + } + } + } + + mlmeext->action_public_rxseq = seq_ctrl; + + if (token >= 0) + mlmeext->action_public_dialog_token = token; + + return _SUCCESS; +} + +static unsigned int on_action_public_p2p(struct recv_frame *precv_frame) +{ + u8 *pframe = precv_frame->rx_data; + u8 *frame_body; + u8 dialogToken = 0; + frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + + dialogToken = frame_body[7]; + + if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL) + return _FAIL; + + return _SUCCESS; +} + +static unsigned int on_action_public_vendor(struct recv_frame *precv_frame) +{ + unsigned int ret = _FAIL; + u8 *pframe = precv_frame->rx_data; + u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + + if (!memcmp(frame_body + 2, P2P_OUI, 4)) + ret = on_action_public_p2p(precv_frame); + + return ret; +} + +static unsigned int on_action_public_default(struct recv_frame *precv_frame, u8 action) +{ + unsigned int ret = _FAIL; + u8 *pframe = precv_frame->rx_data; + u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + u8 token; + + token = frame_body[2]; + + if (rtw_action_public_decache(precv_frame, token) == _FAIL) + goto exit; + + ret = _SUCCESS; + +exit: + return ret; +} + +unsigned int on_action_public(struct adapter *padapter, struct recv_frame *precv_frame) +{ + unsigned int ret = _FAIL; + u8 *pframe = precv_frame->rx_data; + u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + u8 category, action; + + /* check RA matches or not */ + if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN)) + goto exit; + + category = frame_body[0]; + if (category != RTW_WLAN_CATEGORY_PUBLIC) + goto exit; + + action = frame_body[1]; + switch (action) { + case ACT_PUBLIC_VENDOR: + ret = on_action_public_vendor(precv_frame); + break; + default: + ret = on_action_public_default(precv_frame, action); + break; + } + +exit: + return ret; +} + +unsigned int OnAction_ht(struct adapter *padapter, struct recv_frame *precv_frame) +{ + return _SUCCESS; +} + +unsigned int OnAction_wmm(struct adapter *padapter, struct recv_frame *precv_frame) +{ + return _SUCCESS; +} + +unsigned int OnAction_p2p(struct adapter *padapter, struct recv_frame *precv_frame) +{ + return _SUCCESS; +} + +unsigned int DoReserved(struct adapter *padapter, struct recv_frame *precv_frame) +{ + return _SUCCESS; +} + +static struct action_handler OnAction_tbl[] = { + {RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct}, + {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos}, + {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls}, + {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back}, + {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public}, + {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved}, + {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &DoReserved}, + {RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht}, + {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved}, + {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm}, + {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p}, +}; + +unsigned int OnAction(struct adapter *padapter, struct recv_frame *precv_frame) +{ + int i; + unsigned char category; + struct action_handler *ptable; + unsigned char *frame_body; + u8 *pframe = precv_frame->rx_data; + + frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + + category = frame_body[0]; + + for (i = 0; i < sizeof(OnAction_tbl)/sizeof(struct action_handler); i++) { + ptable = &OnAction_tbl[i]; + if (category == ptable->num) + ptable->func(padapter, precv_frame); + } + return _SUCCESS; +} + +/**************************************************************************** + +Following are the initialization functions for WiFi MLME + +*****************************************************************************/ + +static struct mlme_handler mlme_sta_tbl[] = { + {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq}, + {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp}, + {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq}, + {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp}, + {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq}, + {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp}, + + /*---------------------------------------------------------- + below 2 are reserved + -----------------------------------------------------------*/ + {0, "DoReserved", &DoReserved}, + {0, "DoReserved", &DoReserved}, + {WIFI_BEACON, "OnBeacon", &OnBeacon}, + {WIFI_ATIM, "OnATIM", &OnAtim}, + {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc}, + {WIFI_AUTH, "OnAuth", &OnAuthClient}, + {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth}, + {WIFI_ACTION, "OnAction", &OnAction}, +}; + +int init_hw_mlme_ext(struct adapter *padapter) +{ + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + + set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); + return _SUCCESS; +} + +static void init_mlme_ext_priv_value(struct adapter *padapter) +{ + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + unsigned char mixed_datarate[NumRates] = { + _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, + _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, + _48M_RATE_, _54M_RATE_, 0xff + }; + unsigned char mixed_basicrate[NumRates] = { + _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, + _12M_RATE_, _24M_RATE_, 0xff, + }; + + atomic_set(&pmlmeext->event_seq, 0); + pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */ + + pmlmeext->cur_channel = padapter->registrypriv.channel; + pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; + pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; + pmlmeext->oper_channel = pmlmeext->cur_channel; + pmlmeext->oper_bwmode = pmlmeext->cur_bwmode; + pmlmeext->oper_ch_offset = pmlmeext->cur_ch_offset; + pmlmeext->retry = 0; + + pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode; + + memcpy(pmlmeext->datarate, mixed_datarate, NumRates); + memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates); + + pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; + + pmlmeext->sitesurvey_res.state = SCAN_DISABLE; + pmlmeext->sitesurvey_res.channel_idx = 0; + pmlmeext->sitesurvey_res.bss_cnt = 0; + pmlmeext->scan_abort = false; + + pmlmeinfo->state = WIFI_FW_NULL_STATE; + pmlmeinfo->reauth_count = 0; + pmlmeinfo->reassoc_count = 0; + pmlmeinfo->link_count = 0; + pmlmeinfo->auth_seq = 0; + pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; + pmlmeinfo->key_index = 0; + pmlmeinfo->iv = 0; + + pmlmeinfo->enc_algo = _NO_PRIVACY_; + pmlmeinfo->authModeToggle = 0; + + memset(pmlmeinfo->chg_txt, 0, 128); + + pmlmeinfo->slotTime = SHORT_SLOT_TIME; + pmlmeinfo->preamble_mode = PREAMBLE_AUTO; + + pmlmeinfo->dialogToken = 0; + + pmlmeext->action_public_rxseq = 0xffff; + pmlmeext->action_public_dialog_token = 0xff; +} + +static int has_channel(struct rt_channel_info *channel_set, + u8 chanset_size, + u8 chan) { + int i; + + for (i = 0; i < chanset_size; i++) { + if (channel_set[i].ChannelNum == chan) + return 1; + } + return 0; +} + +static void init_channel_list(struct adapter *padapter, struct rt_channel_info *channel_set, + u8 chanset_size, + struct p2p_channels *channel_list) { + struct p2p_oper_class_map op_class[] = { + { IEEE80211G, 81, 1, 13, 1, BW20 }, + { IEEE80211G, 82, 14, 14, 1, BW20 }, + { -1, 0, 0, 0, 0, BW20 } + }; + + int cla, op; + + cla = 0; + + for (op = 0; op_class[op].op_class; op++) { + u8 ch; + struct p2p_oper_class_map *o = &op_class[op]; + struct p2p_reg_class *reg = NULL; + + for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { + if (!has_channel(channel_set, chanset_size, ch)) { + continue; + } + + if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc)) + continue; + + if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) && + ((BW40MINUS == o->bw) || (BW40PLUS == o->bw))) + continue; + + if (reg == NULL) { + reg = &channel_list->reg_class[cla]; + cla++; + reg->reg_class = o->op_class; + reg->channels = 0; + } + reg->channel[reg->channels] = ch; + reg->channels++; + } + } + channel_list->reg_classes = cla; +} + +static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set) +{ + u8 index, chanset_size = 0; + u8 b2_4GBand = false; + u8 Index2G = 0; + + memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM); + + if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) { + DBG_88E("ChannelPlan ID %x error !!!!!\n", ChannelPlan); + return chanset_size; + } + + if (padapter->registrypriv.wireless_mode & WIRELESS_11G) { + b2_4GBand = true; + if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan) + Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G; + else + Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G; + } + + if (b2_4GBand) { + for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) { + channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index]; + + if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */ + (RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == ChannelPlan)) { + if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11) + channel_set[chanset_size].ScanType = SCAN_ACTIVE; + else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14)) + channel_set[chanset_size].ScanType = SCAN_PASSIVE; + } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan || + RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {/* channel 12~13, passive scan */ + if (channel_set[chanset_size].ChannelNum <= 11) + channel_set[chanset_size].ScanType = SCAN_ACTIVE; + else + channel_set[chanset_size].ScanType = SCAN_PASSIVE; + } else { + channel_set[chanset_size].ScanType = SCAN_ACTIVE; + } + + chanset_size++; + } + } + return chanset_size; +} + +int init_mlme_ext_priv(struct adapter *padapter) +{ + struct registry_priv *pregistrypriv = &padapter->registrypriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + pmlmeext->padapter = padapter; + + init_mlme_ext_priv_value(padapter); + pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq; + + init_mlme_ext_timer(padapter); + +#ifdef CONFIG_88EU_AP_MODE + init_mlme_ap_info(padapter); +#endif + + pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set); + init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list); + + pmlmeext->chan_scan_time = SURVEY_TO; + pmlmeext->mlmeext_init = true; + + + pmlmeext->active_keep_alive_check = true; + + return _SUCCESS; +} + +void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext) +{ + struct adapter *padapter = pmlmeext->padapter; + + if (!padapter) + return; + + if (padapter->bDriverStopped) { + del_timer_sync(&pmlmeext->survey_timer); + del_timer_sync(&pmlmeext->link_timer); + } +} + +static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, struct recv_frame *precv_frame) +{ + u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 *pframe = precv_frame->rx_data; + + if (ptable->func) { + /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ + if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && + memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) + return; + ptable->func(padapter, precv_frame); + } +} + +void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame) +{ + int index; + struct mlme_handler *ptable; +#ifdef CONFIG_88EU_AP_MODE + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; +#endif /* CONFIG_88EU_AP_MODE */ + u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 *pframe = precv_frame->rx_data; + struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe)); + + RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, + ("+mgt_dispatcher: type(0x%x) subtype(0x%x)\n", + GetFrameType(pframe), GetFrameSubType(pframe))); + + if (GetFrameType(pframe) != WIFI_MGT_TYPE) { + RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("mgt_dispatcher: type(0x%x) error!\n", GetFrameType(pframe))); + return; + } + + /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ + if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && + memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) + return; + + ptable = mlme_sta_tbl; + + index = GetFrameSubType(pframe) >> 4; + + if (index > 13) { + RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Currently we do not support reserved sub-fr-type=%d\n", index)); + return; + } + ptable += index; + + if (psta != NULL) { + if (GetRetry(pframe)) { + if (precv_frame->attrib.seq_num == + psta->RxMgmtFrameSeqNum) { + /* drop the duplicate management frame */ + DBG_88E("Drop duplicate management frame with seq_num=%d.\n", + precv_frame->attrib.seq_num); + return; + } + } + psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num; + } + +#ifdef CONFIG_88EU_AP_MODE + switch (GetFrameSubType(pframe)) { + case WIFI_AUTH: + if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) + ptable->func = &OnAuth; + else + ptable->func = &OnAuthClient; + /* fall through */ + case WIFI_ASSOCREQ: + case WIFI_REASSOCREQ: + case WIFI_PROBEREQ: + case WIFI_BEACON: + case WIFI_ACTION: + _mgt_dispatcher(padapter, ptable, precv_frame); + break; + default: + _mgt_dispatcher(padapter, ptable, precv_frame); + break; + } +#else + _mgt_dispatcher(padapter, ptable, precv_frame); +#endif +} + +/**************************************************************************** + Following are the functions to report events *****************************************************************************/ |