static wlan_btamp_conn_sm_t ieee80211_btamp_get_smhandle(wlan_btamp_conn_sm_t *smhandle,
                                                         u_int8_t *peer_addr, int cur_state)
{
    u_int8_t                phyLink;
    wlan_btamp_conn_sm_t    sm = NULL;

    for (phyLink = 0; phyLink < AMP_MAX_PHY_LINKS; phyLink++) {

        if (!smhandle[phyLink])
            continue;

        sm = smhandle[phyLink];

        if (peer_addr && OS_MEMCMP(sm->peer, peer_addr, IEEE80211_ADDR_LEN) == 0)
            break;

        if (!peer_addr && ieee80211_sm_get_curstate(sm->hsm_handle) == cur_state)
            break;
    }

    if (phyLink >= AMP_MAX_PHY_LINKS)
        sm = NULL;

    return sm;
}
/**
 * visCheckProject
 *
 * Verifies if the currently loaded project ID of this library instance is still
 * the same as of the project ID of the attached ATCMControl Run Time System.
 *
 * Important: If this function fails, all stored addresses must be abandoned and 
 * reloaded again from the attached RTS. (Possibly a new download to the remote
 * RTS has been done.)
 *
 * return			OK if successful, else error number.
 *
 */
VIS_UINT visCheckProject(void)
{
	SVisInfo *pVI = &g_VI;
	IEC_UINT uRes = OK;

	IEC_DATA *pProjectID;

	if (pVI->bInitialized == FALSE)
	{
		RETURN(ERR_INIT);
	}

	if (pVI->bLogin == FALSE)
	{
		RETURN(ERR_LOGIN);
	}

	uRes = domGetProjVersion(pVI, &pProjectID);
	if (uRes != OK)
	{
		RETURN(uRes);
	}

	uRes = (IEC_UINT)(OS_MEMCMP(pVI->pProjectID, pProjectID, VMM_GUID) == 0 ? OK : ERR_WRONG_PROJECT);

	osFree(&pProjectID);

	return uRes;
}
Exemple #3
0
mi_node_t *
mi_tbl_lkup2(mi_node_t *root, u_int8_t *ip, int ipver)
{
	int		i, len = mi_ip_len(ipver);

	for (i = 0; i < NUM_MITBL_ENTRIES; i++) {
		if (!mi_node_is_free(&mi_tbl[i]) &&
		    (mi_tbl[i].ip_ver == ipver) &&
		    (OS_MEMCMP(ip, mi_tbl[i].ip, len) == 0)) {
			return &mi_tbl[i];
		}
	}
	return NULL;
}
Exemple #4
0
int
ieee80211_vap_match_ssid(struct ieee80211vap *vap, const u_int8_t *ssid, u_int8_t ssidlen)
{
    int i;

    for (i = 0; i < vap->iv_des_nssid; i++) {
        if ((vap->iv_des_ssid[i].len == ssidlen) &&
            (OS_MEMCMP(vap->iv_des_ssid[i].ssid, ssid, ssidlen) == 0)) {
            /* find a matching entry */
            return 1;
        }
    }

    return 0;
}
Exemple #5
0
static void
ieee80211_vap_iter_find_connection(void *arg, struct ieee80211vap *vap, bool is_last_vap)
{
    struct ieee80211_mlme_find_connection    *pmlme_find_connection_data = arg;

    UNREFERENCED_PARAMETER(is_last_vap);

    /*
     * If we haven't found a connection yet, check to see if current VAP is 
     * connected to the specified AP.
     */
    if (! pmlme_find_connection_data->connection_found) {
        /*
         * Since ieee80211_mlme_get_bss_entry is not implemented, compare
         * iv_bss's and scan_entry's SSID and BSSID.
         */
        struct ieee80211_node    *bss_node = ieee80211vap_get_bssnode(vap);

        if (bss_node != NULL) {
            /* 
             * Check for BSSID match first; SSID matching is a more expensive
             * operation and should be checked last.
             */
            if (IEEE80211_ADDR_EQ(wlan_node_getbssid(bss_node), 
                                  wlan_scan_entry_bssid(pmlme_find_connection_data->scan_entry))) {
                ieee80211_ssid    bss_ssid;
                u_int8_t          scan_entry_ssid_len;
                u_int8_t          *scan_entry_ssid;

                /*
                 * BSSID matched, let's check the SSID
                 */
                wlan_get_bss_essid(vap, &bss_ssid);
                scan_entry_ssid  = 
                    wlan_scan_entry_ssid(pmlme_find_connection_data->scan_entry,
                                         &scan_entry_ssid_len);

                if (scan_entry_ssid != NULL) {
                    pmlme_find_connection_data->connection_found =                    
                        (scan_entry_ssid_len == bss_ssid.len)          &&
                        (OS_MEMCMP(scan_entry_ssid, bss_ssid.ssid, bss_ssid.len) == 0);
                }
            }
        }
    }
}
v_BOOL_t vos_is_mmie_valid(v_U8_t *igtk, v_U8_t *ipn,
                           v_U8_t* frm, v_U8_t* efrm)
{
    struct ieee80211_mmie  *mmie;
    struct ieee80211_frame *wh;
    v_U8_t *rx_ipn, aad[AAD_LEN], mic[CMAC_TLEN], *input;
    v_U16_t nBytes = 0;
    int ret = 0;
    struct crypto_cipher *tfm;

    /* Check if frame is invalid length */
    if ((efrm < frm) || ((efrm - frm) < sizeof(*wh))) {
        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
                "Invalid frame length");
        return VOS_FALSE;
    }

    mmie = (struct ieee80211_mmie *)(efrm - sizeof(*mmie));

    /* Check Element ID */
    if ((mmie->element_id != IEEE80211_ELEMID_MMIE) ||
        (mmie->length != (sizeof(*mmie)-2))) {
        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
                "IE is not Mgmt MIC IE or Invalid length");
        /* IE is not Mgmt MIC IE or invalid length */
        return VOS_FALSE;
    }

    /* Validate IPN */
    rx_ipn = mmie->sequence_number;
    if (OS_MEMCMP(rx_ipn, ipn, CMAC_IPN_LEN) <= 0)
    {
        /* Replay error */
        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
            "Replay error mmie ipn %02X %02X %02X %02X %02X %02X"
            " drvr ipn %02X %02X %02X %02X %02X %02X",
            rx_ipn[0], rx_ipn[1], rx_ipn[2], rx_ipn[3], rx_ipn[4], rx_ipn[5],
            ipn[0], ipn[1], ipn[2], ipn[3], ipn[4], ipn[5]);
        return VOS_FALSE;
    }

#if  !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO))
    tfm = crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC);
#else
    tfm = wcnss_wlan_crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC);
#endif
    if (IS_ERR(tfm)) {
        ret = PTR_ERR(tfm);
        tfm = NULL;
        VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,
             "crypto_alloc_cipher failed (%d)", ret);
        goto err_tfm;
    }

    ret = crypto_cipher_setkey(tfm, igtk, AES_KEYSIZE_128);
    if (ret) {
        VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,
             "crypto_cipher_setkey failed (%d)", ret);
        goto err_tfm;
    }

    /* Construct AAD */
    wh = (struct ieee80211_frame *)frm;

    /* Generate BIP AAD: FC(masked) || A1 || A2 || A3 */

    /* FC type/subtype */
    aad[0] = wh->i_fc[0];
    /* Mask FC Retry, PwrMgt, MoreData flags to zero */
    aad[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT |
                             IEEE80211_FC1_MORE_DATA);
    /* A1 || A2 || A3 */
    vos_mem_copy(aad + 2, wh->i_addr_all, 3 * IEEE80211_ADDR_LEN);

    /* MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */
    nBytes = AAD_LEN + (efrm - (v_U8_t*)(wh+1));
    input = (v_U8_t *)vos_mem_malloc(nBytes);
    if (NULL == input)
    {
        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
             "Memory allocation failed");
        ret = VOS_STATUS_E_NOMEM;
        goto err_tfm;
    }

    /* Copy the AAD, MMIE with 8 bit MIC zeroed out */
    vos_mem_zero(input, nBytes);
    vos_mem_copy(input, aad, AAD_LEN);
    vos_mem_copy(input+AAD_LEN, (v_U8_t*)(wh+1), nBytes - AAD_LEN - CMAC_TLEN);

#if  !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO))
    cmac_calc_mic(tfm, input, nBytes, mic);
#else
    wcnss_wlan_cmac_calc_mic(tfm, input, nBytes, mic);
#endif
    vos_mem_free(input);

    VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
            "CMAC(T)= %02X %02X %02X %02X %02X %02X %02X %02X",
            mic[0], mic[1], mic[2], mic[3],
            mic[4], mic[5], mic[6], mic[7]);

    if (OS_MEMCMP(mic, mmie->mic, CMAC_TLEN) != 0) {
        /* MMIE MIC mismatch */
        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
                "BC/MC MGMT frame MMIE MIC check Failed"
                " rmic %02X %02X %02X %02X %02X %02X %02X %02X"
                " cmic %02X %02X %02X %02X %02X %02X %02X %02X",
                mmie->mic[0], mmie->mic[1], mmie->mic[2], mmie->mic[3],
                mmie->mic[4], mmie->mic[5], mmie->mic[6], mmie->mic[7],
                mic[0], mic[1], mic[2], mic[3],
                mic[4], mic[5], mic[6], mic[7]);
        return VOS_FALSE;
    }

    /* Update IPN */
    vos_mem_copy(ipn, rx_ipn, CMAC_IPN_LEN);

err_tfm:
    if (tfm)
#if  !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO))
        crypto_free_cipher(tfm);
#else
        wcnss_wlan_crypto_free_cipher(tfm);
#endif

    return !ret?VOS_TRUE:VOS_FALSE;
}
Exemple #7
0
void ieee80211_recv_beacon_ibss(struct ieee80211_node *ni, wbuf_t wbuf, int subtype, 
                                struct ieee80211_rx_status *rs, ieee80211_scan_entry_t  scan_entry)
{
    struct ieee80211vap                          *vap = ni->ni_vap;
    struct ieee80211com                          *ic = ni->ni_ic;
    u_int16_t                                    capinfo;
    int                                          ibssmerge = 0;
    struct ieee80211_channelswitch_ie            *chanie = NULL;
    struct ieee80211_extendedchannelswitch_ie    *echanie = NULL;
    struct ieee80211_frame                       *wh;
    u_int64_t                                    tsf;
    u_int8_t                                     *quiet_elm = NULL; 
    bool                                         free_node = FALSE;
#if ATH_SUPPORT_IBSS_DFS
    struct ieee80211_ibssdfs_ie                  *ibssdfsie = NULL;
#endif /* ATH_SUPPORT_IBSS_DFS */

    wh = (struct ieee80211_frame *)wbuf_header(wbuf);
    capinfo = ieee80211_scan_entry_capinfo(scan_entry);

    if (!(capinfo & IEEE80211_CAPINFO_IBSS))
        return;

    OS_MEMCPY((u_int8_t *)&tsf, ieee80211_scan_entry_tsf(scan_entry), sizeof(tsf));
    if (ni != ni->ni_bss_node) {
        OS_MEMCPY(ni->ni_tstamp.data, &tsf, sizeof(ni->ni_tstamp));
        /* update activity indication */
        ni->ni_beacon_rstamp = OS_GET_TIMESTAMP();
        ni->ni_probe_ticks   = 0;
    }

    /*
     * Check BBSID before updating our beacon configuration to make 
     * sure the received beacon really belongs to our Adhoc network.
     */
    if ((subtype == IEEE80211_FC0_SUBTYPE_BEACON) &&
        ieee80211_vap_ready_is_set(vap) &&
        (IEEE80211_ADDR_EQ(wh->i_addr3, ieee80211_node_get_bssid(vap->iv_bss)))) {
        /*
         * if the neighbor is not in the list, add it to the list.
         */
        if (ni == ni->ni_bss_node) {
            ni = ieee80211_add_neighbor(ni, scan_entry);
            if (ni == NULL) {
                return;
            }
            OS_MEMCPY(ni->ni_tstamp.data, &tsf, sizeof(ni->ni_tstamp));
            free_node = TRUE;
        }
        ni->ni_rssi = rs->rs_rssi;

        /*
         * record tsf of last beacon into bss node
         */
        OS_MEMCPY(ni->ni_bss_node->ni_tstamp.data, &tsf, sizeof(ni->ni_tstamp));

        /*
         * record absolute time of last beacon
         */
        vap->iv_last_beacon_time = OS_GET_TIMESTAMP();

        ic->ic_beacon_update(ni, rs->rs_rssi);

#if ATH_SUPPORT_IBSS_WMM
        /*
         * check for WMM parameters
         */
        if ((ieee80211_scan_entry_wmeparam_ie(scan_entry) != NULL) ||
            (ieee80211_scan_entry_wmeinfo_ie(scan_entry)  != NULL)) {

            /* Node is WMM-capable if WME IE (either subtype) is present */
            ni->ni_ext_caps |= IEEE80211_NODE_C_QOS;

            /* QOS-enable */
            ieee80211node_set_flag(ni, IEEE80211_NODE_QOS);
        } else {
            /* If WME IE not present node is not WMM capable */
            ni->ni_ext_caps &= ~IEEE80211_NODE_C_QOS;
            
            ieee80211node_clear_flag(ni, IEEE80211_NODE_QOS);
        }
#endif  
#if ATH_SUPPORT_IBSS_DFS

        if (ic->ic_curchan->ic_flagext & IEEE80211_CHAN_DFS) {
            //check and see if we need to update other info for ibss_dfsie
            ibssdfsie = (struct ieee80211_ibssdfs_ie *)ieee80211_scan_entry_ibssdfs_ie(scan_entry);
            if(ibssdfsie) {
               if (ieee80211_check_and_update_ibss_dfs(vap, ibssdfsie)) {
                   ieee80211_ibss_beacon_update_start(ic);
               }
            }

            /* update info from DFS owner */
            if(ibssdfsie){
                if(IEEE80211_ADDR_EQ(wh->i_addr2, ibssdfsie->owner)) {
                    if(OS_MEMCMP(ibssdfsie, &vap->iv_ibssdfs_ie_data, MIN_IBSS_DFS_IE_CONTENT_SIZE)) {
                        if(le64_to_cpu(tsf) >= rs->rs_tstamp.tsf){
                            IEEE80211_ADDR_COPY(vap->iv_ibssdfs_ie_data.owner, ibssdfsie->owner);
                            vap->iv_ibssdfs_ie_data.rec_interval = ibssdfsie->rec_interval;
                            ieee80211_ibss_beacon_update_start(ic);
                        }
                    }
                }
            }
            /* check if owner and it is not transmitting ibssIE */
            else if(IEEE80211_ADDR_EQ(wh->i_addr2, vap->iv_ibssdfs_ie_data.owner)){
                IEEE80211_ADDR_COPY(vap->iv_ibssdfs_ie_data.owner, vap->iv_myaddr);
                vap->iv_ibssdfs_state = IEEE80211_IBSSDFS_OWNER;
                ieee80211_ibss_beacon_update_start(ic);            
            } 
        }
   
#endif /* ATH_SUPPORT_IBSS_DFS */

        /*
         * check for spectrum management
         */
        if (capinfo & IEEE80211_CAPINFO_SPECTRUM_MGMT) {
            chanie  = (struct ieee80211_channelswitch_ie *)         ieee80211_scan_entry_csa(scan_entry);
#if ATH_SUPPORT_IBSS_DFS
            if(chanie)
            {
                 OS_MEMCPY(&vap->iv_channelswitch_ie_data, chanie, sizeof(struct ieee80211_channelswitch_ie));
                 ieee80211_ibss_beacon_update_start(ic);
            }
#endif /* ATH_SUPPORT_IBSS_DFS */
            echanie = (struct ieee80211_extendedchannelswitch_ie *) ieee80211_scan_entry_xcsa(scan_entry);
            if ((!chanie) && (!echanie)) {
                quiet_elm = ieee80211_scan_entry_quiet(scan_entry);
            }
        }
    }

    /*
     * Handle ibss merge as needed; check the tsf on the
     * frame before attempting the merge.  The 802.11 spec
     * says the station should change its bssid to match
     * the oldest station with the same ssid, where oldest
     * is determined by the tsf.  Note that hardware
     * reconfiguration happens through callback to
     * ath as the state machine will go from
     * RUN -> RUN when this happens.
     */
    if (ieee80211_vap_ready_is_set(vap) &&
        (le64_to_cpu(tsf) >= rs->rs_tstamp.tsf)) {
        ibssmerge = ieee80211_ibss_merge(ni,scan_entry);
    }

    if (ibssmerge) {
        ieee80211_mlme_adhoc_merge_start(ni);
    }

    /*
     * RNWF-specific: indicate to NDIS about the potential association.
     * It should be done after IBSS merge, which is called from ath_beacon_update().
     */
    if (IEEE80211_ADDR_EQ(wh->i_addr3, ieee80211_node_get_bssid(ni))) {
        /* Indicate node joined IBSS */
    if ((capinfo & IEEE80211_CAPINFO_RADIOMEAS)
         && ieee80211_vap_rrm_is_set(vap)) {
        if(ni->ni_assoc_state != IEEE80211_NODE_ADHOC_STATE_AUTH_ASSOC)
            ieee80211_set_node_rrm(ni,TRUE);
    } else {
        ieee80211_set_node_rrm(ni,FALSE);
    } 
        ieee80211_mlme_adhoc_join_indication(ni, wbuf);

        /* notify mlme of beacon reception */
        ieee80211_mlme_join_complete_adhoc(ni);
    }

    if (ibssmerge) {
        ieee80211_mlme_adhoc_merge_completion(ni);
    }

    if (quiet_elm) {
        ic->ic_set_quiet(ni, quiet_elm);
    }

