📄 car6koid.cpp
字号:
/*
* The target combines association request and response
* into a single byte stream and notifies the same in
* connect_event. assocReqLen is the length in bytes of
* association request and assocRespLen is the length in
* bytes of association response. There is one glitch
* though. The association request that is passed by the
* target contains only the Variable IEs and the fixed
* IEs like listen Interval and AP address are passed
* as arguments to the connect_event. However the association
* response passed to the host contains the full 802.11
* frame as seen on the wire. That is, in essence the request
* and response parsing will not be symmetrical.
* One pending kludge to be fixed - WZC requires Capabilities
* IE for both request and response as it is not returned
* in requests, it is hardcoded as 0x3104
*/
NDIS_STATUS
CAR6KMini::Get802_11AssociationInformation(
OUT NDIS_802_11_ASSOCIATION_INFORMATION *pAssocInfo,
IN ULONG cbBuffer,
OUT ULONG *pcbNeeded)
{
PBYTE ptr;
if (m_AssocReqLen == 0 && m_AssocRespLen == 0) {
*pcbNeeded = 0;
return NDIS_STATUS_SUCCESS;
}
*pcbNeeded = m_AssocReqLen + m_AssocRespLen + sizeof(*pAssocInfo);
if (cbBuffer < *pcbNeeded) {
return NDIS_STATUS_INVALID_LENGTH;
}
memcpy(pAssocInfo->RequestFixedIEs.CurrentAPAddress,
m_PeerBSSID, ETHERNET_MAC_ADDRESS_LENGTH);
pAssocInfo->AvailableRequestFixedIEs =
NDIS_802_11_AI_REQFI_CAPABILITIES |
NDIS_802_11_AI_REQFI_LISTENINTERVAL |
NDIS_802_11_AI_REQFI_CURRENTAPADDRESS;
pAssocInfo->OffsetRequestIEs = sizeof(*pAssocInfo);
pAssocInfo->RequestIELength = m_AssocReqLen - 4;
ptr = m_pAssocInfo + m_BeaconIeLen;
pAssocInfo->RequestFixedIEs.Capabilities = ((*(ptr + 1)) << 8) | *ptr;
ptr += 2;
pAssocInfo->RequestFixedIEs.ListenInterval = ((*(ptr + 1)) << 8) | *ptr;
ptr += 2;
memcpy((PBYTE)pAssocInfo + pAssocInfo->OffsetRequestIEs, ptr,
pAssocInfo->RequestIELength);
pAssocInfo->AvailableResponseFixedIEs =
NDIS_802_11_AI_RESFI_CAPABILITIES |
NDIS_802_11_AI_RESFI_STATUSCODE |
NDIS_802_11_AI_RESFI_ASSOCIATIONID;
pAssocInfo->OffsetResponseIEs = sizeof(*pAssocInfo) +
pAssocInfo->RequestIELength;
#ifndef AR6K_FIRMWARE_1_0
pAssocInfo->ResponseIELength = m_AssocRespLen - 6;
ptr = m_pAssocInfo + m_BeaconIeLen + m_AssocReqLen;
#else
pAssocInfo->ResponseIELength = m_AssocRespLen -
(sizeof(struct ieee80211_frame) + 6);
ptr = m_pAssocInfo + m_AssocReqLen + sizeof(struct ieee80211_frame);
#endif
pAssocInfo->ResponseFixedIEs.Capabilities = ((*(ptr + 1)) << 8) | *ptr;
ptr += 2;
pAssocInfo->ResponseFixedIEs.StatusCode = ((*(ptr + 1)) << 8) | *ptr;
ptr += 2;
pAssocInfo->ResponseFixedIEs.AssociationId = ((*(ptr + 1)) << 8) | *ptr;
ptr += 2;
memcpy((PBYTE)pAssocInfo + pAssocInfo->OffsetResponseIEs, ptr,
pAssocInfo->ResponseIELength);
pAssocInfo->Length = sizeof(*pAssocInfo);
return NDIS_STATUS_SUCCESS;
}
#ifdef SUPPORT_WPA2
NDIS_STATUS
CAR6KMini::Get802_11PMKID(OUT NDIS_802_11_PMKID *pPMKID,
IN ULONG cbBuffer,
OUT ULONG *pcbNeeded)
{
unsigned int i = 0;
if (m_AuthenticationMode != Ndis802_11AuthModeWPA2) {
return NDIS_STATUS_INVALID_DATA;
}
if (m_pPMKID == NULL) {
return NDIS_STATUS_INVALID_DATA;
}
*pcbNeeded = m_pPMKID->Length;
if (cbBuffer < m_pPMKID->Length) {
return NDIS_STATUS_INVALID_LENGTH;
}
pPMKID->Length = m_pPMKID->Length;
pPMKID->BSSIDInfoCount = m_pPMKID->BSSIDInfoCount;
for (i=0; i<pPMKID->BSSIDInfoCount; i++) {
memcpy(pPMKID->BSSIDInfo[i].BSSID,
m_pPMKID->BSSIDInfo[i].BSSID, 6);
memcpy(pPMKID->BSSIDInfo[i].PMKID,
m_pPMKID->BSSIDInfo[i].PMKID, 16);
}
return NDIS_STATUS_SUCCESS;
}
NDIS_STATUS
CAR6KMini::Get802_11Capability(OUT NDIS_802_11_CAPABILITY *pCap,
IN ULONG cbBuffer,
OUT ULONG *pcbNeeded)
{
ULONG i = 0;
ULONG lenNeeded;
lenNeeded = sizeof(pCap->Version) + sizeof(pCap->NoOfPMKIDs) +
sizeof(pCap->NoOfAuthEncryptPairsSupported) + sizeof(pCap->Length) +
(10 * sizeof(NDIS_802_11_AUTHENTICATION_ENCRYPTION));
*pcbNeeded = lenNeeded;
if (cbBuffer < lenNeeded) {
return NDIS_STATUS_INVALID_LENGTH;
}
pCap->Version = 2;
pCap->NoOfPMKIDs = 3; //no of PMKIDs that can be cached, min of 3 and max of 16.
pCap->NoOfAuthEncryptPairsSupported = 10; //excluding WEP shared and WPA-None
pCap->Length = lenNeeded;
for (i = 0; i < 10; i++) {
pCap->AuthenticationEncryptionSupported[i].AuthModeSupported =
g_WPA2AuthEncryptPairSupported[i].AuthModeSupported;
pCap->AuthenticationEncryptionSupported[i].EncryptStatusSupported =
g_WPA2AuthEncryptPairSupported[i].EncryptStatusSupported;
}
return NDIS_STATUS_SUCCESS;
}
#endif //SUPPORT_WPA2
// AR6K 802.11 OID Set Handlers
NDIS_STATUS
CAR6KMini::Set802_11AssociatedAPBSSID(
IN NDIS_802_11_MAC_ADDRESS *BSSID)
{
memcpy(m_DesiredAPBSSID, BSSID, sizeof(NDIS_802_11_MAC_ADDRESS));
// Setting the desired BSSID results in the following actions:
// o If the device is associated with an AP that has the same BSSID, the device must reassociate with the AP
// o If the device is associated with a different AP, then it must dissasociate from it then associate with the desired AP.
// o If the device is not associated, then it must attempt to associate to the specified BSSID
//
// The desired BSSID is cleared by setting it to MAC address 0xFFFFFFFFFFFF. When set to that broadcast address,
// the device may associate with any AP that matches the desired SSID.
//
return NDIS_STATUS_SUCCESS;
}
bool
IsBroadcastAddress(
IN PBYTE pMACAddress)
//
// Return true if the MAC address is all 1's (i.e. FF FF FF FF FF FF)
//
{
bool IsBroadcast = true;
for (UINT i = 0; i < sizeof(NDIS_802_11_MAC_ADDRESS); i++)
{
if (pMACAddress[i] != 0xFF)
{
IsBroadcast = false;
break;
}
}
return IsBroadcast;
}
NDIS_STATUS
CAR6KMini::SendWMIConnectCommand(
IN NDIS_802_11_SSID *SSID)
//
// Request that the Wireless Module associate with the specified SSID.
//
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
A_STATUS wmiStatus;
NETWORK_TYPE wmiNetworkType = m_InfrastructureMode == Ndis802_11Infrastructure ? INFRA_NETWORK : ADHOC_NETWORK;
DOT11_AUTH_MODE wmiDot11AuthMode = OPEN_AUTH;
AUTH_MODE wmiAuthMode = NONE_AUTH;
BYTE *pAPBSSID;
CRYPTO_TYPE keyType = NONE_CRYPT;
BYTE KeyIndex = 0;
A_UINT16 channel = (m_InfrastructureMode == Ndis802_11IBSS) ? (A_UINT16)(m_Config.ibssChannel/1000) : 0;
//
// CONNECT commands can only be sent in the DISCONNECTED state.
//
ASSERT(false == m_Connected);
ASSERT(false == m_ConnectInProgress);
switch(m_AuthenticationMode)
{
case Ndis802_11AuthModeOpen:
wmiDot11AuthMode = OPEN_AUTH;
break;
case Ndis802_11AuthModeShared:
wmiDot11AuthMode = SHARED_AUTH;
break;
case Ndis802_11AuthModeWPA:
wmiAuthMode = WPA_AUTH;
break;
case Ndis802_11AuthModeWPAPSK:
wmiAuthMode = WPA_PSK_AUTH;
break;
case Ndis802_11AuthModeWPA2PSK:
wmiAuthMode = WPA2_PSK_AUTH;
break;
case Ndis802_11AuthModeWPA2:
wmiAuthMode = WPA2_AUTH;
break;
default:
break;
}
if (m_AuthAlg == 0x04) {
wmiDot11AuthMode = LEAP_AUTH;
}
switch (m_EncryptionStatus)
{
case Ndis802_11WEPEnabled:
m_PairwiseCryptoType = WEP_CRYPT;
m_GrpwiseCryptoType = WEP_CRYPT;
break;
case Ndis802_11WEPDisabled:
m_PairwiseCryptoType = NONE_CRYPT;
m_GrpwiseCryptoType = NONE_CRYPT;
break;
case Ndis802_11Encryption2Enabled:
m_PairwiseCryptoType = TKIP_CRYPT;
m_GrpwiseCryptoType = Encryption2GrpwiseCryptoTable[m_GrpwiseCryptoIndex];
m_GrpwiseCryptoIndex = (m_GrpwiseCryptoIndex++) % ENCRYPT2_GRPWISE_CRYPTOINDEX_MAX;
break;
case Ndis802_11Encryption3Enabled:
m_PairwiseCryptoType = AES_CRYPT;
m_GrpwiseCryptoType = Encryption3GrpwiseCryptoTable[m_GrpwiseCryptoIndex];
m_GrpwiseCryptoIndex = (m_GrpwiseCryptoIndex++) % ENCRYPT3_GRPWISE_CRYPTOINDEX_MAX;
break;
default:
break;
}
pAPBSSID = NULL;
if (!IsBroadcastAddress(m_DesiredAPBSSID))
pAPBSSID = m_DesiredAPBSSID;
NDIS_DEBUG_PRINTF(ATH_LOG_INF, "Connect command from Supplicant\n");
if (m_WMIBssFilter != ALL_BSS_FILTER) {
wmiStatus = wmi_bssfilter_cmd((struct wmi_t *)m_pWMI, ALL_BSS_FILTER);
if (wmiStatus == A_OK) {
m_WMIBssFilter = ALL_BSS_FILTER;
} else {
return NDIS_STATUS_FAILURE;
}
}
//Add the keys to the NIC, before issuing the connect cmd.
//Add the keys here only if the Auth mode is either SharedAuth or AutoSwitch. Only for
//Shared Auth the WEP keys are plumbed before the connection.
if (m_AuthenticationMode == Ndis802_11AuthModeShared ||
m_AuthenticationMode == Ndis802_11AuthModeAutoSwitch ) {
for (KeyIndex = 0; KeyIndex < 4 ; KeyIndex++ ) {
if ( m_cbKey[KeyIndex] != 0 ) {
if( (m_KeyUsage[KeyIndex] & GROUP_USAGE) == GROUP_USAGE )
{
keyType = m_GrpwiseCryptoType;
} else {
keyType = m_PairwiseCryptoType;
}
wmiStatus = wmi_addKey_cmd((wmi_t *)m_pWMI,
(A_UINT8)KeyIndex,
WEP_CRYPT, // Only for WEP the keys are added before connect
m_KeyUsage[KeyIndex],
(A_UINT8)m_cbKey[KeyIndex],
(A_UINT8*)&m_KeyRSC[KeyIndex],
m_Key[KeyIndex]);
if (wmiStatus != A_OK) {
NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - wmi_addKey_cmd failed = %u\n", wmiStatus);
return NDIS_STATUS_FAILURE;
}
}
}
}
/* Set the Listen Interval to 1000TUs. This value will be indicated to the
* AP in the conn. request. Later set it back locally at the STA to 100/1000 TUs depending on the
* power mode.
*/
//Increase the listen interval to 1000 TUs to ensure max buffering capacity at the AP.
wmiStatus = wmi_listeninterval_cmd((struct wmi_t *)m_pWMI,
MAX_LISTEN_INTERVAL, 0 );
if (wmiStatus != A_OK) {
NDIS_DEBUG_PRINTF(ATH_LOG_ERR,"AR6K: ERROR - wmi_listeninterval_cmd failed = %u\n", wmiStatus);
return NDIS_STATUS_FAILURE;
}
wmiStatus = wmi_connect_cmd((wmi_t *)m_pWMI, wmiNetworkType,
wmiDot11AuthMode, wmiAuthMode,
m_PairwiseCryptoType, 0,
m_GrpwiseCryptoType, 0,
m_SSID.SsidLength, m_SSID.Ssid,
pAPBSSID, channel);
if (wmiStatus != A_OK) {
NDIS_DEBUG_PRINTF(ATH_LOG_ERR,"AR6K: ERROR - wmi_connect_cmd failed = %u\n", wmiStatus);
Status = NDIS_STATUS_FAILURE;
} else {
m_ConnectInProgress = true;
}
return Status;
}
NDIS_STATUS
CAR6KMini::SendWMIDisconnectCommand()
//
// Request that the Wireless Module disassociate from the current wireless
// network. This request may be issued in any state. It will cancel an ongoing
// CONNECT command if one is in progress. A DISCONNECTED_EVENT will always be
// generated, even if the current state is DISCONNECTED.
//
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
A_STATUS wmiStatus;
wmiStatus = wmi_disconnect_cmd((wmi_t *)m_pWMI);
NDIS_DEBUG_PRINTF(ATH_LOG_INF, "Disconnect from supplicant\n");
if (wmiStatus != A_OK) {
NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - wmi_disconnect_cmd failed = %u\n", wmiStatus);
Status = NDIS_STATUS_FAILURE;
}
return Status;
}
NDIS_STATUS
CAR6KMini::Set802_11SSID(
IN NDIS_802_11_SSID *SSID)
//
// This request informs the driver of the SSID to associate to. If the first
// character of the SSID string is zero, then it can associate with any SSID.
// If the SSID is invalid (contains non printable ASCII characters), then the
// adapter should not associate with any SSID.
//
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
A_STATUS wmiStatus;
NDIS_802_11_SSID *lSSID;
if (!m_WMIReady) {
Status = NDIS_STATUS_ADAPTER_NOT_READY;
goto done;
}
if (m_RadioDisabled) {
m_RadioDisabled = FALSE;
configRegistryParameters();
configTargetParams();
wmiStatus = wmi_startscan_cmd((wmi_t *)m_pWMI,WMI_LONG_SCAN);
if (wmiStatus != A_OK)
NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - wmi_startscan_cmd failed = %u\n", wmiStatus);
}
if (SSID->SsidLength > 32)
{
// Bad length
Status = NDIS_STATUS_INVALID_DATA;
goto done;
}
// SSID may be NULL to connect to any available SSID
if (SSID->SsidLength == 0) {
ULONG dwSize = 2048;
ULONG NoOfItems,ssidLength;
ULONG *pcbNeeded=(ULONG *)malloc(sizeof(ULONG));
NDIS_802_11_BSSID_LIST_EX *pBSSIDListEx = (NDIS_802_11_BSSID_LIST_EX *)malloc(dwSize);
this->Get802_11BSSIDList(pBSSIDListEx,dwSize,pcbNeeded);
if(pBSSIDListEx) {
NoOfItems = pBSSIDListEx->NumberOfItems;
NDIS_WLAN_BSSID_EX *pBSSID = (NDIS_WLAN_BSSID_EX *) &pBSSIDListEx->Bssid[0];
while (NoOfItems) {
if (pBSSID->Privacy) {
pBSSID = (NDIS_WLAN_BSSID_EX *)((PBYTE)pBSSID + pBSSID->Length);
NoOfItems--;
} else {
ssidLength=pBSSID->Ssid.SsidLength;
if(ssidLength) {
lSSID=&pBSSID->Ssid;
m_AuthenticationMode=Ndis802_11AuthModeOpen;
m_EncryptionStatus=Ndis802_11WEPDisabled;
break;
} else {
pBSSID = (NDIS_WLAN_BSSID_EX *)((PBYTE)pBSSID + pBSSID->Length);
NoOfItems--;
}
}
}
free(pBSSIDListEx);
}
}
else {
lSSID=SSID;
}
m_WantToBeConnected = SSIDIsValid(SSID);
if (false == m_WantToBeConnected)
{
m_SSID = *lSSID;
// We want to abort any connection attempt in progress, and
// dissassociate from any SSID to which we are current associated.
if (m_ConnectInProgress || m_Connected)
{
Status = SendWMIDisconnectCommand();
}
}
else
{
// The set SSID maybe same as the one we are already connected or different.
// In any case we issue a disconnect if we are already connected. This is because
// there may be a change in the Conn. profile (such as encryption key) that warrants
// a disconnect & reconnect.
// We want to associate to the specified SSID
if (lSSID->SsidLength == m_SSID.SsidLength
&& 0 == memcmp(lSSID->Ssid, m_SSID.Ssid, m_SSID.SsidLength))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -