00001
00013 #include "sm.h"
00014 #include "sm_task.h"
00015 #include "scanu.h"
00016 #include "scanu_task.h"
00017 #include "me.h"
00018 #include "co_utils.h"
00019 #include "co_endian.h"
00020 #include "me_utils.h"
00021 #include "mm_task.h"
00022 #include "rxu_task.h"
00023 #include "mac_frame.h"
00024 #include "mac_ie.h"
00025 #include "me_mgmtframe.h"
00026 #include "vif_mgmt.h"
00027 #include "sta_mgmt.h"
00028 #include "ps.h"
00029 #include "txu_cntrl.h"
00030 #if NX_MFP
00031 #include "mfp.h"
00032 #endif
00033 #include "tpc.h"
00034
00039 struct sm_env_tag sm_env;
00040
00042 #if NX_FULLY_HOSTED
00043 #define SM_EXTERNAL_AUTH_TIMEOUT 10000000
00044 #else
00045 #define SM_EXTERNAL_AUTH_TIMEOUT 600000
00046 #endif
00047
00058 static void sm_frame_tx_cfm_handler(void *env, uint32_t status)
00059 {
00060 ke_state_t sm_state = ke_state_get(TASK_SM);
00061 struct txl_frame_desc_tag *frame = env;
00062
00063
00064
00065 if (!(status & (DESC_DONE_SW_TX_BIT | RETRY_LIMIT_REACHED_BIT | LIFETIME_EXPIRED_BIT)))
00066 return;
00067
00068 switch (sm_state)
00069 {
00070 case (SM_AUTHENTICATING):
00071 case (SM_ASSOCIATING):
00072 {
00073
00074 txl_frame_push(frame, AC_VO);
00075
00076
00077 frame->keep_desc = true;
00078 } break;
00079
00080 default:
00081 {
00082
00083 } break;
00084 }
00085 }
00086
00092 static void sm_bss_config_init(void)
00093 {
00094
00095 ASSERT_ERR(co_list_is_empty(&sm_env.bss_config));
00096
00097
00098 co_list_init(&sm_env.bss_config);
00099 }
00100
00108 static void sm_bss_config_push(void *param)
00109 {
00110 struct ke_msg *msg = ke_param2msg(param);
00111
00112 co_list_push_back(&sm_env.bss_config, &msg->hdr);
00113 }
00114
00124 static void sm_deauth_cfm(void *env, uint32_t status)
00125 {
00126 sm_disconnect_process(env, 0);
00127 }
00128
00136 static void sm_delete_resources(struct vif_info_tag *vif)
00137 {
00138 struct me_set_ps_disable_req *ps = KE_MSG_ALLOC(ME_SET_PS_DISABLE_REQ, TASK_ME, TASK_SM,
00139 me_set_ps_disable_req);
00140 struct me_set_active_req *idle = KE_MSG_ALLOC(ME_SET_ACTIVE_REQ, TASK_ME,
00141 TASK_SM, me_set_active_req);
00142
00143
00144 sm_bss_config_init();
00145
00146 #if NX_AMPDU_TX || NX_REORD
00147
00148 bam_delete_all_ba_agg(vif->u.sta.ap_id);
00149 #endif
00150
00151
00152 ps->ps_disable = false;
00153 ps->vif_idx = vif->index;
00154 sm_bss_config_push(ps);
00155
00156
00157 if (vif->active)
00158 {
00159 struct mm_set_vif_state_req *assoc = KE_MSG_ALLOC(MM_SET_VIF_STATE_REQ, TASK_MM,
00160 TASK_SM, mm_set_vif_state_req);
00161 assoc->active = false;
00162 assoc->inst_nbr = vif->index;
00163 sm_bss_config_push(assoc);
00164 }
00165
00166
00167 if (vif->u.sta.ap_id != INVALID_STA_IDX)
00168 {
00169 struct mm_sta_del_req *sta_del = KE_MSG_ALLOC(MM_STA_DEL_REQ, TASK_MM,
00170 TASK_SM, mm_sta_del_req);
00171 sta_del->sta_idx = vif->u.sta.ap_id;
00172 sm_bss_config_push(sta_del);
00173 }
00174
00175
00176 if (vif->chan_ctxt != NULL)
00177 {
00178 struct mm_chan_ctxt_unlink_req *unlk = KE_MSG_ALLOC(MM_CHAN_CTXT_UNLINK_REQ,TASK_MM,
00179 TASK_SM, mm_chan_ctxt_unlink_req);
00180 unlk->vif_index = vif->index;
00181 sm_bss_config_push(unlk);
00182 }
00183
00184 idle->active = false;
00185 idle->vif_idx = vif->index;
00186 sm_bss_config_push(idle);
00187
00188
00189 sm_bss_config_send();
00190 }
00191
00192 void sm_init(void)
00193 {
00194
00195 sm_env.connect_param = NULL;
00196
00197
00198 ke_state_set(TASK_SM, SM_IDLE);
00199 }
00200
00201
00202 void sm_get_bss_params(struct mac_addr const **bssid,
00203 struct mac_chan_def const **chan)
00204 {
00205 struct sm_connect_req const *param = sm_env.connect_param;
00206 struct mac_scan_result *desired_ap_ptr;
00207
00208 *bssid = NULL;
00209 *chan = NULL;
00210
00211
00212
00213 if (MAC_ADDR_GROUP(¶m->bssid))
00214 {
00215 desired_ap_ptr = scanu_search_by_ssid(¶m->ssid);
00216 if (desired_ap_ptr)
00217 *bssid = &desired_ap_ptr->bssid;
00218 }
00219 else
00220 {
00221 *bssid = ¶m->bssid;
00222 desired_ap_ptr = scanu_search_by_bssid(¶m->bssid);
00223 }
00224
00225
00226 if (desired_ap_ptr)
00227 *chan = desired_ap_ptr->chan;
00228 else if (param->chan.freq != ((uint16_t)-1))
00229 *chan = ¶m->chan;
00230 }
00231
00232 void sm_scan_bss(struct mac_addr const *bssid,
00233 struct mac_chan_def const *chan)
00234 {
00235 struct sm_connect_req const *param = sm_env.connect_param;
00236
00237 struct scanu_start_req *req = KE_MSG_ALLOC(SCANU_START_REQ, TASK_SCANU, TASK_SM,
00238 scanu_start_req);
00239
00240 req->vif_idx = param->vif_idx;
00241 req->add_ies = 0;
00242 req->add_ie_len = 0;
00243 req->ssid[0] = param->ssid;
00244 req->ssid_cnt = 1;
00245 req->bssid = bssid?*bssid:mac_addr_bcst;
00246 if (chan)
00247 {
00248 req->chan[0] = *chan;
00249 req->chan_cnt = 1;
00250 }
00251 else
00252 {
00253 int i, j;
00254 struct mac_chan_def *chan[PHY_BAND_MAX] = {me_env.chan.chan2G4, me_env.chan.chan5G};
00255 uint8_t chan_cnt[PHY_BAND_MAX] = {me_env.chan.chan2G4_cnt, me_env.chan.chan5G_cnt};
00256
00257 req->chan_cnt = 0;
00258 for (i = 0; i < PHY_BAND_MAX; i++)
00259 for (j = 0; j < chan_cnt[i]; j++)
00260 if (!(chan[i][j].flags & CHAN_DISABLED))
00261 req->chan[req->chan_cnt++] = chan[i][j];
00262 }
00263
00264
00265 ke_msg_send(req);
00266
00267
00268 ke_state_set(TASK_SM, SM_SCANNING);
00269 }
00270
00271
00272 void sm_join_bss(struct mac_addr const *bssid,
00273 struct mac_chan_def const *chan,
00274 bool passive)
00275 {
00276 struct sm_connect_req const *param = sm_env.connect_param;
00277 struct scanu_start_req *req = KE_MSG_ALLOC(SCANU_JOIN_REQ, TASK_SCANU, TASK_SM,
00278 scanu_start_req);
00279
00280 req->chan[0] = *chan;
00281 req->chan_cnt = 1;
00282 req->ssid[0] = param->ssid;
00283 req->ssid_cnt = 1;
00284 req->add_ie_len = 0;
00285 req->add_ies = 0;
00286 req->vif_idx = param->vif_idx;
00287 req->bssid = *bssid;
00288
00289
00290 if (passive)
00291 {
00292 req->chan[0].flags |= CHAN_NO_IR;
00293 }
00294
00295
00296 sm_env.join_passive = !passive;
00297
00298
00299 ke_msg_send(req);
00300
00301
00302 ke_state_set(TASK_SM, SM_JOINING);
00303 }
00304
00305
00306 uint8_t sm_add_chan_ctx(uint8_t *chan_idx)
00307 {
00308
00309 struct sm_connect_req const *param = sm_env.connect_param;
00310 struct vif_info_tag *vif = &vif_info_tab[param->vif_idx];
00311 struct me_bss_info *bss = &vif->bss_info;
00312
00313
00314 return (chan_ctxt_add(&bss->chan, chan_idx));
00315 }
00316
00317
00318 void sm_set_bss_param(void)
00319 {
00320 int i;
00321 struct sm_connect_req const *param = sm_env.connect_param;
00322 struct vif_info_tag *vif = &vif_info_tab[param->vif_idx];
00323 struct me_bss_info *bss = &vif->bss_info;
00324 struct me_set_ps_disable_req *ps = KE_MSG_ALLOC(ME_SET_PS_DISABLE_REQ, TASK_ME, TASK_SM,
00325 me_set_ps_disable_req);
00326 struct mm_set_bssid_req *bssid = KE_MSG_ALLOC(MM_SET_BSSID_REQ, TASK_MM, TASK_SM,
00327 mm_set_bssid_req);
00328 struct mm_set_basic_rates_req *brates = KE_MSG_ALLOC(MM_SET_BASIC_RATES_REQ, TASK_MM,
00329 TASK_SM, mm_set_basic_rates_req);
00330 struct mm_set_beacon_int_req *bint = KE_MSG_ALLOC(MM_SET_BEACON_INT_REQ, TASK_MM,
00331 TASK_SM, mm_set_beacon_int_req);
00332 struct me_set_active_req *active = KE_MSG_ALLOC(ME_SET_ACTIVE_REQ, TASK_ME,
00333 TASK_SM, me_set_active_req);
00334
00335
00336 sm_bss_config_init();
00337
00338
00339 ps->ps_disable = true;
00340 ps->vif_idx = param->vif_idx;
00341 sm_bss_config_push(ps);
00342
00343
00344 bssid->bssid = bss->bssid;
00345 bssid->inst_nbr = param->vif_idx;
00346 sm_bss_config_push(bssid);
00347
00348
00349 brates->band = bss->chan.band;
00350 brates->rates = me_legacy_rate_bitfield_build(&bss->rate_set, true);
00351 brates->inst_nbr = param->vif_idx;
00352 sm_bss_config_push(brates);
00353
00354
00355 bint->beacon_int = bss->beacon_period;
00356 bint->inst_nbr = param->vif_idx;
00357 sm_bss_config_push(bint);
00358
00359 #if NX_HE
00360 if (BSS_CAPA(bss, HE))
00361 {
00362 struct mm_set_bss_color_req *color = KE_MSG_ALLOC(MM_SET_BSS_COLOR_REQ, TASK_MM,
00363 TASK_SM, mm_set_bss_color_req);
00364 color->bss_color = me_build_bss_color_reg(bss);
00365 sm_bss_config_push(color);
00366 }
00367 #endif
00368
00369
00370 for (i = 0; i < AC_MAX; i++)
00371 {
00372 struct mm_set_edca_req *edca = KE_MSG_ALLOC(MM_SET_EDCA_REQ, TASK_MM,
00373 TASK_SM, mm_set_edca_req);
00374
00375 edca->ac_param = bss->edca_param.ac_param[i];
00376 edca->hw_queue = i;
00377 edca->inst_nbr = param->vif_idx;
00378 #if NX_UAPSD
00379 if (ps_uapsd_enabled() &&
00380 (bss->edca_param.qos_info & MAC_QOS_INFO_AP_UAPSD_ENABLED))
00381 {
00382 edca->uapsd = (mac_ac2uapsd[i] & param->uapsd_queues) != 0;
00383 }
00384 else
00385 #endif
00386 {
00387 edca->uapsd = false;
00388 }
00389 sm_bss_config_push(edca);
00390 }
00391
00392
00393 active->active = true;
00394 active->vif_idx = param->vif_idx;
00395 sm_bss_config_push(active);
00396
00397
00398 sm_bss_config_send();
00399
00400
00401 ke_state_set(TASK_SM, SM_BSS_PARAM_SETTING);
00402 }
00403
00404 void sm_bss_config_send(void)
00405 {
00406 struct ke_msg *msg = (struct ke_msg *)co_list_pop_front(&sm_env.bss_config);
00407
00408
00409 ASSERT_ERR(msg != NULL);
00410
00411
00412 ke_msg_send(ke_msg2param(msg));
00413 }
00414
00415 void sm_disconnect(uint8_t vif_index, uint16_t reason_code)
00416 {
00417 struct vif_info_tag *vif = &vif_info_tab[vif_index];
00418 struct txl_frame_desc_tag *frame;
00419 struct mac_hdr *buf;
00420 struct tx_hd *thd;
00421 struct sta_info_tag *sta = &sta_info_tab[vif->u.sta.ap_id];
00422 uint32_t length;
00423 int txtype;
00424
00425 if ((vif->type != VIF_STA) || (!vif->active))
00426 {
00427 ke_msg_send_basic(SM_DISCONNECT_CFM, TASK_API, TASK_SM);
00428 return;
00429 }
00430
00431 sm_env.host_disconnect = true;
00432 ke_state_set(TASK_SM, SM_DISCONNECTING);
00433
00434 #if (NX_P2P)
00435 if (vif->p2p)
00436 {
00437 txtype = TX_DEFAULT_5G;
00438 }
00439 else
00440 #endif //(NX_P2P)
00441 {
00442 struct me_bss_info *bss = &vif->bss_info;
00443
00444
00445 txtype = (bss->chan.band == PHY_BAND_2G4) ? TX_DEFAULT_24G : TX_DEFAULT_5G;
00446 }
00447
00448
00449 frame = txl_frame_get(txtype, NX_TXFRAME_LEN);
00450 if (frame != NULL)
00451 {
00452 #if NX_MFP
00453 enum mfp_protection mfp;
00454 #endif
00455
00456
00457 tpc_update_frame_tx_power(vif, frame);
00458
00459
00460 buf = txl_buffer_payload_get(&frame->txdesc);
00461
00462
00463 buf->fctl = MAC_FCTRL_DEAUTHENT;
00464 buf->durid = 0;
00465 buf->addr1 = sta->mac_addr;
00466 buf->addr2 = vif->mac_addr;
00467 buf->addr3 = sta->mac_addr;
00468 buf->seq = txl_get_seq_ctrl();
00469
00470
00471 frame->cfm.cfm_func = sm_deauth_cfm;
00472 frame->cfm.env = vif;
00473
00474
00475 frame->txdesc.host.vif_idx = vif_index;
00476 frame->txdesc.host.staid = vif->u.sta.ap_id;
00477
00478 length = MAC_SHORT_MAC_HDR_LEN;
00479
00480 #if NX_MFP
00481 frame->txdesc.umac.head_len = 0;
00482 frame->txdesc.umac.tail_len = 0;
00483 mfp = mfp_protect_mgmt_frame(&frame->txdesc, buf->fctl, 0);
00484 if (mfp == MFP_UNICAST_PROT)
00485 {
00486 txu_cntrl_protect_mgmt_frame(&frame->txdesc, buf, MAC_SHORT_MAC_HDR_LEN);
00487 length += frame->txdesc.umac.head_len;
00488 }
00489 #endif
00490
00491
00492 length += me_build_deauthenticate(CPU2HW(buf) + length, reason_code);
00493
00494 #if NX_MFP
00495 if (mfp == MFP_MULTICAST_PROT)
00496 {
00497 length += mfp_add_mgmt_mic(&frame->txdesc, CPU2HW(buf), length, 0);
00498 }
00499 else if (mfp == MFP_UNICAST_PROT)
00500 {
00501 length += frame->txdesc.umac.tail_len;
00502 }
00503 #endif
00504
00505
00506 thd = &frame->txdesc.lmac.hw_desc->thd;
00507 thd->dataendptr = (uint32_t)thd->datastartptr + length - 1;
00508 thd->frmlen = length + MAC_FCS_LEN;
00509
00510
00511 if (!txl_frame_push(frame, AC_VO))
00512 {
00513 sm_deauth_cfm(frame->cfm.env, 0);
00514 }
00515 }
00516 else
00517 {
00518
00519 sm_disconnect_process(vif, 0);
00520 }
00521 }
00522
00523 void sm_disconnect_process(struct vif_info_tag *vif, uint16_t reason)
00524 {
00525 struct sm_disconnect_ind *disc = KE_MSG_ALLOC(SM_DISCONNECT_IND, TASK_API, TASK_SM,
00526 sm_disconnect_ind);
00527
00528
00529 sm_env.vif_disconnect = vif;
00530
00531
00532 sm_delete_resources(vif);
00533
00534
00535 disc->reason_code = reason;
00536 disc->vif_idx = vif->index;
00537 if (sm_env.ft_over_ds == 1)
00538 {
00539 disc->ft_over_ds = 1;
00540 }
00541
00542 sm_env.disconnect_ind = ke_param2msg(disc);
00543 }
00544
00545 void sm_connect_ind(uint16_t status)
00546 {
00547 struct sm_connect_ind *ind = sm_env.connect_ind;
00548 struct sm_connect_req const *con_par = sm_env.connect_param;
00549 struct vif_info_tag *vif = &vif_info_tab[con_par->vif_idx];
00550 struct me_bss_info *bss = &vif->bss_info;
00551
00552
00553 ind->vif_idx = con_par->vif_idx;
00554 ind->status_code = status;
00555
00556 if (status == MAC_ST_SUCCESSFUL)
00557 {
00558 ind->bssid = bss->bssid;
00559 ind->ap_idx = vif->u.sta.ap_id;
00560 ind->ch_idx = vif->chan_ctxt->idx;
00561 ind->chan = vif->bss_info.chan;
00562
00563 ind->qos = BSS_CAPA(bss, QOS);
00564 ind->acm = ind->qos?bss->edca_param.acm:0;
00565
00566 ind->roamed = false;
00567 #if (NX_TDLS)
00568 memcpy(ind->ac_param, bss->edca_param.ac_param, sizeof(ind->ac_param));
00569 #endif
00570
00571
00572 ke_msg_send(ind);
00573
00574
00575 ke_state_set(TASK_SM, SM_IDLE);
00576 }
00577 else
00578 {
00579 ke_state_set(TASK_SM, SM_DISCONNECTING);
00580 sm_env.vif_disconnect = vif;
00581 sm_env.disconnect_ind = ke_param2msg(ind);
00582
00583
00584 sm_delete_resources(vif);
00585 }
00586
00587
00588 ke_msg_free(ke_param2msg(sm_env.connect_param));
00589 sm_env.connect_param = NULL;
00590 sm_env.ft_over_ds = 0;
00591 }
00592
00593 void sm_auth_send(uint16_t auth_seq, uint32_t *challenge)
00594 {
00595 struct sm_connect_req const *con_par = sm_env.connect_param;
00596 struct vif_info_tag *vif = &vif_info_tab[con_par->vif_idx];
00597 struct txl_frame_desc_tag *frame;
00598 struct mac_hdr *buf;
00599 struct tx_hd *thd;
00600 struct sta_info_tag *sta = &sta_info_tab[vif->u.sta.ap_id];
00601 uint32_t length;
00602
00603 int txtype;
00604
00605 #if (NX_P2P)
00606 if (vif->p2p)
00607 {
00608 txtype = TX_DEFAULT_5G;
00609 }
00610 else
00611 #endif //(NX_P2P)
00612 {
00613 struct me_bss_info *bss = &vif->bss_info;
00614
00615 txtype = (bss->chan.band == PHY_BAND_2G4) ? TX_DEFAULT_24G : TX_DEFAULT_5G;
00616 }
00617
00618
00619 frame = txl_frame_get(txtype, NX_TXFRAME_LEN);
00620
00621 if (frame != NULL)
00622 {
00623
00624 tpc_update_frame_tx_power(vif, frame);
00625
00626
00627 buf = txl_buffer_payload_get(&frame->txdesc);
00628
00629
00630 buf->fctl = MAC_FCTRL_AUTHENT;
00631 buf->durid = 0;
00632 buf->addr1 = sta->mac_addr;
00633 buf->addr2 = vif->mac_addr;
00634 buf->addr3 = sta->mac_addr;
00635 buf->seq = txl_get_seq_ctrl();
00636
00637
00638 frame->txdesc.host.vif_idx = vif->index;
00639 frame->txdesc.host.staid = vif->u.sta.ap_id;
00640
00641 length = MAC_SHORT_MAC_HDR_LEN;
00642 frame->txdesc.umac.head_len = 0;
00643 frame->txdesc.umac.tail_len = 0;
00644
00645 if ((con_par->auth_type == MAC_AUTH_ALGO_SHARED) &&
00646 (auth_seq == MAC_AUTH_THIRD_SEQ))
00647 {
00648
00649 txu_cntrl_protect_mgmt_frame(&frame->txdesc, buf, MAC_SHORT_MAC_HDR_LEN);
00650 length += frame->txdesc.umac.head_len;
00651 }
00652
00653
00654 length += me_build_authenticate(CPU2HW(buf) + length, con_par->auth_type,
00655 auth_seq, MAC_ST_SUCCESSFUL, challenge);
00656
00657 length += frame->txdesc.umac.tail_len;
00658
00659
00660 frame->cfm.cfm_func = sm_frame_tx_cfm_handler;
00661 frame->cfm.env = frame;
00662
00663
00664 thd = &frame->txdesc.lmac.hw_desc->thd;
00665 thd->dataendptr = (uint32_t)thd->datastartptr + length - 1;
00666 thd->frmlen = length + MAC_FCS_LEN;
00667
00668
00669 txl_frame_push(frame, AC_VO);
00670
00671
00672 ke_timer_set(SM_RSP_TIMEOUT_IND, TASK_SM, DEFAULT_AUTHRSP_TIMEOUT);
00673
00674
00675 ke_state_set(TASK_SM, SM_AUTHENTICATING);
00676 }
00677 else
00678 {
00679 sm_connect_ind(MAC_ST_FAILURE);
00680 }
00681 }
00682
00683 void sm_assoc_req_send(void)
00684 {
00685
00686 struct sm_connect_req const *con_par = sm_env.connect_param;
00687 struct vif_info_tag *vif = &vif_info_tab[con_par->vif_idx];
00688 struct me_bss_info *bss = &vif->bss_info;
00689 struct mac_addr *ap_old_ptr = NULL;
00690 struct txl_frame_desc_tag *frame;
00691 struct mac_hdr *buf;
00692 struct tx_hd *thd;
00693 struct sta_info_tag *sta = &sta_info_tab[vif->u.sta.ap_id];
00694 uint32_t length;
00695 int txtype;
00696
00697
00698 #if (NX_P2P)
00699 if (vif->p2p)
00700 {
00701 txtype = TX_DEFAULT_5G;
00702 }
00703 else
00704 #endif //(NX_P2P)
00705 {
00706
00707 txtype = (bss->chan.band == PHY_BAND_2G4) ? TX_DEFAULT_24G : TX_DEFAULT_5G;
00708 }
00709
00710
00711 frame = txl_frame_get(txtype, NX_TXFRAME_LEN);
00712 if (frame != NULL)
00713 {
00714 struct sm_connect_ind *ind = sm_env.connect_ind;
00715 uint32_t ie_addr;
00716 uint16_t ie_len;
00717
00718
00719 tpc_update_frame_tx_power(vif, frame);
00720
00721
00722 buf = txl_buffer_payload_get(&frame->txdesc);
00723
00724
00725 if (sm_env.ft_over_ds == 1)
00726 {
00727 PROF_FT_REASSOC_SET();
00728 buf->fctl = MAC_FCTRL_REASSOCREQ;
00729 ap_old_ptr = &sm_env.ft_old_bssid;
00730 }
00731 else
00732 {
00733 buf->fctl = MAC_FCTRL_ASSOCREQ;
00734 }
00735 buf->durid = 0;
00736 buf->addr1 = sta->mac_addr;
00737 buf->addr2 = vif->mac_addr;
00738 buf->addr3 = sta->mac_addr;
00739 buf->seq = txl_get_seq_ctrl();
00740
00741
00742 length = me_build_associate_req(CPU2HW(buf) + MAC_SHORT_MAC_HDR_LEN, bss,
00743 ap_old_ptr, vif->index, &ie_addr, &ie_len,
00744 con_par);
00745
00746
00747 frame->txdesc.host.vif_idx = vif->index;
00748 frame->txdesc.host.staid = vif->u.sta.ap_id;
00749
00750
00751 frame->cfm.cfm_func = sm_frame_tx_cfm_handler;
00752 frame->cfm.env = frame;
00753
00754
00755 thd = &frame->txdesc.lmac.hw_desc->thd;
00756 thd->dataendptr = thd->datastartptr + length + MAC_SHORT_MAC_HDR_LEN - 1;
00757 thd->frmlen = length + MAC_SHORT_MAC_HDR_LEN + MAC_FCS_LEN;
00758
00759
00760 if (ie_len <= sizeof_b(ind->assoc_ie_buf))
00761 {
00762 co_copy8p(CPU2HW(ind->assoc_ie_buf), ie_addr, ie_len);
00763 ind->assoc_req_ie_len = ie_len;
00764 }
00765 else
00766 {
00767 ASSERT_WARN(0);
00768 ind->assoc_req_ie_len = 0;
00769 }
00770
00771
00772 txl_frame_push(frame, AC_VO);
00773
00774
00775 ke_timer_set(SM_RSP_TIMEOUT_IND, TASK_SM, DEFAULT_ASSOCRSP_TIMEOUT);
00776
00777
00778 ke_state_set(TASK_SM, SM_ASSOCIATING);
00779 }
00780 else
00781 {
00782 sm_connect_ind(MAC_ST_FAILURE);
00783 }
00784 }
00785
00786 void sm_assoc_done(uint16_t aid)
00787 {
00788
00789 struct mm_set_vif_state_req *req;
00790 struct sm_connect_req const *con_par = sm_env.connect_param;
00791
00792
00793 req = KE_MSG_ALLOC(MM_SET_VIF_STATE_REQ, TASK_MM, TASK_SM, mm_set_vif_state_req);
00794
00795
00796 req->aid = aid;
00797 req->active = true;
00798 req->inst_nbr = con_par->vif_idx;
00799
00800
00801 ke_msg_send(req);
00802
00803
00804 ke_state_set(TASK_SM, SM_ACTIVATING);
00805 }
00806
00807 void sm_auth_handler(struct rxu_mgt_ind const *param)
00808 {
00809 uint16_t status, auth_type, auth_seq;
00810 uint32_t payload = CPU2HW(param->payload);
00811
00812
00813 ke_timer_clear(SM_RSP_TIMEOUT_IND, TASK_SM);
00814
00815
00816 status = co_read16p(payload + MAC_AUTH_STATUS_OFT);
00817
00818
00819 switch (status)
00820 {
00821 case MAC_ST_SUCCESSFUL:
00822 auth_type = co_read16p(payload + MAC_AUTH_ALGONBR_OFT);
00823
00824 if (auth_type == MAC_AUTH_ALGO_OPEN)
00825 {
00826
00827 sm_assoc_req_send();
00828 }
00829 else if(auth_type == MAC_AUTH_ALGO_SHARED)
00830 {
00831 auth_seq = co_read16p(payload + MAC_AUTH_SEQNBR_OFT);
00832
00833 if (auth_seq == MAC_AUTH_FOURTH_SEQ)
00834 {
00835
00836 sm_assoc_req_send();
00837 }
00838 else if (auth_seq == MAC_AUTH_SECOND_SEQ)
00839 {
00840
00841 sm_auth_send(MAC_AUTH_THIRD_SEQ,
00842 HW2CPU(payload + MAC_AUTH_CHALLENGE_OFT + MAC_CHALLENGE_TEXT_OFT));
00843 }
00844 else
00845 {
00846 ASSERT_WARN(0);
00847 sm_connect_ind(MAC_ST_FAILURE);
00848 }
00849 }
00850 break;
00851
00852 default:
00853 {
00854
00855 sm_connect_ind(status);
00856 break;
00857 }
00858 }
00859 }
00860
00861 void sm_assoc_rsp_handler(struct rxu_mgt_ind const *param)
00862 {
00863 uint16_t status;
00864 uint32_t payload = CPU2HW(param->payload);
00865 struct sm_connect_ind *ind = sm_env.connect_ind;
00866
00867
00868 ke_timer_clear(SM_RSP_TIMEOUT_IND, TASK_SM);
00869
00870
00871 status = co_read16p(payload + MAC_ASSO_RSP_STATUS_OFT);
00872
00873 if (sm_env.ft_over_ds == 1)
00874 {
00875 PROF_FT_REASSOC_CLR();
00876 }
00877
00878
00879 if (param->length >= MAC_ASSO_RSP_RATES_OFT)
00880 {
00881 uint32_t ie_addr = payload + MAC_ASSO_RSP_RATES_OFT;
00882 uint16_t ie_len = param->length - MAC_ASSO_RSP_RATES_OFT;
00883 if ((ie_len + ind->assoc_req_ie_len) > sizeof_b(ind->assoc_ie_buf))
00884 {
00885 ASSERT_WARN(0);
00886 ie_len = sizeof_b(ind->assoc_ie_buf) - ind->assoc_req_ie_len;
00887 }
00888 co_copy8p(CPU2HW(ind->assoc_ie_buf) + ind->assoc_req_ie_len, ie_addr, ie_len);
00889 ind->assoc_rsp_ie_len = ie_len;
00890 }
00891 else
00892 {
00893 ind->assoc_rsp_ie_len = 0;
00894 }
00895
00896 switch (status)
00897 {
00898 case MAC_ST_SUCCESSFUL:
00899
00900 sm_assoc_done(co_wtohs(co_read16p(payload + MAC_ASSO_RSP_AID_OFT)) & MAC_AID_MSK);
00901 break;
00902
00903 default:
00904
00905 sm_connect_ind(status);
00906 break;
00907 }
00908 }
00909
00910 int sm_deauth_handler(struct rxu_mgt_ind const *param)
00911 {
00912 struct vif_info_tag *vif = &vif_info_tab[param->inst_nbr];
00913
00914
00915 if (ke_state_get(TASK_SM) == SM_DISCONNECTING)
00916
00917 return KE_MSG_SAVED;
00918
00919
00920 if (ke_state_get(TASK_SM) != SM_IDLE)
00921 {
00922 struct sm_connect_req const *con_par = sm_env.connect_param;
00923
00924
00925 if (con_par->vif_idx != param->inst_nbr)
00926
00927 return KE_MSG_SAVED;
00928
00929
00930 sm_connect_ind(MAC_ST_FAILURE);
00931 }
00932 else if (vif->active)
00933 {
00934 uint32_t payload = CPU2HW(param->payload);
00935 uint16_t reason = co_read16p(payload + MAC_DEAUTH_REASON_OFT);
00936
00937
00938 ke_state_set(TASK_SM, SM_DISCONNECTING);
00939 sm_disconnect_process(vif, reason);
00940 }
00941
00942 return KE_MSG_CONSUMED;
00943 }
00944
00945 #if NX_MFP
00946 void sm_sa_query_handler(struct rxu_mgt_ind const *param)
00947 {
00948 struct vif_info_tag *vif = &vif_info_tab[param->inst_nbr];
00949 struct sta_info_tag *ap;
00950 struct txl_frame_desc_tag *frame;
00951 struct tx_hd *thd;
00952 struct mac_hdr *buf;
00953 uint32_t payload = CPU2HW(param->payload);
00954 uint8_t action;
00955 uint16_t transaction_id, length;
00956 int txtype;
00957
00958
00959 if (!vif->active || vif->type != VIF_STA)
00960 return;
00961
00962
00963 if ((param->sta_idx == INVALID_STA_IDX) || (vif->u.sta.ap_id != param->sta_idx))
00964 return;
00965
00966
00967 ap = &sta_info_tab[param->sta_idx];
00968 if (ap->ctrl_port_state != PORT_OPEN)
00969 return;
00970
00971 action = co_read8p(payload + MAC_SA_QUERY_ACTION_OFT);
00972 transaction_id = co_read16p(payload + MAC_SA_QUERY_TR_ID_OFT);
00973
00974 if (action != MAC_SA_QUERY_REQUEST)
00975 return;
00976
00977
00978 txtype = (param->band == PHY_BAND_2G4) ? TX_DEFAULT_24G : TX_DEFAULT_5G;
00979
00980
00981 frame = txl_frame_get(txtype, NX_TXFRAME_LEN);
00982 if (frame == NULL)
00983 return;
00984
00985
00986 tpc_update_frame_tx_power(vif, frame);
00987
00988
00989 buf = txl_buffer_payload_get(&frame->txdesc);
00990
00991 buf->fctl = MAC_FCTRL_ACTION;
00992 buf->durid = 0;
00993 buf->addr1 = ap->mac_addr;
00994 buf->addr2 = vif->mac_addr;
00995 buf->addr3 = ap->mac_addr;
00996 buf->seq = txl_get_seq_ctrl();
00997
00998
00999 frame->txdesc.host.vif_idx = param->inst_nbr;
01000 frame->txdesc.host.staid = param->sta_idx;
01001
01002 length = MAC_SHORT_MAC_HDR_LEN;
01003
01004 frame->txdesc.umac.head_len = 0;
01005 frame->txdesc.umac.tail_len = 0;
01006
01007 mfp_protect_mgmt_frame(&frame->txdesc, buf->fctl,
01008 MAC_SA_QUERY_ACTION_CATEGORY);
01009 txu_cntrl_protect_mgmt_frame(&frame->txdesc, buf, MAC_SHORT_MAC_HDR_LEN);
01010 length += frame->txdesc.umac.head_len;
01011
01012 payload = CPU2HW(buf);
01013 payload += length;
01014
01015 co_write8p(payload + MAC_ACTION_CATEGORY_OFT, MAC_SA_QUERY_ACTION_CATEGORY);
01016 co_write8p(payload + MAC_SA_QUERY_ACTION_OFT, MAC_SA_QUERY_RESPONSE);
01017 co_write16p(payload + MAC_SA_QUERY_TR_ID_OFT, transaction_id);
01018 length += 4 + frame->txdesc.umac.tail_len;
01019
01020 thd = &frame->txdesc.lmac.hw_desc->thd;
01021 thd->dataendptr = (uint32_t)thd->datastartptr + length - 1;
01022 thd->frmlen = length + MAC_FCS_LEN;
01023
01024
01025 txl_frame_push(frame, AC_VO);
01026 }
01027 #endif // NX_MFP
01028
01029 void sm_external_auth_start(uint32_t akm)
01030 {
01031 struct sm_connect_req const *con_par = sm_env.connect_param;
01032 struct vif_info_tag *vif = &vif_info_tab[con_par->vif_idx];
01033 struct me_bss_info *bss = &vif->bss_info;
01034 struct sm_external_auth_required_ind *ind;
01035
01036 ASSERT_ERR(BSS_CAPA(bss, VALID));
01037
01038 ind = KE_MSG_ALLOC(SM_EXTERNAL_AUTH_REQUIRED_IND, TASK_API, TASK_SM,
01039 sm_external_auth_required_ind);
01040
01041 ind->vif_idx = con_par->vif_idx;
01042 ind->ssid = bss->ssid;
01043 ind->bssid = bss->bssid;
01044 ind->akm = co_htonl(akm);
01045
01046
01047 ke_state_set(TASK_SM, SM_EXTERNAL_AUTHENTICATING);
01048
01049
01050 ke_timer_set(SM_RSP_TIMEOUT_IND, TASK_SM, SM_EXTERNAL_AUTH_TIMEOUT);
01051
01052 ke_msg_send(ind);
01053 }
01054
01055 void sm_external_auth_end(uint16_t status)
01056 {
01057 ke_timer_clear(SM_RSP_TIMEOUT_IND, TASK_SM);
01058
01059 if (status != MAC_ST_SUCCESSFUL)
01060 {
01061 sm_connect_ind(status);
01062 return;
01063 }
01064
01065
01066 sm_assoc_req_send();
01067 }
01068
01069 bool sm_external_auth_in_progress(void)
01070 {
01071 return (ke_state_get(TASK_SM) == SM_EXTERNAL_AUTHENTICATING);
01072 }
01073
01074
01075 int sm_get_rsnie_pmkid_count(uint32_t ies, uint16_t ies_len)
01076 {
01077 uint32_t rsn_ie, rsn_ie_ptr;
01078 uint16_t cipher_len, akm_len = 0;
01079 uint8_t rsn_ie_len;
01080 rsn_ie = mac_ie_rsn_find(ies, ies_len, &rsn_ie_len);
01081
01082 if (!rsn_ie || (rsn_ie_len < 30))
01083 return 0;
01084
01085 rsn_ie_ptr = rsn_ie + MAC_RSNIE_PAIRWISE_CIPHER_SUITE_CNT_OFT;
01086 rsn_ie_len -= MAC_RSNIE_PAIRWISE_CIPHER_SUITE_CNT_OFT;
01087
01088 cipher_len = co_wtohs(co_read16p(rsn_ie_ptr)) * MAC_RSNIE_PAIRWISE_CIPHER_SIZE;
01089 rsn_ie_ptr += 2 + cipher_len;
01090 rsn_ie_len -= 2 + cipher_len;
01091
01092 if (rsn_ie_len < 22)
01093 return 0;
01094
01095 akm_len = co_wtohs(co_read16p(rsn_ie_ptr)) * MAC_RSNIE_KEY_MANAGEMENT_SIZE;
01096 rsn_ie_ptr += 2 + akm_len;
01097 rsn_ie_len -= 2 + akm_len;
01098
01099 if (rsn_ie_len < 20)
01100 return 0;
01101
01102 rsn_ie_ptr += 2;
01103 return co_wtohs(co_read16p(rsn_ie_ptr));
01104 }
01105
01106
01108