    if (free_node == TRUE) {
        ieee80211_free_node(ni);
    }

}
Exemple #8
0
/* Interface functions */
static struct ieee80211_node *
ol_ath_node_alloc(struct ieee80211vap *vap, const u_int8_t *macaddr, bool tmpnode)
{
    struct ieee80211com *ic = vap->iv_ic;
    struct ol_ath_vap_net80211 *avn = OL_ATH_VAP_NET80211(vap);
    struct ol_ath_softc_net80211 *scn = OL_ATH_SOFTC_NET80211(ic);
    struct ol_ath_node_net80211 *anode;

    adf_os_spin_lock_bh(&scn->scn_lock);
    scn->peer_count++;
    if (scn->peer_count > scn->wlan_resource_config.num_peers) {
        adf_os_spin_unlock_bh(&scn->scn_lock);
        printk("%s: vap (%p) scn (%p) the peer count exceeds the supported number %d \n",
                __func__, vap, scn, scn->wlan_resource_config.num_peers);
        goto err_node_alloc;
    }
    adf_os_spin_unlock_bh(&scn->scn_lock);

    anode = (struct ol_ath_node_net80211 *)OS_MALLOC(scn->sc_osdev,
                                                  sizeof(struct ol_ath_node_net80211),
                                                  GFP_ATOMIC);
    if (anode == NULL)
        goto err_node_alloc;

    OS_MEMZERO(anode, sizeof(struct ol_ath_node_net80211));

    anode->an_node.ni_vap = vap;

    /* do not create/delete peer on target for temp nodes and self-peers */
    if (!tmpnode && !is_node_self_peer(vap, macaddr)) {
        if (wmi_unified_peer_create_send(scn->wmi_handle, macaddr,avn->av_if_id)) {
            printk("%s : Unable to create peer in Target \n", __func__);
            OS_FREE(anode);
            goto err_node_alloc;
        }

        adf_os_spin_lock_bh(&scn->scn_lock);
        anode->an_txrx_handle = ol_txrx_peer_attach(scn->pdev_txrx_handle,
                avn->av_txrx_handle, (u_int8_t *) macaddr);

        if (anode->an_txrx_handle == NULL) {
			adf_os_spin_unlock_bh(&scn->scn_lock);
            printk("%s : Unable to attach txrx peer\n", __func__);
            OS_FREE(anode);
            goto err_node_alloc;
        }
        adf_os_spin_unlock_bh(&scn->scn_lock);

        /* static wep keys stored in vap needs to be
         * pushed to all nodes except self node
         */
        if(IEEE80211_VAP_IS_PRIVACY_ENABLED(vap) &&
                (OS_MEMCMP(macaddr,vap->iv_myaddr,IEEE80211_ADDR_LEN) != 0 )) {
            set_node_wep_keys(vap,macaddr);
        }
    }

    return &anode->an_node;

err_node_alloc:
    adf_os_spin_lock_bh(&scn->scn_lock);
    scn->peer_count--;
    adf_os_spin_unlock_bh(&scn->scn_lock);
    return NULL;

}
Exemple #9
0
/*
 * Update the dynamic parts of a beacon frame based on the current state.
 */
int
ieee80211_beacon_update(struct ieee80211_node *ni,
                               struct ieee80211_beacon_offsets *bo, wbuf_t wbuf, int mcast)
{
    struct ieee80211vap *vap = ni->ni_vap;
    struct ieee80211com *ic = ni->ni_ic;
    int len_changed = 0;
    u_int16_t capinfo;
    struct ieee80211_frame *wh = (struct ieee80211_frame *)wbuf_header(wbuf);
    int enable_htrates;
    bool update_beacon_copy = false;
#if ATH_SUPPORT_IBSS_DFS
    struct ieee80211_ibssdfs_ie *ibss_ie = NULL;
#endif /* ATH_SUPPORT_IBSS_DFS */

    /* If Beacon Tx is suspended, then don't send this beacon */
    if (ieee80211_mlme_beacon_suspend_state(vap)) {
        IEEE80211_DPRINTF(vap, IEEE80211_MSG_MLME, 
                          "%s: skip Tx beacon during to suspend.\n", __func__);
        return -1;
    }

    /*
     * if vap is paused do not send any beacons to prevent transmitting beacons on wrong channel.
     */
    if (ieee80211_vap_is_paused(vap)) return -1;
    /* use the non-QoS sequence number space for BSS node */
    /* to avoid sw generated frame sequence the same as H/W generated frame,
     * the value lower than min_sw_seq is reserved for HW generated frame */ 
    if ((ni->ni_txseqs[IEEE80211_NON_QOS_SEQ]& IEEE80211_SEQ_MASK) < MIN_SW_SEQ){
        ni->ni_txseqs[IEEE80211_NON_QOS_SEQ] = MIN_SW_SEQ;  
    }
    *(u_int16_t *)&wh->i_seq[0] =
        htole16(ni->ni_txseqs[IEEE80211_NON_QOS_SEQ] << IEEE80211_SEQ_SEQ_SHIFT);
    ni->ni_txseqs[IEEE80211_NON_QOS_SEQ]++;

      /* Check if channel change due to CW interference needs to be done.
     * Since this is a drastic channel change, we do not wait for the TBTT interval to expair and 
     * do not send Channel change flag in beacon  
    */

	/* AUTELAN-Added-Begin : &tuqiang for openessid*/

	if(openessid_param & OPENESSID_ENABLE_MASK)
		vap->channel_change_done = 1;

	/* AUTELAN-Added-End : [email protected] */
    if (vap->channel_change_done) {
        u_int8_t *frm;

        IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, "%s: reinit beacon\n", __func__);

        /*
        * NB: iv_bsschan is in the DSPARMS beacon IE, so must set this
        *     prior to the beacon re-init, below.
        */
        frm = (u_int8_t *) wbuf_header(wbuf) + sizeof(struct ieee80211_frame);
        frm = ieee80211_beacon_init(ni, bo, frm);
        update_beacon_copy = true;
        wbuf_set_pktlen(wbuf, (frm - (u_int8_t *)wbuf_header(wbuf)));

        len_changed = 1;
        vap->channel_change_done = 0;
        if ( ic->cw_inter_found) ic->cw_inter_found = 0;
    }

    if (ieee80211_ic_doth_is_set(ic) && (vap->iv_flags & IEEE80211_F_CHANSWITCH) &&
        (vap->iv_chanchange_count == ic->ic_chanchange_tbtt) 
#ifdef MAGPIE_HIF_GMAC        
        && !ic->ic_chanchange_cnt) {
#else
        ) {
#endif            
        u_int8_t *frm;
        struct ieee80211_channel *c;

        vap->iv_chanchange_count = 0;

        IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, "%s: reinit beacon\n", __func__);

        /*
         * NB: iv_bsschan is in the DSPARMS beacon IE, so must set this
         *     prior to the beacon re-init, below.
         */
        c = ieee80211_doth_findchan(vap, ic->ic_chanchange_chan);
        if (c == NULL) {
            IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, "%s: find channel failure\n", __func__);
            return 0;
        }
        vap->iv_bsschan = c;

        frm = (u_int8_t *) wbuf_header(wbuf) + sizeof(struct ieee80211_frame);
        frm = ieee80211_beacon_init(ni, bo, frm);
        update_beacon_copy = true;
        wbuf_set_pktlen(wbuf, (frm - (u_int8_t *)wbuf_header(wbuf)));

        vap->iv_flags &= ~IEEE80211_F_CHANSWITCH;
        
