📄 soft_ap.c
字号:
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2005, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attempt
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
soft_ap.c
Abstract:
Revision History:
Who When What
-------- ---------- ----------------------------------------------
John 2004-08-08 Major modification from RT2560
*/
#include "rt_config.h"
char const *pEventText[EVENT_MAX_EVENT_TYPE] = {
"restart access point",
"successfully associated",
"has disassociated",
"has been aged-out and disassociated" ,
"active countermeasures",
"has disassociated with invalid PSK password"};
/*
==========================================================================
Description:
Initialize AP specific data
==========================================================================
*/
NDIS_STATUS ApInitialize(
IN PRTMP_ADAPTER pAd)
{
UCHAR apidx;
DBGPRINT(RT_DEBUG_TRACE, "---> ApInitialize\n");
// Initialize MAC table and allocate spin lock
NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE));
NdisAllocateSpinLock(&pAd->MacTabLock);
for (apidx = 0; apidx < pAd->PortCfg.BssidNum; apidx++)
{
// Init TKIP Group-Key-related variables
GenRandom(pAd,pAd->PortCfg.MBSSID[apidx].GMK, apidx);
GenRandom(pAd,pAd->PortCfg.MBSSID[apidx].GNonce, apidx);
pAd->PortCfg.MBSSID[apidx].PortSecured = WPA_802_1X_PORT_NOT_SECURED;
}
// Init Group key update timer, and countermeasures timer
RTMPInitTimer(pAd, &pAd->PortCfg.REKEYTimer, (PVOID)&GREKEYPeriodicExec);
RTMPInitTimer(pAd, &pAd->PortCfg.CounterMeasureTimer, (PVOID)&CMTimerExec);
RTMPInitTimer(pAd, &pAd->QuickResponeForRateUpTimer, (PVOID)&QuickResponeForRateUp);
DBGPRINT(RT_DEBUG_TRACE, "<--- ApInitialize\n");
return NDIS_STATUS_SUCCESS;
}
/*
==========================================================================
Description:
Shutdown AP and free AP specific resources
==========================================================================
*/
VOID ApShutdown(
IN PRTMP_ADAPTER pAd)
{
DBGPRINT(RT_DEBUG_TRACE, "---> ApShutdown\n");
ApStop(pAd, TRUE);
DBGPRINT(RT_DEBUG_TRACE, "<--- ApShutdown\n");
}
VOID ApStartUp(
IN PRTMP_ADAPTER pAd,
IN BOOLEAN bDFSRestart)
{
UCHAR apidx, i;
ULONG sec_csr4 = 0, MacCsr0 = 0;
BOOLEAN bWmmCapable = FALSE;
#ifdef APCLI_SUPPORT
UCHAR apcliidx;
#endif
DBGPRINT(RT_DEBUG_TRACE, "---> ApStartUp\n");
for (apidx = 0; apidx < pAd->PortCfg.BssidNum; apidx++)
{
if ((pAd->PortCfg.MBSSID[apidx].SsidLen <= 0) || (pAd->PortCfg.MBSSID[apidx].SsidLen > MAX_LEN_OF_SSID))
return;
// when B-only mode, beacon will not report using short slot time
if (pAd->PortCfg.PhyMode == PHY_11B)
{
pAd->PortCfg.UseShortSlotTime = FALSE;
}
// Decide the Capability information field
// In IEEE Std 802.1h-2003, the spectrum management bit is enabled in the 5 GHz band
if (pAd->PortCfg.PhyMode == PHY_11A && pAd->PortCfg.RadarDetect.IEEE80211H == TRUE)
pAd->PortCfg.MBSSID[apidx].CapabilityInfo = CAP_GENERATE((pAd->PortCfg.MBSSID[apidx].WepStatus != Ndis802_11EncryptionDisabled), (pAd->PortCfg.TxPreamble == Rt802_11PreambleShort), pAd->PortCfg.UseShortSlotTime, TRUE);
else
pAd->PortCfg.MBSSID[apidx].CapabilityInfo = CAP_GENERATE((pAd->PortCfg.MBSSID[apidx].WepStatus != Ndis802_11EncryptionDisabled), (pAd->PortCfg.TxPreamble == Rt802_11PreambleShort), pAd->PortCfg.UseShortSlotTime, FALSE);
// if one bssid turn on the WMM, the parameter will set to ASIC once.
if (pAd->PortCfg.MBSSID[apidx].bWmmCapable)
bWmmCapable = TRUE;
DBGPRINT(RT_DEBUG_TRACE, "IF(ra%d) CapabilityInfo=%x, WepStatus=%d\n", apidx,
pAd->PortCfg.MBSSID[apidx].CapabilityInfo,pAd->PortCfg.MBSSID[apidx].WepStatus);
// if AuthMode >= WPA and IEEE802.1x is enabled, then pairwise key table must be used;
// if legacy WEP inused, then only shared key table is used
if ((pAd->PortCfg.MBSSID[apidx].AuthMode >= Ndis802_11AuthModeWPA) ||(pAd->PortCfg.MBSSID[apidx].IEEE8021X == TRUE))
{
sec_csr4 |= BIT32[apidx];
DBGPRINT(RT_DEBUG_TRACE, "IF(ra%d)-AP AuthMode=%d, IEEE802.1x is %d, Pairwise Key Table in-used\n", apidx,
pAd->PortCfg.MBSSID[apidx].AuthMode,
pAd->PortCfg.MBSSID[apidx].IEEE8021X);
}
else
{
DBGPRINT(RT_DEBUG_TRACE, "IF(ra%d)-AP AuthMode=%d, disable Pairwise Key Table\n", apidx, pAd->PortCfg.MBSSID[apidx].AuthMode);
}
RTMP_IO_WRITE32(pAd, SEC_CSR4, sec_csr4);
// remove group key table
for (i=0; i<SHARE_KEY_NUM; i++)
{
AsicRemoveSharedKeyEntry(pAd, apidx, i);
}
// remove pairwise key table
for (i=0; i<PAIRWISE_KEY_NO; i++)
{
AsicRemovePairwiseKeyEntry(pAd, i);
}
// Set shared key to ASIC :
// SHARED-WEP, Auto-WEP, OPEN-WEP(no matter 802.1x is enabled or disabled) need to set key
if ((pAd->PortCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeShared) ||
(((pAd->PortCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeAutoSwitch) || (pAd->PortCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeOpen)) && (pAd->PortCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption1Enabled)))
{
for (i=0; i<SHARE_KEY_NUM; i++)
{
if (pAd->PortCfg.MBSSID[apidx].SharedKey[i].KeyLen != 0)
{
AsicAddSharedKeyEntry(pAd, apidx, i, pAd->PortCfg.MBSSID[apidx].SharedKey[i].CipherAlg, pAd->PortCfg.MBSSID[apidx].SharedKey[i].Key, NULL, NULL);
}
}
}
// Add wds key to pairwise key table when TKIP/AES
if (((pAd->WdsTab.WepStatus == Ndis802_11Encryption2Enabled) || (pAd->WdsTab.WepStatus == Ndis802_11Encryption3Enabled)) && (pAd->WdsTab.Wpa_key.KeyLen > 0))
{
AsicAddPairwiseKeyEntry(pAd, pAd->WdsTab.WdsEntry[0].WdsAddr, WDS_PAIRWISE_KEY_OFFSET, pAd->WdsTab.Wpa_key.CipherAlg,
pAd->WdsTab.Wpa_key.Key, pAd->WdsTab.Wpa_key.TxMic, pAd->WdsTab.Wpa_key.RxMic);
AsicAddPairwiseKeyEntry(pAd, pAd->WdsTab.WdsEntry[1].WdsAddr, WDS_PAIRWISE_KEY_OFFSET + 1, pAd->WdsTab.Wpa_key.CipherAlg,
pAd->WdsTab.Wpa_key.Key, pAd->WdsTab.Wpa_key.TxMic, pAd->WdsTab.Wpa_key.RxMic);
AsicAddPairwiseKeyEntry(pAd, pAd->WdsTab.WdsEntry[2].WdsAddr, WDS_PAIRWISE_KEY_OFFSET + 2, pAd->WdsTab.Wpa_key.CipherAlg,
pAd->WdsTab.Wpa_key.Key, pAd->WdsTab.Wpa_key.TxMic, pAd->WdsTab.Wpa_key.RxMic);
AsicAddPairwiseKeyEntry(pAd, pAd->WdsTab.WdsEntry[3].WdsAddr, WDS_PAIRWISE_KEY_OFFSET + 3, pAd->WdsTab.Wpa_key.CipherAlg,
pAd->WdsTab.Wpa_key.Key, pAd->WdsTab.Wpa_key.TxMic, pAd->WdsTab.Wpa_key.RxMic);
}
// Send singal to daemon to indicate driver had restarted
if ((pAd->PortCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA) || (pAd->PortCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2)
|| (pAd->PortCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pAd->PortCfg.MBSSID[apidx].IEEE8021X == TRUE))
{
SendSingalToDaemon(pAd, SIGUSR1);
}
}
#ifdef WMM_SUPPORT
if (bWmmCapable)
{
// EDCA parameters used for AP's own transmission
if (pAd->PortCfg.APEdcaParm.bValid == FALSE)
{
pAd->PortCfg.APEdcaParm.bValid = TRUE;
pAd->PortCfg.APEdcaParm.Aifsn[0] = 3;
pAd->PortCfg.APEdcaParm.Aifsn[1] = 7;
pAd->PortCfg.APEdcaParm.Aifsn[2] = 1;
pAd->PortCfg.APEdcaParm.Aifsn[3] = 1;
pAd->PortCfg.APEdcaParm.Cwmin[0] = 4;
pAd->PortCfg.APEdcaParm.Cwmin[1] = 4;
pAd->PortCfg.APEdcaParm.Cwmin[2] = 3;
pAd->PortCfg.APEdcaParm.Cwmin[3] = 2;
pAd->PortCfg.APEdcaParm.Cwmax[0] = 10;
pAd->PortCfg.APEdcaParm.Cwmax[1] = 6;
pAd->PortCfg.APEdcaParm.Cwmax[2] = 4;
pAd->PortCfg.APEdcaParm.Cwmax[3] = 3;
pAd->PortCfg.APEdcaParm.Txop[0] = 0;
pAd->PortCfg.APEdcaParm.Txop[1] = 0;
pAd->PortCfg.APEdcaParm.Txop[2] = 94;
pAd->PortCfg.APEdcaParm.Txop[3] = 47;
}
AsicSetEdcaParm(pAd, &pAd->PortCfg.APEdcaParm);
// EDCA parameters to be annouced in outgoing BEACON, used by WMM STA
if (pAd->PortCfg.BssEdcaParm.bValid == FALSE)
{
pAd->PortCfg.BssEdcaParm.bValid = TRUE;
pAd->PortCfg.BssEdcaParm.Aifsn[0] = 3;
pAd->PortCfg.BssEdcaParm.Aifsn[1] = 7;
pAd->PortCfg.BssEdcaParm.Aifsn[2] = 2;
pAd->PortCfg.BssEdcaParm.Aifsn[3] = 2;
pAd->PortCfg.BssEdcaParm.Cwmin[0] = 4;
pAd->PortCfg.BssEdcaParm.Cwmin[1] = 4;
pAd->PortCfg.BssEdcaParm.Cwmin[2] = 3;
pAd->PortCfg.BssEdcaParm.Cwmin[3] = 2;
pAd->PortCfg.BssEdcaParm.Cwmax[0] = 10;
pAd->PortCfg.BssEdcaParm.Cwmax[1] = 10;
pAd->PortCfg.BssEdcaParm.Cwmax[2] = 4;
pAd->PortCfg.BssEdcaParm.Cwmax[3] = 3;
pAd->PortCfg.BssEdcaParm.Txop[0] = 0;
pAd->PortCfg.BssEdcaParm.Txop[1] = 0;
pAd->PortCfg.BssEdcaParm.Txop[2] = 94;
pAd->PortCfg.BssEdcaParm.Txop[3] = 47;
}
DBGPRINT(RT_DEBUG_TRACE,"STA : AIFSN CWmin CWmax TXOP(us) ACM\n");
DBGPRINT(RT_DEBUG_TRACE," AC_BE %d %d %d %4d %d\n",
pAd->PortCfg.BssEdcaParm.Aifsn[0], pAd->PortCfg.BssEdcaParm.Cwmin[0], pAd->PortCfg.BssEdcaParm.Cwmax[0],
pAd->PortCfg.BssEdcaParm.Txop[0]<<5, pAd->PortCfg.BssEdcaParm.bACM[0]);
DBGPRINT(RT_DEBUG_TRACE," AC_BK %d %d %d %4d %d\n",
pAd->PortCfg.BssEdcaParm.Aifsn[1], pAd->PortCfg.BssEdcaParm.Cwmin[1], pAd->PortCfg.BssEdcaParm.Cwmax[1],
pAd->PortCfg.BssEdcaParm.Txop[1]<<5, pAd->PortCfg.BssEdcaParm.bACM[1]);
DBGPRINT(RT_DEBUG_TRACE," AC_VI %d %d %d %4d %d\n",
pAd->PortCfg.BssEdcaParm.Aifsn[2], pAd->PortCfg.BssEdcaParm.Cwmin[2], pAd->PortCfg.BssEdcaParm.Cwmax[2],
pAd->PortCfg.BssEdcaParm.Txop[2]<<5, pAd->PortCfg.BssEdcaParm.bACM[2]);
DBGPRINT(RT_DEBUG_TRACE," AC_VO %d %d %d %4d %d\n",
pAd->PortCfg.BssEdcaParm.Aifsn[3], pAd->PortCfg.BssEdcaParm.Cwmin[3], pAd->PortCfg.BssEdcaParm.Cwmax[3],
pAd->PortCfg.BssEdcaParm.Txop[3]<<5, pAd->PortCfg.BssEdcaParm.bACM[3]);
}
#endif /* WMM_SUPPORT */
AsicSetBssid(pAd, pAd->CurrentAddress);
AsicSwitchChannel(pAd, pAd->PortCfg.Channel);
AsicLockChannel(pAd, pAd->PortCfg.Channel);
MlmeUpdateTxRates(pAd);
AsicSetSlotTime(pAd, (BOOLEAN)pAd->PortCfg.UseShortSlotTime);
// if (pAd->PortCfg.RadarDetect.IEEE80211H == TRUE)
{
RTMPPrepareRadarDetectParams(pAd);
}
RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0);
MakeAllBssBeacon(pAd);
UpdateAllBeaconFrame(pAd);
// This part needs to take care of following situation.
// 1. NO DFS, 2. DFS in silence mode, 3. DFS in normal mode 4. DFS in switching mode
if ((pAd->PortCfg.PhyMode == PHY_11A) && (pAd->PortCfg.RadarDetect.IEEE80211H == TRUE) && RadarChannelCheck(pAd, pAd->PortCfg.Channel) && (bDFSRestart == TRUE))
{
AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x00, 0x00); // send stop-RD command to MCU
RTMPusecDelay(500000);
pAd->PortCfg.RadarDetect.RDMode = RD_SILENCE_MODE;
pAd->PortCfg.RadarDetect.RDCount = 0;
pAd->PortCfg.RadarDetect.InServiceMonitorCount = 0;
RadarDetectionStart(pAd);
}
else if ((pAd->PortCfg.PhyMode == PHY_11A) && (pAd->PortCfg.RadarDetect.IEEE80211H == TRUE) && RadarChannelCheck(pAd, pAd->PortCfg.Channel))
{
}
else
{
AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x00, 0x00); // send stop-RD command to MCU
RTMPusecDelay(500000);
pAd->PortCfg.RadarDetect.RDMode = RD_NORMAL_MODE;
RadarDetectionStop(pAd);
AsicEnableBssSync(pAd);
}
// Set LED
RTMPSetLED(pAd, LED_RADIO_ON);
//delay to get H2M_MAILBOX ownership again before next RTMPSetLED().
mdelay(1000);
RTMPSetLED(pAd, LED_LINK_UP);
// Group rekey related
if ((pAd->PortCfg.WPAREKEY.ReKeyInterval != 0) && ((pAd->PortCfg.WPAREKEY.ReKeyMethod == TIME_REKEY) || (pAd->PortCfg.WPAREKEY.ReKeyMethod == PKT_REKEY)))
{
// Regularly check the timer
if (pAd->PortCfg.REKEYTimerRunning == FALSE)
{
RTMPAddTimer(&pAd->PortCfg.REKEYTimer, GUPDATE_EXEC_INTV);
pAd->PortCfg.REKEYTimerRunning = TRUE;
pAd->PortCfg.REKEYCOUNTER = 0;
}
}
else
pAd->PortCfg.REKEYTimerRunning = FALSE;
pAd->Mlme.PeriodicRound = 0;
ApLogEvent(pAd, pAd->CurrentAddress, EVENT_RESET_ACCESS_POINT, MAIN_MBSSID);
#ifdef APCLI_SUPPORT
for (apcliidx = 0; apcliidx < MAX_APCLI_ENTRY; apcliidx++)
{
// Pairwise or Shared key table lookup enable for ApCli interface
if (pAd->ApCliTab.ApCliEntry[apcliidx].Enable)
{
// remove group key table for ApCli IF
for (i = 0; i < SHARE_KEY_NUM; i++)
{
AsicRemoveSharedKeyEntry(pAd, pAd->PortCfg.BssidNum, i);
}
// When OPEN-WEP, Shared-WEP, Auto-WEP, open shared key table security
if (pAd->PortCfg.MBSSID[MAIN_MBSSID].WepStatus == Ndis802_11WEPEnabled)
{
for (i = 0; i < SHARE_KEY_NUM; i++)
{
if (pAd->PortCfg.MBSSID[MAIN_MBSSID].SharedKey[i].KeyLen != 0)
{
AsicAddSharedKeyEntry(pAd, pAd->PortCfg.BssidNum, i, pAd->PortCfg.MBSSID[MAIN_MBSSID].SharedKey[i].CipherAlg, pAd->PortCfg.MBSSID[MAIN_MBSSID].SharedKey[i].Key, NULL, NULL);
}
}
// Stop STA supplicant WPA state machine
pAd->ApCliTab.ApCliEntry[apcliidx].WpaState = SS_NOTUSE;
#ifdef RTL865X_SOC
printk("IF(apcli%d) AP-Client AuthMode=%d, Shared Key Table in-used\n", apcliidx, pAd->PortCfg.MBSSID[MAIN_MBSSID].AuthMode);
#else
DBGPRINT(RT_DEBUG_TRACE, "IF(apcli%d) AP-Client AuthMode=%d, Shared Key Table in-used\n", apcliidx, pAd->PortCfg.MBSSID[MAIN_MBSSID].AuthMode);
#endif
}
// When WPA, open pairwise key table security
else if (pAd->PortCfg.MBSSID[MAIN_MBSSID].AuthMode >= Ndis802_11AuthModeWPA)
{
sec_csr4 |= BIT32[pAd->PortCfg.BssidNum];
// Start STA supplicant WPA state machine
pAd->ApCliTab.ApCliEntry[apcliidx].WpaState = SS_START;
#ifdef RTL865X_SOC
printk("IF(apcli%d) AP-Client AuthMode=%d, Pairwise Key Table in-used\n", apcliidx, pAd->PortCfg.MBSSID[MAIN_MBSSID].AuthMode);
#else
DBGPRINT(RT_DEBUG_TRACE, "IF(apcli%d) AP-Client AuthMode=%d, Pairwise Key Table in-used\n", apcliidx, pAd->PortCfg.MBSSID[MAIN_MBSSID].AuthMode);
#endif
RTMP_IO_WRITE32(pAd, SEC_CSR4, sec_csr4);
}
else
{
// Stop STA supplicant WPA state machine
pAd->ApCliTab.ApCliEntry[apcliidx].WpaState = SS_NOTUSE;
#ifdef RTL865X_SOC
printk("IF(apcli%d) AP-Client AuthMode=%d, disable Pairwise or Shared Key Table\n", apcliidx, pAd->PortCfg.MBSSID[MAIN_MBSSID].AuthMode);
#else
DBGPRINT(RT_DEBUG_TRACE, "IF(apcli%d) AP-Client AuthMode=%d, disable Pairwise or Shared Key Table\n", apcliidx, pAd->PortCfg.MBSSID[MAIN_MBSSID].AuthMode);
#endif
}
}
// firstly, disassociate this connection,
// Then re-connect that previous AP.
if (pAd->ApCliTab.ApCliEntry[apcliidx].Enable && pAd->ApCliTab.ApCliEntry[apcliidx].Valid)
{
DBGPRINT(RT_DEBUG_TRACE, "Restart ApCli link - IF(apcli%d).\n", apcliidx);
StaMlmeEnqueue(pAd, STA_CTRL_STATE_MACHINE, STA_CTRL_DISCONNECT_REQ, 0, NULL, apcliidx);
}
}
#endif
DBGPRINT(RT_DEBUG_TRACE, "<--- ApStartUp (sec_csr4=0x%x)\n", sec_csr4);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -