/* * mlmeParser.c * * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name Texas Instruments nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** \file mlmeBuilder.c * \brief 802.11 MLME Parser * * \see mlmeParser.h */ /***************************************************************************/ /* */ /* MODULE: mlmeParser.c */ /* PURPOSE: 802.11 MLME Parser */ /* */ /***************************************************************************/ #define __FILE_ID__ FILE_ID_68 #include "osApi.h" #include "paramOut.h" #include "report.h" #include "DataCtrl_Api.h" #include "smeApi.h" #include "mlmeApi.h" #include "mlmeSm.h" #include "AssocSM.h" #include "authSm.h" #include "mlmeParser.h" #include "measurementMgrApi.h" #include "ScanCncn.h" #include "siteMgrApi.h" #include "spectrumMngmntMgr.h" #include "currBss.h" #include "apConn.h" #include "SwitchChannelApi.h" #include "regulatoryDomainApi.h" #include "qosMngr_API.h" #include "scanResultTable.h" #include "RxBuf.h" /* Constants */ /* Enumerations */ /* Typedefs */ /* Structures */ /* External data definitions */ /* External functions definitions */ /* Local function prototypes */ /* Functions */ #define CHECK_PARSING_ERROR_CONDITION_PRINT 0 extern int WMEQosTagToACTable[MAX_NUM_OF_802_1d_TAGS]; TI_STATUS mlmeParser_recv(TI_HANDLE hMlme, void *pBuffer, TRxAttr* pRxAttr) { TI_STATUS status; mlme_t *pHandle = (mlme_t *)hMlme; TI_UINT8 *pData; TI_INT32 bodyDataLen; TI_UINT32 readLen; dot11_eleHdr_t *pEleHdr; dot11_mgmtFrame_t *pMgmtFrame; dot11MgmtSubType_e msgType; paramInfo_t *pParam; TMacAddr recvBssid; TMacAddr recvSa; TI_UINT8 rsnIeIdx = 0; TI_UINT8 wpaIeOuiIe[] = WPA_IE_OUI; #ifdef XCC_MODULE_INCLUDED TI_UINT8 XCC_oui[] = XCC_OUI; XCCv4IEs_t *pXCCIeParameter; #endif TI_BOOL ciscoIEPresent = TI_FALSE; if ((hMlme == NULL) || (pBuffer == NULL)) { WLAN_OS_REPORT (("mlmeParser_recv: hMlme == %x, buf = %x\n", hMlme, pBuffer)); return TI_NOK; } /* zero frame content */ os_memoryZero (pHandle->hOs, &(pHandle->tempFrameInfo), sizeof(mlmeIEParsingParams_t)); pMgmtFrame = (dot11_mgmtFrame_t*)RX_BUF_DATA(pBuffer); /* get frame type */ status = mlmeParser_getFrameType(pHandle, (TI_UINT16 *)&pMgmtFrame->hdr.fc, &msgType); if (status != TI_OK) { RxBufFree(pHandle->hOs, pBuffer); return TI_NOK; } pParam = (paramInfo_t *)os_memoryAlloc(pHandle->hOs, sizeof(paramInfo_t)); if (!pParam) { RxBufFree(pHandle->hOs, pBuffer); return TI_NOK; } pHandle->tempFrameInfo.frame.subType = msgType; /* We have to ignore management frames from other BSSIDs (except beacons & probe responses) */ pParam->paramType = CTRL_DATA_CURRENT_BSSID_PARAM; ctrlData_getParam(pHandle->hCtrlData, pParam); MAC_COPY (recvBssid, pMgmtFrame->hdr.BSSID); MAC_COPY(recvSa, pMgmtFrame->hdr.SA); if (MAC_EQUAL (pParam->content.ctrlDataCurrentBSSID, recvBssid)) pHandle->tempFrameInfo.myBssid = TI_TRUE; else pHandle->tempFrameInfo.myBssid = TI_FALSE; if (MAC_EQUAL (pParam->content.ctrlDataCurrentBSSID, recvSa)) pHandle->tempFrameInfo.mySa = TI_TRUE; else pHandle->tempFrameInfo.mySa = TI_FALSE; /* The Default value of the myDst flag is false, only in case of unicast packet with the STA's destination address, the flag is set to True */ pHandle->tempFrameInfo.myDst = TI_FALSE; /* check destination MAC address for broadcast */ if (MAC_BROADCAST (pMgmtFrame->hdr.DA)) { pHandle->tempFrameInfo.frame.extesion.destType = MSG_BROADCAST; } else { if (MAC_MULTICAST (pMgmtFrame->hdr.DA)) { pHandle->tempFrameInfo.frame.extesion.destType = MSG_MULTICAST; } else { pHandle->tempFrameInfo.frame.extesion.destType = MSG_UNICAST; pParam->paramType = CTRL_DATA_MAC_ADDRESS; ctrlData_getParam(pHandle->hCtrlData, pParam); /* Verifying whether the received unicast packet is for the STA, if yes we set the flag to True */ if (MAC_EQUAL( (pParam->content.ctrlDataDeviceMacAddress), (pMgmtFrame->hdr.DA) )) pHandle->tempFrameInfo.myDst = TI_TRUE; } } MAC_COPY (pHandle->tempFrameInfo.bssid, pMgmtFrame->hdr.BSSID); pData = (TI_UINT8 *)(pMgmtFrame->body); /* length of body (BUF without 802.11 header and FCS) */ bodyDataLen = RX_BUF_LEN(pBuffer) - WLAN_HDR_LEN; switch (msgType) { case ASSOC_REQUEST: TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "MLME_PARSER: recieved ASSOC_REQ message \n"); break; case RE_ASSOC_REQUEST: TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "MLME_PARSER: recieved RE_ASSOC_REQ message \n"); break; case RE_ASSOC_RESPONSE: TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "MLME_PARSER: recieved RE_ASSOC_RSP message \n"); /* break;*/ case ASSOC_RESPONSE: /* if the assoc response is not directed to our STA or not from the current AP */ if ((!pHandle->tempFrameInfo.myBssid) || (!pHandle->tempFrameInfo.mySa) || (pHandle->tempFrameInfo.myDst == TI_FALSE)) break; /* Save the association response message */ assoc_saveAssocRespMessage(pHandle->hAssoc, (TI_UINT8 *)(pMgmtFrame->body), bodyDataLen); /* init frame fields */ pHandle->tempFrameInfo.frame.content.assocRsp.barkerPreambleMode = PREAMBLE_UNSPECIFIED; /* read capabilities */ COPY_WLAN_WORD(&pHandle->tempFrameInfo.frame.content.assocRsp.capabilities , pData); pData += 2; /* read status */ COPY_WLAN_WORD(&pHandle->tempFrameInfo.frame.content.assocRsp.status , pData); pData += 2; /* read AID */ COPY_WLAN_WORD(&pHandle->tempFrameInfo.frame.content.assocRsp.aid , pData); pHandle->tempFrameInfo.frame.content.assocRsp.aid &= ASSOC_RESP_AID_MASK; pData += 2; bodyDataLen -= ASSOC_RESP_FIXED_DATA_LEN; /***************************/ pHandle->tempFrameInfo.frame.content.assocRsp.pRsnIe = NULL; pHandle->tempFrameInfo.frame.content.assocRsp.rsnIeLen = 0; while (bodyDataLen > 2) { pEleHdr = (dot11_eleHdr_t*)pData; if ((*pEleHdr)[1] > (bodyDataLen - 2)) { TRACE3(pHandle->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: IE %d with length %d out of bounds %d\n", (*pEleHdr)[0], (*pEleHdr)[1], (bodyDataLen - 2)); status = TI_NOK; goto mlme_recv_end; } switch ((*pEleHdr)[0]) { /* read rates */ case SUPPORTED_RATES_IE_ID: pHandle->tempFrameInfo.frame.content.assocRsp.pRates = &(pHandle->tempFrameInfo.rates); status = mlmeParser_readRates(pHandle, pData, bodyDataLen, &readLen, &(pHandle->tempFrameInfo.rates)); if (status != TI_OK) { TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: error reading RATES\n"); goto mlme_recv_end; } break; case EXT_SUPPORTED_RATES_IE_ID: /* read rates */ pHandle->tempFrameInfo.frame.content.assocRsp.pExtRates = &(pHandle->tempFrameInfo.extRates); status = mlmeParser_readRates(pHandle, pData, bodyDataLen, &readLen, &(pHandle->tempFrameInfo.extRates)); if (status != TI_OK) { TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: error reading RATES\n"); goto mlme_recv_end; } break; case WPA_IE_ID: /* Note : WPA, WME, TSRS and msdu lifetime use the same Element ID */ /* Its assumes that: TSRS and msdu lifetime use OUI = 0x00,0x40,0x96 (=Cisco) but use different OUI Type: TSRS uses OUI Type 8 msdu lifetime uses OUI Type 9; WPA and WME use the same OUI = 0x00,0x50,0xf2 but use different OUI Type: WPA - uses OUI Type with value - 1 WME - uses OUI Type with value - 2. */ /* check if this is WME IE */ if((os_memoryCompare(pHandle->hOs, wpaIeOuiIe, pData+2, DOT11_OUI_LEN - 1) == 0) && ((*(TI_UINT8*)(pData+5)) == dot11_WME_OUI_TYPE)) { pHandle->tempFrameInfo.frame.content.assocRsp.WMEParams = &(pHandle->tempFrameInfo.WMEParams); status = mlmeParser_readWMEParams(pHandle, pData, bodyDataLen, &readLen, &(pHandle->tempFrameInfo.WMEParams), &(pHandle->tempFrameInfo.frame.content.assocRsp)); if (status != TI_OK) { TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: error reading WME parameters\n"); goto mlme_recv_end; } } #ifdef XCC_MODULE_INCLUDED /* check if this is XCC vendor specific OUI */ else if (os_memoryCompare(pHandle->hOs, XCC_oui, pData+2, DOT11_OUI_LEN - 1) == 0) { pXCCIeParameter = &(pHandle->tempFrameInfo.frame.content.assocRsp.XCCIEs[WMEQosTagToACTable[*(pData+6)]]); mlmeParser_readXCCOui(pData, bodyDataLen, &readLen, pXCCIeParameter); } #endif else { /* skip this IE */ readLen = (*pEleHdr)[1] + 2; } break; case XCC_EXT_1_IE_ID: ciscoIEPresent = TI_TRUE; pHandle->tempFrameInfo.frame.content.assocRsp.pRsnIe = &(pHandle->tempFrameInfo.rsnIe[0]); status = mlmeParser_readRsnIe(pHandle, pData, bodyDataLen, &readLen, &(pHandle->tempFrameInfo.rsnIe[rsnIeIdx])); if (status != TI_OK) { TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: error reading XCC EXT1 IE\n"); goto mlme_recv_end; } pHandle->tempFrameInfo.frame.content.assocRsp.rsnIeLen += readLen; rsnIeIdx ++; break; case XCC_EXT_2_IE_ID: ciscoIEPresent = TI_TRUE; pHandle->tempFrameInfo.frame.content.assocRsp.pRsnIe = &(pHandle->tempFrameInfo.rsnIe[0]); status = mlmeParser_readRsnIe(pHandle, pData, bodyDataLen, &readLen, &(pHandle->tempFrameInfo.rsnIe[rsnIeIdx])); if (status != TI_OK) { TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: error reading RSN IP ADDR IE\n"); goto mlme_recv_end; } pHandle->tempFrameInfo.frame.content.assocRsp.rsnIeLen += readLen; rsnIeIdx ++; break; case DOT11_QOS_CAPABILITY_ELE_ID: pHandle->tempFrameInfo.frame.content.assocRsp.QoSCapParameters = &(pHandle->tempFrameInfo.QosCapParams); status = mlmeParser_readQosCapabilityIE(pHandle, pData, bodyDataLen, &readLen, &(pHandle->tempFrameInfo.QosCapParams)); if (status != TI_OK) { TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: error reading QOS\n"); goto mlme_recv_end; } break; case HT_CAPABILITIES_IE_ID: pHandle->tempFrameInfo.frame.content.assocRsp.pHtCapabilities = &(pHandle->tempFrameInfo.tHtCapabilities); status = mlmeParser_readHtCapabilitiesIE (pHandle, pData, bodyDataLen, &readLen, &(pHandle->tempFrameInfo.tHtCapabilities)); if (status != TI_OK) { TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: error reading HT Capabilities IE\n"); goto mlme_recv_end; } break; case HT_INFORMATION_IE_ID: pHandle->tempFrameInfo.frame.content.assocRsp.pHtInformation = &(pHandle->tempFrameInfo.tHtInformation); status = mlmeParser_readHtInformationIE (pHandle, pData, bodyDataLen, &readLen, &(pHandle->tempFrameInfo.tHtInformation)); if (status != TI_OK) { TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: error reading HT Information IE\n"); goto mlme_recv_end; } break; default: TRACE1(pHandle->hReport, REPORT_SEVERITY_INFORMATION, "MLME_PARSER: unsupported IE found (%d)\n", (*pEleHdr)[1]); readLen = (*pEleHdr)[1] + 2; status = TI_OK; break; } pData += readLen; bodyDataLen -= readLen; } /***************************/ /* set the appropriate flag in the association response frame */ /* to indicate whether or not we encountered a Cisco IE, i.e., */ /* if we have any indication as to whether the AP we've associated */ /* with is a Cisco AP. */ pHandle->tempFrameInfo.frame.content.assocRsp.ciscoIEPresent = ciscoIEPresent; TRACE1(pHandle->hReport, REPORT_SEVERITY_INFORMATION, "MLME_PARSER: ciscoIEPresent = %d\n", ciscoIEPresent); status = assoc_recv(pHandle->hAssoc, &(pHandle->tempFrameInfo.frame)); break; case PROBE_REQUEST: TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "MLME_PARSER: recieved PROBE_REQ message \n"); break; case PROBE_RESPONSE: TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "MLME_PARSER: recieved PROBE_RESPONSE message \n"); if(RX_BUF_LEN(pBuffer)-WLAN_HDR_LEN-TIME_STAMP_LEN-4 > MAX_BEACON_BODY_LENGTH) { TRACE3(pHandle->hReport, REPORT_SEVERITY_ERROR, "mlmeParser_recv: probe response length out of range. length=%d, band=%d, channel=%d\n", RX_BUF_LEN(pBuffer)-WLAN_HDR_LEN-TIME_STAMP_LEN-4, pRxAttr->band, pRxAttr->channel); if ((pRxAttr->eScanTag > SCAN_RESULT_TAG_CURENT_BSS) && (pRxAttr->eScanTag != SCAN_RESULT_TAG_MEASUREMENT)) { /* Notify the result CB of an invalid frame (to update the result counter) */ scanCncn_MlmeResultCB( pHandle->hScanCncn, NULL, NULL, pRxAttr, NULL, 0); } status = TI_NOK; goto mlme_recv_end; } /* init frame fields */ pHandle->tempFrameInfo.frame.content.iePacket.barkerPreambleMode = PREAMBLE_UNSPECIFIED; /* read time stamp */ os_memoryCopy(pHandle->hOs, (void *)pHandle->tempFrameInfo.frame.content.iePacket.timestamp, pData, TIME_STAMP_LEN); pData += TIME_STAMP_LEN; bodyDataLen -= TIME_STAMP_LEN; /* read beacon interval */ COPY_WLAN_WORD(&pHandle->tempFrameInfo.frame.content.iePacket.beaconInerval , pData); pData += 2; /* read capabilities */ COPY_WLAN_WORD(&pHandle->tempFrameInfo.frame.content.iePacket.capabilities , pData); pData += 2; bodyDataLen -= 4; pHandle->tempFrameInfo.frame.content.iePacket.pRsnIe = NULL; pHandle->tempFrameInfo.frame.content.iePacket.rsnIeLen = 0; pHandle->tempFrameInfo.band = pRxAttr->band; pHandle->tempFrameInfo.rxChannel = pRxAttr->channel; if ((pRxAttr->band == RADIO_BAND_2_4_GHZ) && (pRxAttr->channel > NUM_OF_CHANNELS_24)) { TRACE2(pHandle->hReport, REPORT_SEVERITY_ERROR, "mlmeParser_recv, band=%d, channel=%d\n", pRxAttr->band, pRxAttr->channel); /* Error in parsing Probe response packet - exit */ if ((pRxAttr->eScanTag > SCAN_RESULT_TAG_CURENT_BSS) && (pRxAttr->eScanTag != SCAN_RESULT_TAG_MEASUREMENT)) { /* Notify the result CB of an invalid frame (to update the result counter) */ scanCncn_MlmeResultCB( pHandle->hScanCncn, NULL, NULL, pRxAttr, NULL, 0); } status = TI_NOK; goto mlme_recv_end; } else if ((pRxAttr->band == RADIO_BAND_5_0_GHZ) && (pRxAttr->channel <= NUM_OF_CHANNELS_24)) { TRACE2(pHandle->hReport, REPORT_SEVERITY_ERROR, "mlmeParser_recv, band=%d, channel=%d\n", pRxAttr->band, pRxAttr->channel); /* Error in parsing Probe response packet - exit */ if ((pRxAttr->eScanTag > SCAN_RESULT_TAG_CURENT_BSS) && (pRxAttr->eScanTag != SCAN_RESULT_TAG_MEASUREMENT)) { /* Notify the result CB of an invalid frame (to update the result counter) */ scanCncn_MlmeResultCB( pHandle->hScanCncn, NULL, NULL, pRxAttr, NULL, 0); } status = TI_NOK; goto mlme_recv_end; } if (mlmeParser_parseIEs(hMlme, pData, bodyDataLen, &(pHandle->tempFrameInfo)) != TI_OK) { TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, "mlmeParser_recv: Error in parsing Probe response packet\n"); /* Error in parsing Probe response packet - exit */ if ((pRxAttr->eScanTag > SCAN_RESULT_TAG_CURENT_BSS) && (pRxAttr->eScanTag != SCAN_RESULT_TAG_MEASUREMENT)) { /* Notify the result CB of an invalid frame (to update the result counter) */ scanCncn_MlmeResultCB( pHandle->hScanCncn, NULL, NULL, pRxAttr, NULL, 0); } status = TI_NOK; goto mlme_recv_end; } /* updating CountryIE */ if ((pHandle->tempFrameInfo.frame.content.iePacket.country != NULL) && (pHandle->tempFrameInfo.frame.content.iePacket.country->hdr[1] != 0)) { /* set the country info in the regulatory domain - If a different code was detected earlier the regDomain will ignore it */ pParam->paramType = REGULATORY_DOMAIN_COUNTRY_PARAM; pParam->content.pCountry = (TCountry *)pHandle->tempFrameInfo.frame.content.iePacket.country; regulatoryDomain_setParam (pHandle->hRegulatoryDomain, pParam); } /* if tag = MSR, forward to the MSR module. */ if (SCAN_RESULT_TAG_MEASUREMENT == pRxAttr->eScanTag) { measurementMgr_mlmeResultCB( pHandle->hMeasurementMgr, &(pHandle->tempFrameInfo.bssid), &(pHandle->tempFrameInfo.frame), pRxAttr, (TI_UINT8 *)(pMgmtFrame->body+TIME_STAMP_LEN+4), RX_BUF_LEN(pBuffer)-WLAN_HDR_LEN-TIME_STAMP_LEN-4 ); } /* only forward frames from the current BSS (according to the tag) to current BSS */ else if (SCAN_RESULT_TAG_CURENT_BSS == pRxAttr->eScanTag) { currBSS_probRespReceivedCallb(pHandle->hCurrBss, pRxAttr, &(pHandle->tempFrameInfo.bssid), &(pHandle->tempFrameInfo.frame), (TI_UINT8 *)(pMgmtFrame->body+TIME_STAMP_LEN+4), RX_BUF_LEN(pBuffer)-WLAN_HDR_LEN-TIME_STAMP_LEN-4); } /* Check if there is a scan in progress, and this is a scan or measurement result (according to tag) */ else /* (SCAN_RESULT_TAG_CURENT_BSS!= pRxAttr->eScanTag) & (SCAN_RESULT_TAG_MEASUREMENT != pRxAttr->eScanTag) */ { /* result CB is registered - results are sent to the registered callback */ scanCncn_MlmeResultCB( pHandle->hScanCncn, &(pHandle->tempFrameInfo.bssid), &(pHandle->tempFrameInfo.frame), pRxAttr, (TI_UINT8 *)(pMgmtFrame->body+TIME_STAMP_LEN+4), RX_BUF_LEN(pBuffer)-WLAN_HDR_LEN-TIME_STAMP_LEN-4 ); } if(pHandle->tempFrameInfo.recvChannelSwitchAnnoncIE == TI_FALSE) { switchChannel_recvCmd(pHandle->hSwitchChannel, NULL, pRxAttr->channel); } break; case BEACON: TRACE1(pHandle->hReport, REPORT_SEVERITY_INFORMATION, "MLME_PARSER: recieved BEACON message, TS= %ld\n", os_timeStampMs(pHandle->hOs)); TRACE0(pHandle->hReport, REPORT_SEVERITY_INFORMATION, "beacon BUF"); if(RX_BUF_LEN(pBuffer)-WLAN_HDR_LEN-TIME_STAMP_LEN-4 > MAX_BEACON_BODY_LENGTH) { TRACE3(pHandle->hReport, REPORT_SEVERITY_ERROR, "mlmeParser_recv: beacon length out of range. length=%d, band=%d, channel=%d\n", RX_BUF_LEN(pBuffer)-WLAN_HDR_LEN-TIME_STAMP_LEN-4, pRxAttr->band, pRxAttr->channel); if ((pRxAttr->eScanTag > SCAN_RESULT_TAG_CURENT_BSS) && (pRxAttr->eScanTag != SCAN_RESULT_TAG_MEASUREMENT)) { /* Notify the result CB of an invalid frame (to update the result counter) */ scanCncn_MlmeResultCB( pHandle->hScanCncn, NULL, NULL, pRxAttr, NULL, 0); } status = TI_NOK; goto mlme_recv_end; } /* init frame fields */ pHandle->tempFrameInfo.frame.content.iePacket.barkerPreambleMode = PREAMBLE_UNSPECIFIED; /* read time stamp */ os_memoryCopy(pHandle->hOs, (void *)pHandle->tempFrameInfo.frame.content.iePacket.timestamp, pData, TIME_STAMP_LEN); pData += TIME_STAMP_LEN; bodyDataLen -= TIME_STAMP_LEN; /* read beacon interval */ COPY_WLAN_WORD(&pHandle->tempFrameInfo.frame.content.iePacket.beaconInerval , pData); pData += 2; /* read capabilities */ COPY_WLAN_WORD(&pHandle->tempFrameInfo.frame.content.iePacket.capabilities , pData); pData += 2; bodyDataLen -= 4; pHandle->tempFrameInfo.frame.content.iePacket.pRsnIe = NULL; pHandle->tempFrameInfo.frame.content.iePacket.rsnIeLen = 0; if ((pRxAttr->band == RADIO_BAND_2_4_GHZ) && (pRxAttr->channel > NUM_OF_CHANNELS_24)) { TRACE2(pHandle->hReport, REPORT_SEVERITY_ERROR, "mlmeParser_recv, band=%d, channel=%d\n", pRxAttr->band, pRxAttr->channel); /* Error in parsing Probe response packet - exit */ if ((pRxAttr->eScanTag > SCAN_RESULT_TAG_CURENT_BSS) && (pRxAttr->eScanTag != SCAN_RESULT_TAG_MEASUREMENT)) { /* Notify the result CB of an invalid frame (to update the result counter) */ scanCncn_MlmeResultCB( pHandle->hScanCncn, NULL, NULL, pRxAttr, NULL, 0); } status = TI_NOK; goto mlme_recv_end; } else if ((pRxAttr->band == RADIO_BAND_5_0_GHZ) && (pRxAttr->channel <= NUM_OF_CHANNELS_24)) { TRACE2(pHandle->hReport, REPORT_SEVERITY_ERROR, "mlmeParser_recv, band=%d, channel=%d\n", pRxAttr->band, pRxAttr->channel); /* Error in parsing Probe response packet - exit */ if ((pRxAttr->eScanTag > SCAN_RESULT_TAG_CURENT_BSS) && (pRxAttr->eScanTag != SCAN_RESULT_TAG_MEASUREMENT)) { /* Notify the result CB of an invalid frame (to update the result counter) */ scanCncn_MlmeResultCB( pHandle->hScanCncn, NULL, NULL, pRxAttr, NULL, 0); } status = TI_NOK; goto mlme_recv_end; } pHandle->tempFrameInfo.band = pRxAttr->band; pHandle->tempFrameInfo.rxChannel = pRxAttr->channel; if (mlmeParser_parseIEs(hMlme, pData, bodyDataLen, &(pHandle->tempFrameInfo)) != TI_OK) { TRACE0(pHandle->hReport, REPORT_SEVERITY_WARNING, "mlmeParser_parseIEs - Error in parsing Beacon \n"); /* Error in parsing Probe response packet - exit */ if ((pRxAttr->eScanTag > SCAN_RESULT_TAG_CURENT_BSS) && (pRxAttr->eScanTag != SCAN_RESULT_TAG_MEASUREMENT)) { /* Notify the result CB of an invalid frame (to update the result counter) */ scanCncn_MlmeResultCB( pHandle->hScanCncn, NULL, NULL, pRxAttr, NULL, 0); } status = TI_NOK; goto mlme_recv_end; } /* updating CountryIE */ if ((pHandle->tempFrameInfo.frame.content.iePacket.country != NULL) && (pHandle->tempFrameInfo.frame.content.iePacket.country->hdr[1] != 0)) { /* set the country info in the regulatory domain - If a different code was detected earlier the regDomain will ignore it */ pParam->paramType = REGULATORY_DOMAIN_COUNTRY_PARAM; pParam->content.pCountry = (TCountry *)pHandle->tempFrameInfo.frame.content.iePacket.country; regulatoryDomain_setParam (pHandle->hRegulatoryDomain, pParam); } /* if tag = MSR, forward to the MSR module. */ if (SCAN_RESULT_TAG_MEASUREMENT == pRxAttr->eScanTag) { measurementMgr_mlmeResultCB( pHandle->hMeasurementMgr, &(pHandle->tempFrameInfo.bssid), &(pHandle->tempFrameInfo.frame), pRxAttr, (TI_UINT8 *)(pMgmtFrame->body+TIME_STAMP_LEN+4), RX_BUF_LEN(pBuffer)-WLAN_HDR_LEN-TIME_STAMP_LEN-4 ); } /* only forward frames from the current BSS (according to the tag) to current BSS */ else if (SCAN_RESULT_TAG_CURENT_BSS == pRxAttr->eScanTag) { currBSS_beaconReceivedCallb(pHandle->hCurrBss, pRxAttr, &(pHandle->tempFrameInfo.bssid), &(pHandle->tempFrameInfo.frame), (TI_UINT8 *)(pMgmtFrame->body+TIME_STAMP_LEN+4), RX_BUF_LEN(pBuffer)-WLAN_HDR_LEN-TIME_STAMP_LEN-4); } /* Check if there is a scan in progress, and this is a scan or measurement result (according to tag) */ else /* (SCAN_RESULT_TAG_CURENT_BSS!= pRxAttr->eScanTag) & (SCAN_RESULT_TAG_MEASUREMENT != pRxAttr->eScanTag) */ { /* result CB is registered - results are sent to the registered callback */ scanCncn_MlmeResultCB( pHandle->hScanCncn, &(pHandle->tempFrameInfo.bssid), &(pHandle->tempFrameInfo.frame), pRxAttr, (TI_UINT8 *)(pMgmtFrame->body+TIME_STAMP_LEN+4), RX_BUF_LEN(pBuffer)-WLAN_HDR_LEN-TIME_STAMP_LEN-4 ); } /* Counting the number of recieved beacons - used for statistics */ pHandle->BeaconsCounterPS++; if (pHandle->tempFrameInfo.recvChannelSwitchAnnoncIE == TI_FALSE) { switchChannel_recvCmd(pHandle->hSwitchChannel, NULL, pRxAttr->channel); } break; case ATIM: if (!pHandle->tempFrameInfo.myBssid) break; TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "MLME_PARSER: recieved ATIM message \n"); break; case DIS_ASSOC: if ((!pHandle->tempFrameInfo.myBssid) || (!pHandle->tempFrameInfo.mySa)) break; /* read Reason interval */ COPY_WLAN_WORD(&pHandle->tempFrameInfo.frame.content.disAssoc.reason , pData); { /* Send roaming trigger */ roamingEventData_u RoamingEventData; RoamingEventData.APDisconnect.uStatusCode = pHandle->tempFrameInfo.frame.content.disAssoc.reason; RoamingEventData.APDisconnect.bDeAuthenticate = TI_FALSE; /* i.e. This is not DeAuth packet */ apConn_reportRoamingEvent(pHandle->hApConn, ROAMING_TRIGGER_AP_DISCONNECT, &RoamingEventData); } break; case AUTH: /* Auth response frame is should be directed to our STA, and from the current AP */ if ( (!pHandle->tempFrameInfo.myBssid) || (!pHandle->tempFrameInfo.mySa) || (pHandle->tempFrameInfo.myDst == TI_FALSE) ) break; /* read Algorithm interval */ COPY_WLAN_WORD(&pHandle->tempFrameInfo.frame.content.auth.authAlgo , pData); pData += 2; /* read Sequence number */ COPY_WLAN_WORD(&pHandle->tempFrameInfo.frame.content.auth.seqNum , pData); pData += 2; /* read status */ COPY_WLAN_WORD(&pHandle->tempFrameInfo.frame.content.auth.status , pData); pData += 2; TRACE3(pHandle->hReport, REPORT_SEVERITY_INFORMATION, "MLME_PARSER: Read Auth: algo=%d, seq=%d, status=%d\n", pHandle->tempFrameInfo.frame.content.auth.authAlgo, pHandle->tempFrameInfo.frame.content.auth.seqNum, pHandle->tempFrameInfo.frame.content.auth.status); bodyDataLen -= 6; /* read Challenge */ pHandle->tempFrameInfo.frame.content.auth.pChallenge = &(pHandle->tempFrameInfo.challenge); status = mlmeParser_readChallange(pHandle, pData, bodyDataLen, &readLen, &(pHandle->tempFrameInfo.challenge)); if (status != TI_OK) { pHandle->tempFrameInfo.challenge.hdr[1] = 0; readLen = 0; } pData += readLen; status = auth_recv(pHandle->hAuth, &(pHandle->tempFrameInfo.frame)); break; case DE_AUTH: if ((!pHandle->tempFrameInfo.myBssid) || (!pHandle->tempFrameInfo.mySa)) break; /* consider the Assoc frame if it is one of the following: 1) unicast frame and directed to our STA 2) broadcast frame */ if( (pHandle->tempFrameInfo.frame.extesion.destType == MSG_UNICAST) && (pHandle->tempFrameInfo.myDst == TI_FALSE) ) break; /* read Reason */ COPY_WLAN_WORD(&pHandle->tempFrameInfo.frame.content.deAuth.reason , pData); { /* Send roaming trigger */ roamingEventData_u RoamingEventData; RoamingEventData.APDisconnect.uStatusCode = pHandle->tempFrameInfo.frame.content.disAssoc.reason; RoamingEventData.APDisconnect.bDeAuthenticate = TI_TRUE; /* i.e. This is DeAuth packet */ apConn_reportRoamingEvent(pHandle->hApConn, ROAMING_TRIGGER_AP_DISCONNECT, &RoamingEventData); } break; case ACTION: pParam->paramType = CTRL_DATA_CURRENT_BSS_TYPE_PARAM; ctrlData_getParam(pHandle->hCtrlData, pParam); if ((!pHandle->tempFrameInfo.myBssid) || ((!pHandle->tempFrameInfo.mySa) && (pParam->content.ctrlDataCurrentBssType == BSS_INFRASTRUCTURE))) break; /* if the action frame is unicast and not directed to our STA, we should ignore it */ if( (pHandle->tempFrameInfo.frame.extesion.destType == MSG_UNICAST) && (pHandle->tempFrameInfo.myDst == TI_FALSE) ) break; /* read Category field */ pHandle->tempFrameInfo.frame.content.action.category = *pData; pData ++; bodyDataLen --; /* Checking if the category field is valid */ if(( pHandle->tempFrameInfo.frame.content.action.category != CATAGORY_SPECTRUM_MANAGEMENT) && (pHandle->tempFrameInfo.frame.content.action.category != CATAGORY_QOS) && (pHandle->tempFrameInfo.frame.content.action.category != WME_CATAGORY_QOS) ) { TRACE1(pHandle->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: Error category is invalid for action management frame %d \n", pHandle->tempFrameInfo.frame.content.action.category ); break; } switch(pHandle->tempFrameInfo.frame.content.action.category) { case CATAGORY_QOS: case WME_CATAGORY_QOS: /* read action field */ pHandle->tempFrameInfo.frame.content.action.action = *pData; pData ++; bodyDataLen --; QosMngr_receiveActionFrames(pHandle->hQosMngr, pData, pHandle->tempFrameInfo.frame.content.action.action, bodyDataLen); break; case CATAGORY_SPECTRUM_MANAGEMENT: /* read action field */ pHandle->tempFrameInfo.frame.content.action.action = *pData; pData ++; bodyDataLen --; switch(pHandle->tempFrameInfo.frame.content.action.action) { case MEASUREMENT_REQUEST: /* Checking the frame type */ if(pHandle->tempFrameInfo.frame.extesion.destType == MSG_BROADCAST) pHandle->tempFrameInfo.frame.content.action.frameType = MSR_FRAME_TYPE_BROADCAST; else pHandle->tempFrameInfo.frame.content.action.frameType = MSR_FRAME_TYPE_UNICAST; /*measurementMgr_receiveFrameRequest(pHandle->hMeasurementMgr, pHandle->tempFrameInfo.frame.content.action.frameType, bodyDataLen,pData);*/ break; case TPC_REQUEST: /*measurementMgr_receiveTPCRequest(pHandle->hMeasurementMgr,(TI_UINT8)bodyDataLen,pData);*/ break; case CHANNEL_SWITCH_ANNOUNCEMENT: if (pHandle->tempFrameInfo.myBssid) { /* Ignore Switch Channel commands from non my BSSID */ mlmeParser_readChannelSwitch(pHandle,pData,bodyDataLen,&readLen,&(pHandle->tempFrameInfo.channelSwitch), pRxAttr->channel); } break; default: TRACE1(pHandle->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: Error, category is invalid for action management frame %d \n", pHandle->tempFrameInfo.frame.content.action.category ); break; } break; default: status = TI_NOK; break; } } mlme_recv_end: /* release BUF */ os_memoryFree(pHandle->hOs, pParam, sizeof(paramInfo_t)); RxBufFree(pHandle->hOs, pBuffer); if (status != TI_OK) return TI_NOK; return status; } TI_STATUS mlmeParser_getFrameType(mlme_t *pMlme, TI_UINT16* pFrameCtrl, dot11MgmtSubType_e *pType) { TI_UINT16 fc; COPY_WLAN_WORD(&fc, pFrameCtrl); /* copy with endianess handling. */ if ((fc & DOT11_FC_PROT_VERSION_MASK) != DOT11_FC_PROT_VERSION) { TRACE1(pMlme->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: Error Wrong protocol version (not %d) \n", DOT11_FC_PROT_VERSION); return TI_NOK; } if ((fc & DOT11_FC_TYPE_MASK) != DOT11_FC_TYPE_MGMT) { TRACE0(pMlme->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: Error not MANAGEMENT frame\n"); return TI_NOK; } *pType = (dot11MgmtSubType_e)((fc & DOT11_FC_SUB_MASK) >> 4); return TI_OK; } #ifdef XCC_MODULE_INCLUDED void mlmeParser_readXCCOui (TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, XCCv4IEs_t *XCCIEs) { TI_UINT8 ieLen; TI_UINT8 ouiType; ieLen = *(pData+1) + 2; if (dataLen < ieLen) { /* Wrong length of info-element, skip to the end of the packet */ *pReadLen = dataLen; return; } *pReadLen = ieLen; ouiType = *(pData+5); switch (ouiType) { case TS_METRIX_OUI_TYPE: XCCIEs->tsMetrixParameter = (dot11_TS_METRICS_IE_t *)pData; break; case TS_RATE_SET_OUI_TYPE: XCCIEs->trafficStreamParameter = (dot11_TSRS_IE_t *)pData; break; case EDCA_LIFETIME_OUI_TYPE: XCCIEs->edcaLifetimeParameter = (dot11_MSDU_LIFE_TIME_IE_t *)pData; break; } return; } #endif TI_STATUS mlmeParser_readERP(mlme_t *pMlme, TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, TI_BOOL *useProtection, EPreamble *barkerPreambleMode) { TI_UINT32 erpIElen; TI_UINT16 ctrl; erpIElen = *(pData+1); *pReadLen = erpIElen + 2; if (dataLen < (TI_UINT32)(erpIElen + 2)) { return TI_NOK; } COPY_WLAN_WORD(&ctrl , pData + 2); *useProtection = (ctrl & 0x2) >>1; *barkerPreambleMode = ((ctrl & 0x4) >>2) ? PREAMBLE_LONG : PREAMBLE_SHORT; return TI_OK; } TI_STATUS mlmeParser_readRates(mlme_t *pMlme, TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_RATES_t *pRates) { pRates->hdr[0] = *pData; pRates->hdr[1] = *(pData+1); *pReadLen = pRates->hdr[1] + 2; if (dataLen < (TI_UINT32)(pRates->hdr[1] + 2)) { return TI_NOK; } if (pRates->hdr[1] > DOT11_MAX_SUPPORTED_RATES) { return TI_NOK; } os_memoryCopy(pMlme->hOs, (void *)pRates->rates, pData+2, pRates->hdr[1]); return TI_OK; } TI_STATUS mlmeParser_readSsid(mlme_t *pMlme, TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_SSID_t *pSsid) { pSsid->hdr[0] = *pData; pSsid->hdr[1] = *(pData+1); *pReadLen = pSsid->hdr[1] + 2; if ((dataLen < 2) || (dataLen < (TI_UINT32)(pSsid->hdr[1] + 2))) { return TI_NOK; } if (pSsid->hdr[1] > MAX_SSID_LEN) { return TI_NOK; } os_memoryCopy(pMlme->hOs, (void *)pSsid->serviceSetId, pData+2, pSsid->hdr[1]); return TI_OK; } TI_STATUS mlmeParser_readFhParams(mlme_t *pMlme, TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_FH_PARAMS_t *pFhParams) { pFhParams->hdr[0] = *pData; pFhParams->hdr[1] = *(pData+1); pData += 2; if ((dataLen < 2) || (dataLen < (TI_UINT32)(pFhParams->hdr[1] + 2))) { return TI_NOK; } COPY_WLAN_WORD(&pFhParams->dwellTime , pData); pData += 2; pFhParams->hopSet = *pData; pFhParams->hopPattern = *(pData+1); pFhParams->hopIndex = *(pData+2); *pReadLen = pFhParams->hdr[1] + 2; return TI_OK; } TI_STATUS mlmeParser_readDsParams(mlme_t *pMlme, TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_DS_PARAMS_t *pDsParams) { pDsParams->hdr[0] = *pData; pDsParams->hdr[1] = *(pData+1); if ((dataLen < 2) || (dataLen < (TI_UINT32)(pDsParams->hdr[1] + 2))) { return TI_NOK; } pDsParams->currChannel = *(pData+2); *pReadLen = pDsParams->hdr[1] + 2; return TI_OK; } TI_STATUS mlmeParser_readCfParams(mlme_t *pMlme, TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_CF_PARAMS_t *pCfParams) { pCfParams->hdr[0] = *pData; pCfParams->hdr[1] = *(pData+1); pData += 2; if ((dataLen < 2) || (dataLen < (TI_UINT32)(pCfParams->hdr[1] + 2))) { return TI_NOK; } pCfParams->cfpCount = *pData; pCfParams->cfpPeriod = *(pData+1); pData += 2; COPY_WLAN_WORD(&pCfParams->cfpMaxDuration, pData); pData += 2; COPY_WLAN_WORD(&pCfParams->cfpDurRemain, pData); *pReadLen = pCfParams->hdr[1] + 2; return TI_OK; } TI_STATUS mlmeParser_readIbssParams(mlme_t *pMlme, TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_IBSS_PARAMS_t *pIbssParams) { pIbssParams->hdr[0] = *pData; pIbssParams->hdr[1] = *(pData+1); pData += 2; if ((dataLen < 2) || (dataLen < (TI_UINT32)(pIbssParams->hdr[1] + 2))) { return TI_NOK; } COPY_WLAN_WORD(&pIbssParams->atimWindow, pData); *pReadLen = pIbssParams->hdr[1] + 2; return TI_OK; } TI_STATUS mlmeParser_readTim(mlme_t *pMlme, TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_TIM_t *pTim) { pTim->hdr[0] = *pData; pTim->hdr[1] = *(pData+1); if ((dataLen < 2) || (dataLen < (TI_UINT32)(pTim->hdr[1] + 2)) || (pTim->hdr[1] < 3)) { return TI_NOK; } pTim->dtimCount = *(pData + 2); pTim->dtimPeriod = *(pData + 3); pTim->bmapControl = *(pData + 4); os_memoryCopy(pMlme->hOs, (void *)pTim->partialVirtualBmap, pData + 5, pTim->hdr[1] - 3); *pReadLen = pTim->hdr[1] + 2; return TI_OK; } TI_STATUS mlmeParser_readCountry(mlme_t *pMlme,TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_COUNTRY_t *countryIE) { TI_INT32 i, j; countryIE->hdr[0] = *pData; countryIE->hdr[1] = *(pData+1); *pReadLen = countryIE->hdr[1] + 2; if ((dataLen < 8) || (dataLen < (TI_UINT32)(countryIE->hdr[1] + 2))) { return TI_NOK; } if (countryIE->hdr[1] > DOT11_COUNTRY_ELE_LEN_MAX) { TRACE2(pMlme->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: country IE error: eleLen=%d, maxLen=%d\n", countryIE->hdr[1], DOT11_COUNTRY_ELE_LEN_MAX); return TI_NOK; } os_memoryCopy(pMlme->hOs,&(countryIE->countryIE.CountryString), pData+2, DOT11_COUNTRY_STRING_LEN); /* Loop on all tripletChannels. Each item has three fields ('i' counts rows and 'j' counts bytes). */ for (i = 0, j = 0; j < (countryIE->hdr[1] - DOT11_COUNTRY_STRING_LEN); i++, j+=3) { countryIE->countryIE.tripletChannels[i].firstChannelNumber = *(pData + j + 5); countryIE->countryIE.tripletChannels[i].numberOfChannels = *(pData + j + 6); countryIE->countryIE.tripletChannels[i].maxTxPowerLevel = *(pData + j + 7); } return TI_OK; } TI_STATUS mlmeParser_readWMEParams(mlme_t *pMlme,TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_WME_PARAM_t *pWMEParamIE, assocRsp_t *assocRsp) { TI_UINT8 ieSubtype; TI_UINT8 ac; /* Note: This function actually reads either the WME-Params IE or the WME-Info IE! */ pWMEParamIE->hdr[0] = *pData; pWMEParamIE->hdr[1] = *(pData+1); *pReadLen = pWMEParamIE->hdr[1] + 2; if (dataLen < *pReadLen) { TRACE2(pMlme->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: WME Parameter: eleLen=%d is too long (%d)\n", *pReadLen, dataLen); *pReadLen = dataLen; return TI_NOK; } if ((pWMEParamIE->hdr[1]> WME_TSPEC_IE_LEN) || (pWMEParamIE->hdr[1]< DOT11_WME_ELE_LEN)) { TRACE1(pMlme->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: WME Parameter IE error: eleLen=%d\n", pWMEParamIE->hdr[1]); return TI_NOK; } ieSubtype = *((TI_UINT8*)(pData+6)); switch (ieSubtype) { case dot11_WME_OUI_SUB_TYPE_IE: case dot11_WME_OUI_SUB_TYPE_PARAMS_IE: /* Checking WME Version validity */ if (*((TI_UINT8*)(pData+7)) != dot11_WME_VERSION ) { TRACE1(pMlme->hReport, REPORT_SEVERITY_INFORMATION, "MLME_PARSER: WME Parameter IE error: Version =%d is unsupported\n", *((TI_UINT8*)(pData+7)) ); return TI_NOK; } /* * Copy either the WME-Params IE or the WME-Info IE (Info is a subset of Params)! * * Note that the WME_ACParameteres part is copied separately for two reasons: * 1) It exists only in the WME-Params IE. * 2) There is a gap of 2 bytes before the WME_ACParameteres if OS_PACKED is not supported. */ os_memoryCopy(pMlme->hOs,&(pWMEParamIE->OUI), pData+2, 8); if ( *((TI_UINT8*)(pData+6)) == dot11_WME_OUI_SUB_TYPE_PARAMS_IE ) { os_memoryCopy(pMlme->hOs,&(pWMEParamIE->WME_ACParameteres), pData+10, pWMEParamIE->hdr[1] - 8); } break; case WME_TSPEC_IE_OUI_SUB_TYPE: /* Read renegotiated TSPEC parameters */ if (assocRsp == NULL) { TRACE0(pMlme->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: WME Parameter IE error: TSPEC Sub Type in beacon or probe resp\n"); return TI_NOK; } ac = WMEQosTagToACTable [ GET_USER_PRIORITY_FROM_WME_TSPEC_IE(pData) ]; if (ac == QOS_AC_VO) { assocRsp->tspecVoiceParameters = pData; } else if (ac == QOS_AC_VI) { assocRsp->tspecSignalParameters = pData; } break; default: /* Checking OUI Sub Type validity */ TRACE1(pMlme->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: WME Parameter IE error: Sub Type =%d is invalid\n", ieSubtype); return TI_NOK; } return TI_OK; } static TI_UINT32 mlmeParser_getWSCReadLen(TI_UINT8 *pData) { return *(pData+1) + 2; } static TI_STATUS mlmeParser_readWSCParams(mlme_t *pMlme,TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_WSC_t *pWSC_IE) { pWSC_IE->hdr[0] = *pData; pWSC_IE->hdr[1] = *(pData+1); *pReadLen = pWSC_IE->hdr[1] + 2; /* Length Sanity check of the WSC IE */ if ((dataLen < 8) || (dataLen < (TI_UINT32)(pWSC_IE->hdr[1] + 2))) { TRACE2(pMlme->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: WSC Parameter IE error: dataLen=%d, pWSC_IE->hdr[1]=%d\n", dataLen, pWSC_IE->hdr[1]); return TI_NOK; } /* Length Sanity check of the WSC IE */ if (pWSC_IE->hdr[1] > ( sizeof(dot11_WSC_t) - sizeof(dot11_eleHdr_t) )) { TRACE2(pMlme->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: WSC Parameter IE error: eleLen=%d, maxLen=%d\n", pWSC_IE->hdr[1], ( sizeof(dot11_WSC_t) - sizeof(dot11_eleHdr_t) )); return TI_NOK; } /* Copy the WSC Params IE */ os_memoryCopy(pMlme->hOs,&(pWSC_IE->OUI), pData+2, pWSC_IE->hdr[1]); return TI_OK; } TI_STATUS mlmeParser_readQosCapabilityIE(mlme_t *pMlme,TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_QOS_CAPABILITY_IE_t *QosCapParams) { QosCapParams->hdr[0] = *pData; QosCapParams->hdr[1] = *(pData+1); *pReadLen = QosCapParams->hdr[1] + 2; if (dataLen < (TI_UINT32)(QosCapParams->hdr[1] + 2)) { return TI_NOK; } if (QosCapParams->hdr[1] > DOT11_QOS_CAPABILITY_ELE_LEN) { TRACE2(pMlme->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: QOS Capability IE error: eleLen=%d, maxLen=%d\n", QosCapParams->hdr[1], DOT11_QOS_CAPABILITY_ELE_LEN); return TI_NOK; } QosCapParams->QosInfoField = (*(pData+1)); return TI_OK; } TI_STATUS mlmeParser_readHtCapabilitiesIE(mlme_t *pMlme,TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, Tdot11HtCapabilitiesUnparse *pHtCapabilities) { pHtCapabilities->tHdr[0] = *pData; pHtCapabilities->tHdr[1] = *(pData+1); *pReadLen = pHtCapabilities->tHdr[1] + 2; if (dataLen < (TI_UINT32)(pHtCapabilities->tHdr[1] + 2)) { return TI_NOK; } if (pHtCapabilities->tHdr[1] != DOT11_HT_CAPABILITIES_ELE_LEN) { TRACE2(pMlme->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: HT Capability IE error: eleLen=%d, expectedLen=%d\n", pHtCapabilities->tHdr[1], DOT11_HT_CAPABILITIES_ELE_LEN); return TI_NOK; } os_memoryCopy(pMlme->hOs, (void*)pHtCapabilities->aHtCapabilitiesIe, pData + 2, pHtCapabilities->tHdr[1]); return TI_OK; } TI_STATUS mlmeParser_readHtInformationIE(mlme_t *pMlme,TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, Tdot11HtInformationUnparse *pHtInformation) { pHtInformation->tHdr[0] = *pData; pHtInformation->tHdr[1] = *(pData+1); *pReadLen = pHtInformation->tHdr[1] + 2; if (dataLen < (TI_UINT32)(pHtInformation->tHdr[1] + 2)) { return TI_NOK; } if (pHtInformation->tHdr[1] < DOT11_HT_INFORMATION_ELE_LEN) { TRACE2(pMlme->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: HT Information IE error: eleLen=%d, minimum Len=%d\n", pHtInformation->tHdr[1], DOT11_HT_INFORMATION_ELE_LEN); return TI_NOK; } os_memoryCopy(pMlme->hOs, (void*)pHtInformation->aHtInformationIe, pData + 2, pHtInformation->tHdr[1]); return TI_OK; } TI_STATUS mlmeParser_readChallange(mlme_t *pMlme, TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_CHALLENGE_t *pChallange) { if (dataLen < 2) { return TI_NOK; } pChallange->hdr[0] = *pData; pChallange->hdr[1] = *(pData+1); pData += 2; if ((dataLen < 2) || (dataLen < (TI_UINT32)(pChallange->hdr[1] + 2))) { return TI_NOK; } if (pChallange->hdr[1] > DOT11_CHALLENGE_TEXT_MAX) { return TI_NOK; } os_memoryCopy(pMlme->hOs, (void *)pChallange->text, pData, pChallange->hdr[1]); *pReadLen = pChallange->hdr[1] + 2; return TI_OK; } TI_STATUS mlmeParser_readRsnIe(mlme_t *pMlme, TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_RSN_t *pRsnIe) { pRsnIe->hdr[0] = *pData; pRsnIe->hdr[1] = *(pData+1); pData += 2; if ((dataLen < 2) || (dataLen < (TI_UINT32)(pRsnIe->hdr[1] + 2))) { return TI_NOK; } os_memoryCopy(pMlme->hOs, (void *)pRsnIe->rsnIeData, pData, pRsnIe->hdr[1]); *pReadLen = pRsnIe->hdr[1] + 2; return TI_OK; } TI_STATUS mlmeParser_readPowerConstraint(mlme_t *pMlme,TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_POWER_CONSTRAINT_t *powerConstraintIE) { powerConstraintIE->hdr[0] = *pData; powerConstraintIE->hdr[1] = *(pData+1); *pReadLen = powerConstraintIE->hdr[1] + 2; if ((dataLen < 2) || (dataLen < (TI_UINT32)(powerConstraintIE->hdr[1] + 2))) { return TI_NOK; } if (powerConstraintIE->hdr[1] > DOT11_POWER_CONSTRAINT_ELE_LEN) { return TI_NOK; } os_memoryCopy(pMlme->hOs,(void *)&(powerConstraintIE->powerConstraint), pData+2, powerConstraintIE->hdr[1]); return TI_OK; } TI_STATUS mlmeParser_readChannelSwitch(mlme_t *pMlme,TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_CHANNEL_SWITCH_t *channelSwitch, TI_UINT8 channel) { channelSwitch->hdr[0] = *pData++; channelSwitch->hdr[1] = *pData++; *pReadLen = channelSwitch->hdr[1] + 2; if ((dataLen < 2) || (dataLen < (TI_UINT32)(channelSwitch->hdr[1] + 2))) { return TI_NOK; } if (channelSwitch->hdr[1] > DOT11_CHANNEL_SWITCH_ELE_LEN) { return TI_NOK; } channelSwitch->channelSwitchMode = *pData++; channelSwitch->channelNumber = *pData++; channelSwitch->channelSwitchCount = *pData; switchChannel_recvCmd(pMlme->hSwitchChannel, channelSwitch, channel); return TI_OK; } TI_STATUS mlmeParser_readQuiet(mlme_t *pMlme,TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_QUIET_t *quiet) { quiet->hdr[0] = *pData++; quiet->hdr[1] = *pData++; *pReadLen = quiet->hdr[1] + 2; if ((dataLen < 2) || (dataLen < (TI_UINT32)(quiet->hdr[1] + 2))) { return TI_NOK; } if (quiet->hdr[1] > DOT11_QUIET_ELE_LEN) { return TI_NOK; } quiet->quietCount = *pData++; quiet->quietPeriod = *pData++; quiet->quietDuration = *((TI_UINT16*)pData); pData += sizeof(TI_UINT16); quiet->quietOffset = *((TI_UINT16*)pData); return TI_OK; } TI_STATUS mlmeParser_readTPCReport(mlme_t *pMlme,TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_TPC_REPORT_t *TPCReport) { TPCReport->hdr[0] = *pData; TPCReport->hdr[1] = *(pData+1); *pReadLen = TPCReport->hdr[1] + 2; if ((dataLen < 2) || (dataLen < (TI_UINT32)(TPCReport->hdr[1] + 2))) { return TI_NOK; } if (TPCReport->hdr[1] > DOT11_TPC_REPORT_ELE_LEN) { return TI_NOK; } TPCReport->transmitPower = *(pData+2); return TI_OK; } #ifdef XCC_MODULE_INCLUDED TI_STATUS mlmeParser_readCellTP(mlme_t *pMlme, TI_UINT8 *pData, TI_UINT32 dataLen, TI_UINT32 *pReadLen, dot11_CELL_TP_t *cellTP) { TI_UINT8 XCC_OUI[] = XCC_OUI; cellTP->hdr[0] = *pData++; cellTP->hdr[1] = *pData++; *pReadLen = cellTP->hdr[1] + 2; if ((dataLen < 2) || (dataLen < (TI_UINT32)(cellTP->hdr[1] + 2))) { return TI_NOK; } if (cellTP->hdr[1] > DOT11_CELL_TP_ELE_LEN) { return TI_NOK; } os_memoryCopy(pMlme->hOs, (void*)cellTP->oui, pData, cellTP->hdr[1]); if (os_memoryCompare(pMlme->hOs, (void*)cellTP->oui, XCC_OUI, 3) != 0) { return TI_NOK; } return TI_OK; } #endif #if CHECK_PARSING_ERROR_CONDITION_PRINT #define CHECK_PARSING_ERROR_CONDITION(x, msg, bDump) \ if ((x)) \ { \ TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, msg); \ if (bDump) {\ TRACE1(pHandle->hReport, REPORT_SEVERITY_ERROR, "Buff len = %d \n", packetLength); \ report_PrintDump (pPacketBody, packetLength); }\ return TI_NOK; \ } #else #define CHECK_PARSING_ERROR_CONDITION(x, msg, bDump) \ if ((x)) return TI_NOK; #endif TI_STATUS mlmeParser_parseIEs(TI_HANDLE hMlme, TI_UINT8 *pData, TI_INT32 bodyDataLen, mlmeIEParsingParams_t *params) { dot11_eleHdr_t *pEleHdr; TI_UINT32 readLen; TI_STATUS status = TI_NOK; TI_UINT8 rsnIeIdx = 0; TI_UINT8 wpaIeOuiIe[4] = { 0x00, 0x50, 0xf2, 0x01}; beacon_probeRsp_t *frame = &(params->frame.content.iePacket); mlme_t *pHandle = (mlme_t *)hMlme; #ifdef XCC_MODULE_INCLUDED TI_BOOL allowCellTP = TI_TRUE; #endif #if CHECK_PARSING_ERROR_CONDITION_PRINT TI_INT32 packetLength = bodyDataLen; TI_UINT8 *pPacketBody = pData; #endif params->recvChannelSwitchAnnoncIE = TI_FALSE; while (bodyDataLen > 1) { pEleHdr = (dot11_eleHdr_t *)pData; #if CHECK_PARSING_ERROR_CONDITION_PRINT /* CHECK_PARSING_ERROR_CONDITION(((*pEleHdr)[1] > (bodyDataLen - 2)), ("MLME_PARSER: IE %d with length %d out of bounds %d\n", (*pEleHdr)[0], (*pEleHdr)[1], (bodyDataLen - 2)), TI_TRUE); */ if ((*pEleHdr)[1] > (bodyDataLen - 2)) { TRACE3(pHandle->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: IE %d with length %d out of bounds %d\n", (*pEleHdr)[0], (*pEleHdr)[1], (bodyDataLen - 2)); TRACE1(pHandle->hReport, REPORT_SEVERITY_ERROR, "Buff len = %d \n", packetLength); report_PrintDump (pPacketBody, packetLength); } #endif switch ((*pEleHdr)[0]) { /* read SSID */ case SSID_IE_ID: frame->pSsid = ¶ms->ssid; status = mlmeParser_readSsid(pHandle, pData, bodyDataLen, &readLen, frame->pSsid); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading SSID\n"),TI_TRUE); break; /* read rates */ case SUPPORTED_RATES_IE_ID: frame->pRates = ¶ms->rates; status = mlmeParser_readRates(pHandle, pData, bodyDataLen, &readLen, frame->pRates); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading RATES\n"),TI_TRUE); break; case EXT_SUPPORTED_RATES_IE_ID: frame->pExtRates = ¶ms->extRates; status = mlmeParser_readRates(pHandle, pData, bodyDataLen, &readLen, frame->pExtRates); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading EXT RATES\n"),TI_TRUE); break; case ERP_IE_ID: status = mlmeParser_readERP(pHandle, pData, bodyDataLen, &readLen, (TI_BOOL *)&frame->useProtection, (EPreamble *)&frame->barkerPreambleMode); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading ERP\n"),TI_TRUE); break; /* read FH parameter set */ case FH_PARAMETER_SET_IE_ID: frame->pFHParamsSet = ¶ms->fhParams; status = mlmeParser_readFhParams(pHandle, pData, bodyDataLen, &readLen, frame->pFHParamsSet); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading FH parameters\n"),TI_TRUE); break; /* read DS parameter set */ case DS_PARAMETER_SET_IE_ID: frame->pDSParamsSet = ¶ms->dsParams; status = mlmeParser_readDsParams(pHandle, pData, bodyDataLen, &readLen, frame->pDSParamsSet); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading DS parameters\n"),TI_TRUE); if (RADIO_BAND_2_4_GHZ == params->band ) { if (frame->pDSParamsSet->currChannel != params->rxChannel) { TRACE2(pHandle->hReport, REPORT_SEVERITY_ERROR, "Channel ERROR - incompatible channel source information: Frame=%d Vs Radio=%d.\nparser ABORTED!!!\n", frame->pDSParamsSet->currChannel , params->rxChannel); return TI_NOK; } } break; /* read CF parameter set */ case CF_PARAMETER_SET_IE_ID: frame->pCFParamsSet = ¶ms->cfParams; status = mlmeParser_readCfParams(pHandle, pData, bodyDataLen, &readLen, frame->pCFParamsSet); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading CF parameters\n"),TI_TRUE); break; /* read IBSS parameter set */ case IBSS_PARAMETER_SET_IE_ID: frame->pIBSSParamsSet = ¶ms->ibssParams; status = mlmeParser_readIbssParams(pHandle, pData, bodyDataLen, &readLen, frame->pIBSSParamsSet); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading IBSS parameters\n"),TI_TRUE); break; /* read TIM */ case TIM_IE_ID: frame->pTIM = ¶ms->tim; status = mlmeParser_readTim(pHandle, pData, bodyDataLen, &readLen, frame->pTIM); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading TIM\n"),TI_TRUE); break; /* read Country */ case COUNTRY_IE_ID: frame->country = ¶ms->country; status = mlmeParser_readCountry(pHandle, pData, bodyDataLen, &readLen, frame->country); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading country parameters\n"),TI_TRUE); break; /* read Power Constraint */ case POWER_CONSTRAINT_IE_ID: #ifdef XCC_MODULE_INCLUDED allowCellTP = TI_FALSE; #endif frame->powerConstraint = ¶ms->powerConstraint; status = mlmeParser_readPowerConstraint(pHandle, pData, bodyDataLen, &readLen, frame->powerConstraint); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading Power Constraint parameters\n"),TI_TRUE); break; /* read Channel Switch Mode */ case CHANNEL_SWITCH_ANNOUNCEMENT_IE_ID: frame->channelSwitch = ¶ms->channelSwitch; if (params->myBssid) { /* Ignore Switch Channel commands from non my BSSID */ params->recvChannelSwitchAnnoncIE = TI_TRUE; status = mlmeParser_readChannelSwitch(pHandle, pData, bodyDataLen, &readLen, frame->channelSwitch, params->rxChannel); if (status != TI_OK) { /* * PATCH for working with AP-DK 4.0.51 that use IE 37 (with length 20) for RSNE * Ignore the IE instead of rejecting the whole BUF (beacon or probe response) */ TRACE0(pHandle->hReport, REPORT_SEVERITY_WARNING, "MLME_PARSER: error reading Channel Switch announcement parameters - ignore IE\n"); } } break; /* read Quiet IE */ case QUIET_IE_ID: frame->quiet = ¶ms->quiet; status = mlmeParser_readQuiet(pHandle, pData, bodyDataLen, &readLen, frame->quiet); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading Quiet parameters\n"),TI_TRUE); break; /* read TPC report IE */ case TPC_REPORT_IE_ID: frame->TPCReport = ¶ms->TPCReport; status = mlmeParser_readTPCReport(pHandle, pData, bodyDataLen, &readLen, frame->TPCReport); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading TPC report parameters\n"),TI_TRUE); break; case XCC_EXT_1_IE_ID: frame->pRsnIe = ¶ms->rsnIe[0]; status = mlmeParser_readRsnIe(pHandle, pData, bodyDataLen, &readLen, ¶ms->rsnIe[rsnIeIdx]); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading RSN IE\n"),TI_TRUE); frame->rsnIeLen += readLen; rsnIeIdx ++; break; case RSN_IE_ID: frame->pRsnIe = ¶ms->rsnIe[0]; status = mlmeParser_readRsnIe(pHandle, pData, bodyDataLen, &readLen, ¶ms->rsnIe[rsnIeIdx]); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading RSN IE\n"),TI_TRUE); frame->rsnIeLen += readLen; rsnIeIdx ++; break; case DOT11_QOS_CAPABILITY_ELE_ID: frame->QoSCapParameters = ¶ms->QosCapParams; status = mlmeParser_readQosCapabilityIE(pHandle, pData, bodyDataLen, &readLen, ¶ms->QosCapParams); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading QOS CapabilityIE\n"),TI_TRUE); break; case HT_CAPABILITIES_IE_ID: frame->pHtCapabilities = ¶ms->tHtCapabilities; status = mlmeParser_readHtCapabilitiesIE(pHandle, pData, bodyDataLen, &readLen, ¶ms->tHtCapabilities); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading HT Capabilitys IE\n"),TI_TRUE); break; case HT_INFORMATION_IE_ID: frame->pHtInformation = ¶ms->tHtInformation; status = mlmeParser_readHtInformationIE(pHandle, pData, bodyDataLen, &readLen, ¶ms->tHtInformation); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading HT Information IE\n"),TI_TRUE); break; case WPA_IE_ID: if (!os_memoryCompare(pHandle->hOs, pData+2, wpaIeOuiIe, 3)) { /* Note : WSC, WPA and WME use the same OUI */ /* Its assumes that: WPA uses OUI Type with value - 1 WME uses OUI Type with value - 2 WSC uses OUI Type with value - 4 */ /* Check the OUI sub Type to verify whether this is a WSC IE, WME IE or WPA IE*/ if( (*(TI_UINT8*)(pData+5)) == dot11_WPA_OUI_TYPE) { /* If we are here - the following is WPA IE */ frame->pRsnIe = ¶ms->rsnIe[0]; status = mlmeParser_readRsnIe(pHandle, pData, bodyDataLen, &readLen, ¶ms->rsnIe[rsnIeIdx]); frame->rsnIeLen += readLen; rsnIeIdx ++; CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading RSN IE\n"),TI_TRUE); } if( ( (*(TI_UINT8*)(pData+5)) == dot11_WME_OUI_TYPE ) && ( ( (*(TI_UINT8*)(pData+6)) == dot11_WME_OUI_SUB_TYPE_PARAMS_IE) || ( (*(TI_UINT8*)(pData+6)) == dot11_WME_OUI_SUB_TYPE_IE) ) ) { /* If we are here - the following is WME-Params IE, WME-Info IE or TSPEC IE. */ /* Note that we are using the WMEParams struct also to hold the WME-Info IE which is a subset of WMEParams, and only one of them is sent in a frame. */ frame->WMEParams = ¶ms->WMEParams; status = mlmeParser_readWMEParams(pHandle, pData, bodyDataLen, &readLen, frame->WMEParams, NULL); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading WME params\n"),TI_TRUE); } if( ( (*(TI_UINT8*)(pData+5)) == dot11_WSC_OUI_TYPE )) { /* If we are here - the following is WSC IE */ readLen = mlmeParser_getWSCReadLen (pData); /* * This IE is not supposed to be found in beacons accroding to the standard * definition. However, some APs do add it to beacons. It is read from beacons * accroding to a registry key (which is false by default). Even if it is not * read, the readLen must be set for the pointer to advance, which is done * above. */ if ((BEACON != params->frame.subType) || (TI_TRUE == pHandle->bParseBeaconWSC)) { frame->WSCParams = ¶ms->WSCParams; status = mlmeParser_readWSCParams(pHandle, pData, bodyDataLen, &readLen, frame->WSCParams); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading WSC params\n"),TI_TRUE); } } else { /* Unrecognized OUI type */ readLen = (*pEleHdr)[1] + 2; } } else { readLen = (*pEleHdr)[1] + 2; } break; #ifdef XCC_MODULE_INCLUDED case CELL_POWER_IE: /* We mustn't take the Cell Transmit Power IE into account if */ /* there's a Power Constraint IE. Since the IEs must be in increasing */ /* order, it's enough to perform the check here, because if the Power */ /* Constraint IE is present it must have already been processed. */ if (allowCellTP) { frame->cellTP = ¶ms->cellTP; status = mlmeParser_readCellTP(pHandle, pData, bodyDataLen, &readLen, frame->cellTP); CHECK_PARSING_ERROR_CONDITION((status != TI_OK), ("MLME_PARSER: error reading Cell Transmit Power params.\n"),TI_TRUE); } break; #endif default: TRACE1(pHandle->hReport, REPORT_SEVERITY_INFORMATION, "MLME_PARSER: unknown IE found (%d)\n", pData[0]); readLen = pData[1] + 2; status = TI_OK; os_memoryCopy( pHandle->hOs, ¶ms->unknownIe[params->frame.content.iePacket.unknownIeLen], pData, readLen ); params->frame.content.iePacket.pUnknownIe = params->unknownIe; params->frame.content.iePacket.unknownIeLen += readLen; break; } pData += readLen; bodyDataLen -= readLen; #if CHECK_PARSING_ERROR_CONDITION_PRINT /* CHECK_PARSING_ERROR_CONDITION((bodyDataLen < 0), ("MLME_PARSER: negative bodyDataLen %d bytes\n", bodyDataLen),TI_TRUE); */ if (bodyDataLen < 0) { TRACE1(pHandle->hReport, REPORT_SEVERITY_ERROR, "MLME_PARSER: negative bodyDataLen %d bytes\n", bodyDataLen); TRACE1(pHandle->hReport, REPORT_SEVERITY_ERROR, "Buff len = %d \n", packetLength); report_PrintDump (pPacketBody, packetLength); } #endif } return TI_OK; } mlmeIEParsingParams_t *mlmeParser_getParseIEsBuffer(TI_HANDLE *hMlme) { return (&(((mlme_t *)hMlme)->tempFrameInfo)); } /** * * parseIeBuffer - Parse a required information element. * * \b Description: * * Parse an required information element * and returns a pointer to the IE. * If given a matching buffer as well, returns a pointer to the first IE * that matches the IE ID and the given buffer. * * \b ARGS: * * I - hOs - pointer to OS context * I - pIeBuffer - pointer to the IE buffer \n * I - length - the length of the whole buffer * I - desiredIeId - the desired IE ID * O - pDesiredIe - a pointer to the desired IE * I - pMatchBuffer - a matching buffer in the IE buffer. Optional, if not required a NULL can be given. * I - matchBufferLen - the matching buffer length. Optional, if not required zero can be given. * * * \b RETURNS: * * TI_TRUE if IE pointer was found, TI_FALSE on failure. * * \sa */ TI_BOOL mlmeParser_ParseIeBuffer (TI_HANDLE hMlme, TI_UINT8 *pIeBuffer, TI_UINT32 length, TI_UINT8 desiredIeId, TI_UINT8 **pDesiredIe, TI_UINT8 *pMatchBuffer, TI_UINT32 matchBufferLen) { mlme_t *pMlme = (mlme_t *)hMlme; dot11_eleHdr_t *eleHdr; TI_UINT8 *pCurIe; if (pDesiredIe!=NULL) { *pDesiredIe = NULL; } if ((pIeBuffer == NULL) || (length==0)) { return TI_FALSE; } pCurIe = pIeBuffer; while (length>0) { eleHdr = (dot11_eleHdr_t*)pCurIe; if ((TI_UINT8)length < ((*eleHdr)[1] + 2)) { return TI_FALSE; } if ((*eleHdr)[0] == desiredIeId) { if ((matchBufferLen==0) || (pMatchBuffer == NULL) || (!os_memoryCompare(pMlme->hOs, &pCurIe[2], pMatchBuffer, matchBufferLen))) { if (pDesiredIe!=NULL) { *pDesiredIe = (TI_UINT8*)eleHdr; } return TI_TRUE; } } length -= (*eleHdr)[1] + 2; pCurIe += (*eleHdr)[1] + 2; } return TI_FALSE; }