#ifdef MAGPIE_HIF_GMAC
        vap->iv_chanswitch = 0;
#endif        
        ic->ic_flags &= ~IEEE80211_F_CHANSWITCH;
#if ATH_SUPPORT_IBSS_DFS
        if(vap->iv_opmode == IEEE80211_M_IBSS) {
            if (IEEE80211_ADDR_EQ(vap->iv_ibssdfs_ie_data.owner, vap->iv_myaddr)) {
                vap->iv_ibssdfs_state = IEEE80211_IBSSDFS_OWNER;
            } else {
                vap->iv_ibssdfs_state = IEEE80211_IBSSDFS_JOINER;
            }
        }
#endif

        /* NB: only for the first VAP to get here */
        if (ic->ic_curchan != c) {
            ieee80211_set_channel(ic, c);
        }

        len_changed = 1;
    }

    /*Begin:zhanghu added for beacon_frame rate support*/
    else if(ic->ic_rate_mask != ic->ic_rate_mask_bak || \
        ic->ic_mcs_mask != ic->ic_mcs_mask_bak){
        u_int8_t *frm = NULL;
        frm = (u_int8_t *) wbuf_header(wbuf) + sizeof(struct ieee80211_frame);
        frm = ieee80211_beacon_init(ni, bo, frm);
        update_beacon_copy = true;
        wbuf_set_pktlen(wbuf, (frm - (u_int8_t *)wbuf_header(wbuf)));
        len_changed = 1;
    }
    /*End:zhanghu added for beacon_frame rate support*/

    /* XXX faster to recalculate entirely or just changes? */
    if (vap->iv_opmode == IEEE80211_M_IBSS)
        capinfo = IEEE80211_CAPINFO_IBSS;
    else
        capinfo = IEEE80211_CAPINFO_ESS;
    if (IEEE80211_VAP_IS_PRIVACY_ENABLED(vap))
        capinfo |= IEEE80211_CAPINFO_PRIVACY;
    if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
        IEEE80211_IS_CHAN_2GHZ(vap->iv_bsschan))
        capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
    if (ic->ic_flags & IEEE80211_F_SHSLOT)
        capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
    if (ieee80211_ic_doth_is_set(ic) && ieee80211_vap_doth_is_set(vap))
        capinfo |= IEEE80211_CAPINFO_SPECTRUM_MGMT;

    if (IEEE80211_VAP_IS_PUREB_ENABLED(vap)){
        capinfo &= ~IEEE80211_CAPINFO_SHORT_SLOTTIME;
    }
    *bo->bo_caps = htole16(capinfo);

    if (ieee80211_vap_wme_is_set(vap) &&
#if ATH_SUPPORT_IBSS_WMM
        (vap->iv_opmode == IEEE80211_M_HOSTAP || vap->iv_opmode == IEEE80211_M_IBSS)) {
#else
        vap->iv_opmode == IEEE80211_M_HOSTAP) {
#endif
        struct ieee80211_wme_state *wme = &ic->ic_wme;

        /* XXX multi-bss */
        if (vap->iv_flags & IEEE80211_F_WMEUPDATE) {
            (void) ieee80211_add_wme_param(bo->bo_wme, wme, IEEE80211_VAP_IS_UAPSD_ENABLED(vap));
            update_beacon_copy = true;
            vap->iv_flags &= ~IEEE80211_F_WMEUPDATE;
        }
    }

    enable_htrates = ieee80211vap_htallowed(vap);

    /*
     * HT cap. check for vap is done in ieee80211vap_htallowed.
     * TBD: remove iv_bsschan check to support multiple channel operation.
     */
    if (IEEE80211_IS_CHAN_11N(vap->iv_bsschan) && enable_htrates) {
        struct ieee80211_ie_htinfo_cmn *htinfo;
        struct ieee80211_ie_obss_scan *obss_scan;
#if IEEE80211_BEACON_NOISY 
		IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N,
                          "%s: AP: updating HT Info IE (ANA) for %s\n",
                          __func__, ether_sprintf(ni->ni_macaddr));
		if (bo->bo_htinfo[0] != IEEE80211_ELEMID_HTINFO_ANA) {
			IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N,
                              "%s: AP: HT Info IE (ANA) beacon offset askew %s "
                              "expected 0x%02x, found 0x%02x\n",
                              __func__, ether_sprintf(ni->ni_macaddr),
                              IEEE80211_ELEMID_HTINFO_ANA, bo->bo_htinfo[0] );
		}
#endif
        htinfo = &((struct ieee80211_ie_htinfo *)bo->bo_htinfo)->hi_ie;
		if (bo->bo_htinfo)
			ieee80211_update_htinfo_cmn(htinfo, ni);

		if (bo->bo_htcap)
			ieee80211_add_htcap(bo->bo_htcap, ni, IEEE80211_FC0_SUBTYPE_BEACON);

        if (!(ic->ic_flags & IEEE80211_F_COEXT_DISABLE)) {
            obss_scan = (struct ieee80211_ie_obss_scan *)bo->bo_obss_scan;
			/*Beginning:Modified by zhaoyang1 for APVXI-30 2013-03-04*/
			if (obss_scan)
				ieee80211_update_obss_scan(obss_scan, ni);
			/*Ending:Modified by zhaoyang1 for APVXI-30 2013-03-04*/
        }

        if (IEEE80211_IS_HTVIE_ENABLED(ic)) {
#if IEEE80211_BEACON_NOISY 
			IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N,
                              "%s: AP: updating HT Info IE (Vendor Specific) for %s\n",
                              __func__, ether_sprintf(ni->ni_macaddr));
			if (bo->bo_htinfo_vendor_specific[5] != IEEE80211_ELEMID_HTINFO) {
				IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N,
                                  "%s: AP: HT Info IE (Vendor Specific) beacon offset askew %s ",
                                  "expected 0x%02x, found 0x%02x\n",
                                  __func__, ether_sprintf(ni->ni_macaddr),
                                  IEEE80211_ELEMID_HTINFO_ANA, bo->bo_htinfo_vendor_specific[5] );
			}
