- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/ip/umac/src/sm/sm.c

Go to the documentation of this file.

    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     // Authentication and Association Request frames can be sent until expiration of
    00064     // SM_RSP_TIMEOUT_IND timer.
    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             // Push again the frame for TX
    00074             txl_frame_push(frame, AC_VO);
    00075
    00076             // Inform txl_frame module that descriptor cannot be freed
    00077             frame->keep_desc = true;
    00078         } break;
    00079
    00080         default:
    00081         {
    00082             // Nothing to do
    00083         } break;
    00084     }
    00085 }
    00086
    00092 static void sm_bss_config_init(void)
    00093 {
    00094     // Sanity check - No BSS config should be ongoing
    00095     ASSERT_ERR(co_list_is_empty(&sm_env.bss_config));
    00096
    00097     // Initialize the BSS configuration list
    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     // Initialize the BSS configuration list
    00144     sm_bss_config_init();
    00145
    00146     #if NX_AMPDU_TX || NX_REORD
    00147     // Release all the Block Ack agreement
    00148     bam_delete_all_ba_agg(vif->u.sta.ap_id);
    00149     #endif
    00150
    00151     // Re-allow PS mode in case it was disallowed
    00152     ps->ps_disable = false;
    00153     ps->vif_idx = vif->index;
    00154     sm_bss_config_push(ps);
    00155
    00156     // Assoc
    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     // Delete station
    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     // Unlink the VIF from the channel context
    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     // Send the first BSS disconnection message
    00189     sm_bss_config_send();
    00190 }
    00191
    00192 void sm_init(void)
    00193 {
    00194     // Value of pointer of the scan result is NULL
    00195     sm_env.connect_param = NULL;
    00196     //Station index value
    00197      //Set the state as IDLE
    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     // In order to launch the join procedure we need the BSSID and the channel,
    00212     // otherwise we will need to get this information by doing a scan
    00213     if (MAC_ADDR_GROUP(&param->bssid))
    00214     {
    00215         desired_ap_ptr = scanu_search_by_ssid(&param->ssid);
    00216         if (desired_ap_ptr)
    00217             *bssid = &desired_ap_ptr->bssid;
    00218     }
    00219     else
    00220     {
    00221         *bssid = &param->bssid;
    00222         desired_ap_ptr = scanu_search_by_bssid(&param->bssid);
    00223     }
    00224
    00225     // Get channel
    00226     if (desired_ap_ptr)
    00227         *chan = desired_ap_ptr->chan;
    00228     else if (param->chan.freq != ((uint16_t)-1))
    00229         *chan = &param->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     // Prepare the scan request
    00237     struct scanu_start_req *req = KE_MSG_ALLOC(SCANU_START_REQ, TASK_SCANU, TASK_SM,
    00238                                                                     scanu_start_req);
    00239     // fill in message
    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     // Send the message
    00265     ke_msg_send(req);
    00266
    00267     // We are now waiting for the scan results
    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     // Check if passive scan is required
    00290     if (passive)
    00291     {
    00292         req->chan[0].flags |= CHAN_NO_IR;
    00293     }
    00294
    00295     // Set next join active / passive
    00296     sm_env.join_passive = !passive;
    00297
    00298     // Send the message
    00299     ke_msg_send(req);
    00300
    00301     // We are now waiting for the end of the joining procedure
    00302     ke_state_set(TASK_SM, SM_JOINING);
    00303 }
    00304
    00305
    00306 uint8_t sm_add_chan_ctx(uint8_t *chan_idx)
    00307 {
    00308     // Retrieve connection information
    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     // Add the channel context and return status and channel index
    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     // Initialize the BSS configuration list
    00336     sm_bss_config_init();
    00337
    00338     // Disable PS mode prior to the association procedure
    00339     ps->ps_disable = true;
    00340     ps->vif_idx = param->vif_idx;
    00341     sm_bss_config_push(ps);
    00342
    00343     // BSSID
    00344     bssid->bssid = bss->bssid;
    00345     bssid->inst_nbr = param->vif_idx;
    00346     sm_bss_config_push(bssid);
    00347
    00348     // Basic rates
    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     // Beacon interval
    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     // EDCA parameters
    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     // Go back to ACTIVE after setting the BSS parameters
    00393     active->active = true;
    00394     active->vif_idx = param->vif_idx;
    00395     sm_bss_config_push(active);
    00396
    00397     // Send the first BSS configuration message
    00398     sm_bss_config_send();
    00399
    00400     // We are now waiting for the channel addition confirmation
    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     // Sanity check - We shall have a message available
    00409     ASSERT_ERR(msg != NULL);
    00410
    00411     // Send the message
    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         // Chose the right rate according to the band
    00445         txtype = (bss->chan.band == PHY_BAND_2G4) ? TX_DEFAULT_24G : TX_DEFAULT_5G;
    00446     }
    00447
    00448     // Allocate a frame descriptor from the TX path
    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         // update Tx power in policy table
    00457         tpc_update_frame_tx_power(vif, frame);
    00458
    00459         // Get the buffer pointer
    00460         buf = txl_buffer_payload_get(&frame->txdesc);
    00461
    00462         // Fill-in the frame
    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         // Fill-in the confirmation structure
    00471         frame->cfm.cfm_func = sm_deauth_cfm;
    00472         frame->cfm.env = vif;
    00473
    00474         // Set VIF and STA indexes
    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         // Build the payload
    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         // Update the length
    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         // Push the frame for TX
    00511         if (!txl_frame_push(frame, AC_VO))
    00512         {
    00513             sm_deauth_cfm(frame->cfm.env, 0);
    00514         }
    00515     }
    00516     else
    00517     {
    00518         // No frame available, simply consider us as disconnected immediately
    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     // Save a pointer to the VIF we are handling
    00529     sm_env.vif_disconnect = vif;
    00530
    00531     // Delete the resources that were allocated for this connection
    00532     sm_delete_resources(vif);
    00533
    00534     // Fill in the indication parameters
    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     // Fill the message parameters
    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         //ind->aid = ??
    00563         ind->qos = BSS_CAPA(bss, QOS);
    00564         ind->acm = ind->qos?bss->edca_param.acm:0;
    00565         // This connection results from a host request
    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         // Send the message
    00572         ke_msg_send(ind);
    00573
    00574         // Set state to back to IDLE
    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         // Delete the resources that were allocated for this connection
    00584         sm_delete_resources(vif);
    00585     }
    00586
    00587     // Free the connection parameters
    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     // Chose the right rate according to the band
    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     // Allocate a frame descriptor from the TX path
    00619     frame = txl_frame_get(txtype, NX_TXFRAME_LEN);
    00620
    00621     if (frame != NULL)
    00622     {
    00623         // update Tx power in policy table
    00624         tpc_update_frame_tx_power(vif, frame);
    00625
    00626         // Get the buffer pointer
    00627         buf = txl_buffer_payload_get(&frame->txdesc);
    00628
    00629         // Fill-in the frame
    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         // Set VIF and STA indexes
    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             // Need to encrypt the auth frame
    00649             txu_cntrl_protect_mgmt_frame(&frame->txdesc, buf, MAC_SHORT_MAC_HDR_LEN);
    00650             length += frame->txdesc.umac.head_len;
    00651         }
    00652
    00653         // Build the payload
    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         // Set callback for TX confirmation
    00660         frame->cfm.cfm_func = sm_frame_tx_cfm_handler;
    00661         frame->cfm.env = frame;
    00662
    00663         // Update the length
    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         // Push the frame for TX
    00669         txl_frame_push(frame, AC_VO);
    00670
    00671         // Start authentication timeout timer
    00672         ke_timer_set(SM_RSP_TIMEOUT_IND, TASK_SM, DEFAULT_AUTHRSP_TIMEOUT);
    00673
    00674         // Set the state to AUTH
    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     //The local variables
    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     // Send Association request through TX path
    00698     #if (NX_P2P)
    00699     if (vif->p2p)
    00700     {
    00701         txtype = TX_DEFAULT_5G;
    00702     }
    00703     else
    00704     #endif //(NX_P2P)
    00705     {
    00706         // Chose the right rate according to the band
    00707         txtype = (bss->chan.band == PHY_BAND_2G4) ? TX_DEFAULT_24G : TX_DEFAULT_5G;
    00708     }
    00709
    00710     // Allocate a frame descriptor from the TX path
    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         // update Tx power in policy table
    00719         tpc_update_frame_tx_power(vif, frame);
    00720
    00721         // Get the buffer pointer
    00722         buf = txl_buffer_payload_get(&frame->txdesc);
    00723
    00724         // Fill-in the frame
    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         // Build the payload
    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         // Set VIF and STA indexes
    00747         frame->txdesc.host.vif_idx = vif->index;
    00748         frame->txdesc.host.staid   = vif->u.sta.ap_id;
    00749
    00750         // Set callback for TX confirmation
    00751         frame->cfm.cfm_func = sm_frame_tx_cfm_handler;
    00752         frame->cfm.env = frame;
    00753
    00754         // Update the length
    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         // Copy the AssocReq IEs into the indication message
    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         // Push the frame for TX
    00772         txl_frame_push(frame, AC_VO);
    00773
    00774         // Run association timeout timer
    00775         ke_timer_set(SM_RSP_TIMEOUT_IND, TASK_SM, DEFAULT_ASSOCRSP_TIMEOUT);
    00776
    00777         // Move to state associating
    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     //  Send Association done IND to LMAC
    00789     struct mm_set_vif_state_req *req;
    00790     struct sm_connect_req const *con_par = sm_env.connect_param;
    00791
    00792     // Get a pointer to the kernel message
    00793     req = KE_MSG_ALLOC(MM_SET_VIF_STATE_REQ, TASK_MM, TASK_SM, mm_set_vif_state_req);
    00794
    00795     // Fill the message parameters
    00796     req->aid = aid;
    00797     req->active = true;
    00798     req->inst_nbr = con_par->vif_idx;
    00799
    00800     // Send the message to the task
    00801     ke_msg_send(req);
    00802
    00803     // Set state to back to IDLE
    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     // Stop the authentication timeout timer
    00813     ke_timer_clear(SM_RSP_TIMEOUT_IND, TASK_SM);
    00814
    00815     // Check authentication response (S,F)
    00816     status = co_read16p(payload + MAC_AUTH_STATUS_OFT);
    00817
    00818     // Check on the value of the status
    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                 // Send AIR_ASSOC_REQ to the AIR
    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                     // Authentication done Send AIR_ASSOC_REQ to the AIR
    00836                     sm_assoc_req_send();
    00837                 }
    00838                 else if (auth_seq == MAC_AUTH_SECOND_SEQ)
    00839                 {
    00840                     // Need to send challenge encrypted
    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             // No station available, terminate the connection procedure
    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     // stop the assoc timeout timer
    00868     ke_timer_clear(SM_RSP_TIMEOUT_IND, TASK_SM);
    00869
    00870     // get association response status code
    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     // Copy the AssocRsp IEs into the indication message
    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             // send MM_SET_ASSOCIATED_REQ to the LMAC
    00900             sm_assoc_done(co_wtohs(co_read16p(payload + MAC_ASSO_RSP_AID_OFT)) & MAC_AID_MSK);
    00901             break;
    00902
    00903         default:
    00904             // status is not successful
    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     // Check if we are in a disconnection procedure
    00915     if (ke_state_get(TASK_SM) == SM_DISCONNECTING)
    00916         // We are already in a disconnection procedure, so save the message
    00917         return KE_MSG_SAVED;
    00918
    00919     // Check if we are in a connection procedure
    00920     if (ke_state_get(TASK_SM) != SM_IDLE)
    00921     {
    00922         struct sm_connect_req const *con_par = sm_env.connect_param;
    00923
    00924         // Check on which VIF we are currently in a connection procedure
    00925         if (con_par->vif_idx != param->inst_nbr)
    00926             // We are in a connection procedure on another VIF, so save the message
    00927             return KE_MSG_SAVED;
    00928
    00929         // status is not successful
    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         // Process to the disconnection
    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     // only process sa_query on STA interfaces
    00959     if (!vif->active || vif->type != VIF_STA)
    00960         return;
    00961
    00962     // Ensure we recieved the frame form the AP
    00963     if ((param->sta_idx == INVALID_STA_IDX) || (vif->u.sta.ap_id != param->sta_idx))
    00964         return;
    00965
    00966     // Check that connection with AP is finished
    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     // Chose the right rate according to the band
    00978     txtype = (param->band == PHY_BAND_2G4) ? TX_DEFAULT_24G : TX_DEFAULT_5G;
    00979
    00980     // Allocate frame to send SA Query response
    00981     frame = txl_frame_get(txtype, NX_TXFRAME_LEN);
    00982     if (frame == NULL)
    00983         return;
    00984
    00985     // update Tx power in policy table
    00986     tpc_update_frame_tx_power(vif, frame);
    00987
    00988     // Get the buffer pointer
    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     // Set VIF and STA indexes
    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     // Push the frame for TX
    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     // Wait until host complete the external authentication procedure
    01047     ke_state_set(TASK_SM, SM_EXTERNAL_AUTHENTICATING);
    01048
    01049     // Start timeout timer
    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     // Start association if external authentication succeed
    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