#endif
            htinfo = &((struct vendor_ie_htinfo *)bo->bo_htinfo_vendor_specific)->hi_ie;
            ieee80211_update_htinfo_cmn(htinfo, ni);
        }
    }

    if (vap->iv_opmode == IEEE80211_M_HOSTAP || vap->iv_opmode == IEEE80211_M_IBSS) {
        struct ieee80211_tim_ie *tie =
            (struct ieee80211_tim_ie *) bo->bo_tim;
        if (IEEE80211_VAP_IS_TIMUPDATE_ENABLED(vap) && vap->iv_opmode == IEEE80211_M_HOSTAP) {
            u_int timlen, timoff, i;
            /*
             * ATIM/DTIM needs updating.  If it fits in the
             * current space allocated then just copy in the
             * new bits.  Otherwise we need to move any trailing
             * data to make room.  Note that we know there is
             * contiguous space because ieee80211_beacon_allocate
             * insures there is space in the wbuf to write a
             * maximal-size virtual bitmap (based on ic_max_aid).
             */
            /*
             * Calculate the bitmap size and offset, copy any
             * trailer out of the way, and then copy in the
             * new bitmap and update the information element.
             * Note that the tim bitmap must contain at least
             * one byte and any offset must be even.
             */
            if (vap->iv_ps_pending != 0) {
                timoff = 128;        /* impossibly large */
                for (i = 0; i < vap->iv_tim_len; i++) {
                    if (vap->iv_tim_bitmap[i]) {
                        timoff = i &~ 1;
                        break;
                    }
                }
                KASSERT(timoff != 128, ("tim bitmap empty!"));
                for (i = vap->iv_tim_len-1; i >= timoff; i--)
                    if (vap->iv_tim_bitmap[i])
                        break;
                timlen = 1 + (i - timoff);
            } else {
                timoff = 0;
                timlen = 1;
            }
            tie->tim_bitctl = timoff;
            if (timlen != bo->bo_tim_len) {
                int trailer_adjust = (tie->tim_bitmap+timlen) - bo->bo_tim_trailer;
                /* copy up/down trailer */
                OS_MEMCPY(tie->tim_bitmap+timlen, bo->bo_tim_trailer, 
                          bo->bo_tim_trailerlen);
                bo->bo_tim_trailer = tie->tim_bitmap+timlen;
                bo->bo_chanswitch += trailer_adjust;
                bo->bo_wme += trailer_adjust;
                bo->bo_erp += trailer_adjust;
                bo->bo_ath_caps += trailer_adjust;
                bo->bo_appie_buf += trailer_adjust;
                bo->bo_xr += trailer_adjust;
				/*zhaoyang1 transplant from 717*/
				/*Begin:Added by duanmingzhe for adjust pointer*/
				bo->bo_htcap +=trailer_adjust;
				bo->bo_obss_scan +=trailer_adjust;
		        bo->bo_extcap +=trailer_adjust;
			    /*End:Added by duanmingzhe for adjust pointer*/
				/*zhaoyang1 transplant end*/
#ifdef E_CSA
                bo->bo_extchanswitch += trailer_adjust;
#endif /* E_CSA */
#if ATH_SUPPORT_IBSS_DFS
                bo->bo_ibssdfs += trailer_adjust;
#endif /* ATH_SUPPORT_IBSS_DFS */
                bo->bo_htinfo += trailer_adjust;
                bo->bo_htinfo_pre_ana += trailer_adjust;
                bo->bo_htinfo_vendor_specific += trailer_adjust;
                if (timlen > bo->bo_tim_len)
                    wbuf_append(wbuf, timlen - bo->bo_tim_len);
                else
                    wbuf_trim(wbuf, bo->bo_tim_len - timlen);
                bo->bo_tim_len = timlen;
                
                /* update information element */
                tie->tim_len = 3 + timlen;
                len_changed = 1;
			}
            OS_MEMCPY(tie->tim_bitmap, vap->iv_tim_bitmap + timoff,
                      bo->bo_tim_len);

            IEEE80211_VAP_TIMUPDATE_DISABLE(vap);

            IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                           "%s: TIM updated, pending %u, off %u, len %u\n",
                           __func__, vap->iv_ps_pending, timoff, timlen);
        }
        if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
            /* count down DTIM period */
            if (tie->tim_count == 0)
                tie->tim_count = tie->tim_period - 1;
            else
                tie->tim_count--;
            /* update state for buffered multicast frames on DTIM */
		    if (mcast && (tie->tim_count == 0 || tie->tim_period == 1))
                tie->tim_bitctl |= 1;
            else
                tie->tim_bitctl &= ~1;
        }
        if (ieee80211_ic_doth_is_set(ic) && (ic->ic_flags & IEEE80211_F_CHANSWITCH) 
#ifdef MAGPIE_HIF_GMAC                
                && (!vap->iv_chanswitch)) {
#else
        ) {
#endif            
            if (!vap->iv_chanchange_count) {

		u_int8_t	* tempbuf;
		
                vap->iv_flags |= IEEE80211_F_CHANSWITCH;

                /* copy out trailer to open up a slot */
		tempbuf = OS_MALLOC(vap->iv_ic->ic_osdev, bo->bo_chanswitch_trailerlen , GFP_KERNEL);
		OS_MEMCPY(tempbuf,bo->bo_chanswitch, bo->bo_chanswitch_trailerlen);
		
                OS_MEMCPY(bo->bo_chanswitch + IEEE80211_CHANSWITCHANN_BYTES, 
                          tempbuf, bo->bo_chanswitch_trailerlen);
		OS_FREE(tempbuf);

                /* add ie in opened slot */
                bo->bo_chanswitch[0] = IEEE80211_ELEMID_CHANSWITCHANN;
                bo->bo_chanswitch[1] = 3; /* fixed length */
                bo->bo_chanswitch[2] = 1; /* stas get off for now */
                bo->bo_chanswitch[3] = ic->ic_chanchange_chan;
                bo->bo_chanswitch[4] = ic->ic_chanchange_tbtt;

                /* update the trailer lens */
                bo->bo_chanswitch_trailerlen += IEEE80211_CHANSWITCHANN_BYTES;
#if ATH_SUPPORT_IBSS_DFS
                bo->bo_ibssdfs += IEEE80211_CHANSWITCHANN_BYTES;
#endif /* ATH_SUPPORT_IBSS_DFS */                
                bo->bo_tim_trailerlen += IEEE80211_CHANSWITCHANN_BYTES;
                bo->bo_wme += IEEE80211_CHANSWITCHANN_BYTES;
                bo->bo_erp += IEEE80211_CHANSWITCHANN_BYTES;
                bo->bo_ath_caps += IEEE80211_CHANSWITCHANN_BYTES;
                bo->bo_appie_buf += IEEE80211_CHANSWITCHANN_BYTES;
                bo->bo_xr += IEEE80211_CHANSWITCHANN_BYTES;
#ifdef E_CSA
                bo->bo_extchanswitch += IEEE80211_CHANSWITCHANN_BYTES;
#endif /* E_CSA */
                bo->bo_htinfo += IEEE80211_CHANSWITCHANN_BYTES;
                bo->bo_htinfo_pre_ana += IEEE80211_CHANSWITCHANN_BYTES;
                bo->bo_htinfo_vendor_specific += IEEE80211_CHANSWITCHANN_BYTES;
		bo->bo_htcap += IEEE80211_CHANSWITCHANN_BYTES;
		bo->bo_extcap += IEEE80211_CHANSWITCHANN_BYTES;
		bo->bo_obss_scan += IEEE80211_CHANSWITCHANN_BYTES;

                /* indicate new beacon length so other layers may manage memory */
                wbuf_append(wbuf, IEEE80211_CHANSWITCHANN_BYTES);
                len_changed = 1;
            }
            else {
#ifdef MAGPIE_HIF_GMAC
                if(vap->iv_chanchange_count != ic->ic_chanchange_tbtt)   
                    bo->bo_chanswitch[4]--;
#else
                 bo->bo_chanswitch[4]--;
#endif                 
            }
#ifdef MAGPIE_HIF_GMAC            
            if(vap->iv_chanchange_count != ic->ic_chanchange_tbtt) {
                vap->iv_chanchange_count++;
                ic->ic_chanchange_cnt--;
            }    
             
            if(vap->iv_chanchange_count == ic->ic_chanchange_tbtt)
               vap->iv_chanswitch = 1; 
#else
            vap->iv_chanchange_count++;
#endif             
            IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, "%s: CHANSWITCH IE, change in %d \n",
                              __func__, bo->bo_chanswitch[4]);
        }
    }
#if ATH_SUPPORT_IBSS_DFS
    if (vap->iv_opmode == IEEE80211_M_IBSS &&
        (ic->ic_curchan->ic_flagext & IEEE80211_CHAN_DFS)) {
        /*reset action frames counts for measrep and csa action */
        vap->iv_measrep_action_count_per_tbtt = 0;
        vap->iv_csa_action_count_per_tbtt = 0;

        if(vap->iv_ibssdfs_state == IEEE80211_IBSSDFS_OWNER) {
            vap->iv_ibssdfs_ie_data.rec_interval = vap->iv_ibss_dfs_enter_recovery_threshold_in_tbtt;
        }
        
        ibss_ie =(struct ieee80211_ibssdfs_ie *) bo->bo_ibssdfs;
        if(ibss_ie) {
            if (OS_MEMCMP(bo->bo_ibssdfs, &vap->iv_ibssdfs_ie_data, ibss_ie->len + sizeof(struct ieee80211_ie_header))) {
                int trailer_adjust = vap->iv_ibssdfs_ie_data.len - ibss_ie->len;
                /* copy up/down trailer */
                if(trailer_adjust > 0) {
                    u_int8_t	* tempbuf;
            		tempbuf = OS_MALLOC(vap->iv_ic->ic_osdev, bo->bo_ibssdfs_trailerlen , GFP_KERNEL);
            		if (tempbuf == NULL) {
            		   IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY, "%s: Unable to alloc ibssdfs copy buf. Size=%d\n",
                                        __func__, bo->bo_ibssdfs_trailerlen);
                        return -1;
            		}
            		OS_MEMCPY(tempbuf,bo->bo_ibssdfs + sizeof(struct ieee80211_ie_header) + ibss_ie->len, bo->bo_ibssdfs_trailerlen);
                    OS_MEMCPY(bo->bo_ibssdfs + sizeof(struct ieee80211_ie_header) + vap->iv_ibssdfs_ie_data.len, 
                              tempbuf, 
                              bo->bo_ibssdfs_trailerlen);
            		OS_FREE(tempbuf);
        		} else {
                    
                    OS_MEMCPY(bo->bo_ibssdfs + sizeof(struct ieee80211_ie_header) + vap->iv_ibssdfs_ie_data.len ,
                              bo->bo_ibssdfs + sizeof(struct ieee80211_ie_header) + ibss_ie->len, 
                              bo->bo_ibssdfs_trailerlen);
                }
                    
                bo->bo_tim_trailerlen += trailer_adjust;
                bo->bo_chanswitch_trailerlen += trailer_adjust;
                bo->bo_wme += trailer_adjust;
                bo->bo_erp += trailer_adjust;
                bo->bo_ath_caps += trailer_adjust;
                bo->bo_appie_buf += trailer_adjust;
                bo->bo_xr += trailer_adjust;
#ifdef E_CSA
                bo->bo_extchanswitch += trailer_adjust;
#endif /* E_CSA */
                bo->bo_htinfo += trailer_adjust;
                bo->bo_htinfo_pre_ana += trailer_adjust;
                bo->bo_htinfo_vendor_specific += trailer_adjust;
                bo->bo_htcap += trailer_adjust;
                bo->bo_extcap += trailer_adjust;
                bo->bo_obss_scan += trailer_adjust;
                if (trailer_adjust >  0) {
                    wbuf_append(wbuf, trailer_adjust);
                }
                else {
                    wbuf_trim(wbuf, -trailer_adjust);
                }
                OS_MEMCPY(bo->bo_ibssdfs, &vap->iv_ibssdfs_ie_data, sizeof(struct ieee80211_ie_header) + vap->iv_ibssdfs_ie_data.len);
                len_changed = 1;   
            }
            
        }
        if (vap->iv_ibssdfs_state == IEEE80211_IBSSDFS_JOINER ||
            vap->iv_ibssdfs_state == IEEE80211_IBSSDFS_OWNER) {
            vap->iv_ibssdfs_recovery_count = vap->iv_ibssdfs_ie_data.rec_interval;
            ieee80211_ibss_beacon_update_stop(ic);
         } else if (vap->iv_ibssdfs_state == IEEE80211_IBSSDFS_WAIT_RECOVERY) {
            vap->iv_ibssdfs_recovery_count --;
            if(vap->iv_ibssdfs_recovery_count == 0) {
               IEEE80211_ADDR_COPY(vap->iv_ibssdfs_ie_data.owner, vap->iv_myaddr);
               vap->iv_ibssdfs_state = IEEE80211_IBSSDFS_OWNER;
               vap->iv_ibssdfs_recovery_count = vap->iv_ibssdfs_ie_data.rec_interval;
               ieee80211_dfs_action(vap, NULL);
            }
         }
    } 
#endif /* ATH_SUPPORT_IBSS_DFS */
    if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
        vap->iv_opmode == IEEE80211_M_BTAMP) { /* No IBSS Support */
        if (ieee80211_vap_erpupdate_is_set(vap) && bo->bo_erp) {
            (void) ieee80211_add_erp(bo->bo_erp, ic);
	        ieee80211_vap_erpupdate_clear(vap);
        }
    }

#ifdef E_CSA
    if (ieee80211_ic_doth_is_set(ic) && (ic->ic_flags & IEEE80211_F_CHANSWITCH)) {

        if (!vap->iv_chanchange_count)  {
            /* copy out trailer to open up a slot */
            OS_MEMCPY(bo->bo_extchanswitch + IEEE80211_EXTCHANSWITCHANN_BYTES, 
                      bo->bo_extchanswitch, bo->bo_extchanswitch_trailerlen);

            /* add ie in opened slot */
            bo->bo_extchanswitch[0] = IEEE80211_ELEMID_EXTCHANSWITCHANN;
            bo->bo_extchanswitch[1] = 4; /* fixed length */
            bo->bo_extchanswitch[2] = 1; /* stations get off for now */
            /*
             * XXX: bo_extchanswitch[3] should be regulatory class instead
             * of country code. Currently there is no functionality to retrieve
             * the regulatory classe from HAL. Need to correct this later when
             * we fix the IEEE80211_ELEMID_EXTCHANSWITCHANN to ANA defined
             * value.
             */
            bo->bo_extchanswitch[3] = ic->ic_country_code;
            bo->bo_extchanswitch[4] = ic->ic_chanchange_chan;
            bo->bo_extchanswitch[5] = ic->ic_chanchange_tbtt;

            /* update the trailer lens */
            bo->bo_extchanswitch_trailerlen += IEEE80211_EXTCHANSWITCHANN_BYTES;
            bo->bo_ath_caps += IEEE80211_EXTCHANSWITCHANN_BYTES;
            bo->bo_appie_buf += IEEE80211_EXTCHANSWITCHANN_BYTES;
#if ATH_SUPPORT_IBSS_DFS
            bo->bo_ibssdfs_trailerlen += IEEE80211_EXTCHANSWITCHANN_BYTES;
#endif       
            /* indicate new beacon length so other layers may manage memory */
            wbuf_append(skb, IEEE80211_EXTCHANSWITCHANN_BYTES);
            len_changed = 1;
        }
        else
        {
            bo->bo_extchanswitch[5]--;
        }
        IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, "%s: EXT CHANSWITCH IE, change in %d\n",
                          __func__, bo->bo_extchanswitch[5]);
    }
#endif /* E_CSA */

    /* add APP_IE buffer if app updated it */
#ifdef ATH_BEACON_DEFERRED_PROC
    IEEE80211_VAP_LOCK(vap);
#endif
    if (IEEE80211_VAP_IS_APPIE_UPDATE_ENABLED(vap)) {
        /* adjust the buffer size if the size is changed */
        u_int8_t  *frm;
        u_int32_t newlen = vap->iv_app_ie[IEEE80211_FRAME_TYPE_BEACON].length;

        /* Also add the length from the new App IE module */
        newlen += vap->iv_app_ie_list[IEEE80211_FRAME_TYPE_BEACON].total_ie_len;

        if (newlen != bo->bo_appie_buf_len) {
            int diff_len;
            diff_len = newlen - bo->bo_appie_buf_len;
            bo->bo_appie_buf_len = (u_int16_t) newlen;
            /* update the trailer lens */
            bo->bo_chanswitch_trailerlen += diff_len;
            bo->bo_tim_trailerlen += diff_len;
            if (diff_len > 0)
                wbuf_append(wbuf, diff_len);
            else
                wbuf_trim(wbuf, -(diff_len));
            len_changed = 1;
        }

        if (vap->iv_app_ie[IEEE80211_FRAME_TYPE_BEACON].length) {
            OS_MEMCPY(bo->bo_appie_buf, vap->iv_app_ie[IEEE80211_FRAME_TYPE_BEACON].ie,
                      vap->iv_app_ie[IEEE80211_FRAME_TYPE_BEACON].length);
        }

        /* Add the Application IE's */
        if (vap->iv_app_ie_list[IEEE80211_FRAME_TYPE_BEACON].total_ie_len) {
            frm = bo->bo_appie_buf + vap->iv_app_ie[IEEE80211_FRAME_TYPE_BEACON].length;
            frm = ieee80211_mlme_app_ie_append(vap, IEEE80211_FRAME_TYPE_BEACON, frm);
        }

        IEEE80211_VAP_APPIE_UPDATE_DISABLE(vap);

        update_beacon_copy = true;
    }
#ifdef ATH_BEACON_DEFERRED_PROC
    IEEE80211_VAP_UNLOCK(vap);
#endif

    if (update_beacon_copy && ieee80211_vap_copy_beacon_is_set(vap)) {
        store_beacon_frame(vap, (u_int8_t *)wbuf_header(wbuf), wbuf_get_pktlen(wbuf));
    }

    return len_changed;
}

int
wlan_copy_ap_beacon_frame(wlan_if_t vaphandle, u_int32_t in_buf_size, u_int32_t *required_buf_size, void *buffer)
{
    struct ieee80211vap *vap = vaphandle;
    void *beacon_buf;

    *required_buf_size = 0;

    /* Make sure that this VAP is SoftAP */
    if (vap->iv_opmode != IEEE80211_M_HOSTAP) {
        return EPERM ;
    }

    if (!vap->iv_beacon_copy_buf) {
        /* Error: no beacon buffer */
        return EPERM ;
    }

    if (in_buf_size < vap->iv_beacon_copy_len) {
        /* Input buffer too small */
        *required_buf_size = vap->iv_beacon_copy_len;
        return ENOMEM ;
    }
    *required_buf_size = vap->iv_beacon_copy_len;

    beacon_buf = (void *)vap->iv_beacon_copy_buf;

    OS_MEMCPY(buffer, beacon_buf, vap->iv_beacon_copy_len);

    return EOK;
}