linux/drivers/staging/rt2860/sta/sanity.c
<<
>>
Prefs
   1/*
   2 *************************************************************************
   3 * Ralink Tech Inc.
   4 * 5F., No.36, Taiyuan St., Jhubei City,
   5 * Hsinchu County 302,
   6 * Taiwan, R.O.C.
   7 *
   8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
   9 *
  10 * This program is free software; you can redistribute it and/or modify  *
  11 * it under the terms of the GNU General Public License as published by  *
  12 * the Free Software Foundation; either version 2 of the License, or     *
  13 * (at your option) any later version.                                   *
  14 *                                                                       *
  15 * This program is distributed in the hope that it will be useful,       *
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  18 * GNU General Public License for more details.                          *
  19 *                                                                       *
  20 * You should have received a copy of the GNU General Public License     *
  21 * along with this program; if not, write to the                         *
  22 * Free Software Foundation, Inc.,                                       *
  23 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  24 *                                                                       *
  25 *************************************************************************
  26
  27        Module Name:
  28        sanity.c
  29
  30        Abstract:
  31
  32        Revision History:
  33        Who                     When                    What
  34        --------        ----------              ----------------------------------------------
  35        John Chang  2004-09-01      add WMM support
  36*/
  37#include "../rt_config.h"
  38
  39extern UCHAR    CISCO_OUI[];
  40
  41extern UCHAR    WPA_OUI[];
  42extern UCHAR    RSN_OUI[];
  43extern UCHAR    WME_INFO_ELEM[];
  44extern UCHAR    WME_PARM_ELEM[];
  45extern UCHAR    Ccx2QosInfo[];
  46extern UCHAR    RALINK_OUI[];
  47extern UCHAR    BROADCOM_OUI[];
  48
  49/*
  50    ==========================================================================
  51    Description:
  52        MLME message sanity check
  53    Return:
  54        TRUE if all parameters are OK, FALSE otherwise
  55    ==========================================================================
  56 */
  57BOOLEAN MlmeStartReqSanity(
  58    IN PRTMP_ADAPTER pAd,
  59    IN VOID *Msg,
  60    IN ULONG MsgLen,
  61    OUT CHAR Ssid[],
  62    OUT UCHAR *pSsidLen)
  63{
  64    MLME_START_REQ_STRUCT *Info;
  65
  66    Info = (MLME_START_REQ_STRUCT *)(Msg);
  67
  68    if (Info->SsidLen > MAX_LEN_OF_SSID)
  69    {
  70        DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqSanity fail - wrong SSID length\n"));
  71        return FALSE;
  72    }
  73
  74    *pSsidLen = Info->SsidLen;
  75    NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen);
  76
  77    return TRUE;
  78}
  79
  80/*
  81    ==========================================================================
  82    Description:
  83        MLME message sanity check
  84    Return:
  85        TRUE if all parameters are OK, FALSE otherwise
  86
  87    IRQL = DISPATCH_LEVEL
  88
  89    ==========================================================================
  90 */
  91BOOLEAN PeerAssocRspSanity(
  92    IN PRTMP_ADAPTER pAd,
  93    IN VOID *pMsg,
  94    IN ULONG MsgLen,
  95    OUT PUCHAR pAddr2,
  96    OUT USHORT *pCapabilityInfo,
  97    OUT USHORT *pStatus,
  98    OUT USHORT *pAid,
  99    OUT UCHAR SupRate[],
 100    OUT UCHAR *pSupRateLen,
 101    OUT UCHAR ExtRate[],
 102    OUT UCHAR *pExtRateLen,
 103    OUT HT_CAPABILITY_IE                *pHtCapability,
 104    OUT ADD_HT_INFO_IE          *pAddHtInfo,    // AP might use this additional ht info IE
 105    OUT UCHAR                   *pHtCapabilityLen,
 106    OUT UCHAR                   *pAddHtInfoLen,
 107    OUT UCHAR                   *pNewExtChannelOffset,
 108    OUT PEDCA_PARM pEdcaParm,
 109    OUT UCHAR *pCkipFlag)
 110{
 111    CHAR          IeType, *Ptr;
 112    PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;
 113    PEID_STRUCT   pEid;
 114    ULONG         Length = 0;
 115
 116        *pNewExtChannelOffset = 0xff;
 117        *pHtCapabilityLen = 0;
 118        *pAddHtInfoLen = 0;
 119    COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
 120    Ptr = pFrame->Octet;
 121    Length += LENGTH_802_11;
 122
 123    NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2);
 124    Length += 2;
 125    NdisMoveMemory(pStatus,         &pFrame->Octet[2], 2);
 126    Length += 2;
 127    *pCkipFlag = 0;
 128    *pExtRateLen = 0;
 129    pEdcaParm->bValid = FALSE;
 130
 131    if (*pStatus != MLME_SUCCESS)
 132        return TRUE;
 133
 134    NdisMoveMemory(pAid, &pFrame->Octet[4], 2);
 135    Length += 2;
 136
 137    // Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform
 138    *pAid = (*pAid) & 0x3fff; // AID is low 14-bit
 139
 140    // -- get supported rates from payload and advance the pointer
 141    IeType = pFrame->Octet[6];
 142    *pSupRateLen = pFrame->Octet[7];
 143    if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES))
 144    {
 145        DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity fail - wrong SupportedRates IE\n"));
 146        return FALSE;
 147    }
 148    else
 149        NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen);
 150
 151    Length = Length + 2 + *pSupRateLen;
 152
 153    // many AP implement proprietary IEs in non-standard order, we'd better
 154    // tolerate mis-ordered IEs to get best compatibility
 155    pEid = (PEID_STRUCT) &pFrame->Octet[8 + (*pSupRateLen)];
 156
 157    // get variable fields from payload and advance the pointer
 158    while ((Length + 2 + pEid->Len) <= MsgLen)
 159    {
 160        switch (pEid->Eid)
 161        {
 162            case IE_EXT_SUPP_RATES:
 163                if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES)
 164                {
 165                    NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len);
 166                    *pExtRateLen = pEid->Len;
 167                }
 168                break;
 169
 170             case IE_HT_CAP:
 171            case IE_HT_CAP2:
 172                        if (pEid->Len >= SIZE_HT_CAP_IE)  //Note: allow extension.!!
 173                        {
 174                                NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE);
 175
 176                                *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
 177                                *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
 178
 179                                *pHtCapabilityLen = SIZE_HT_CAP_IE;
 180                        }
 181                        else
 182                        {
 183                                DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_HT_CAP. \n"));
 184                        }
 185
 186                break;
 187            case IE_ADD_HT:
 188            case IE_ADD_HT2:
 189                        if (pEid->Len >= sizeof(ADD_HT_INFO_IE))
 190                        {
 191                                // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only
 192                                // copy first sizeof(ADD_HT_INFO_IE)
 193                                NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE));
 194
 195                                *(USHORT *)(&pAddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo2));
 196                                *(USHORT *)(&pAddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo3));
 197
 198                                *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE;
 199                        }
 200                        else
 201                        {
 202                                DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_ADD_HT. \n"));
 203                        }
 204
 205                break;
 206            case IE_SECONDARY_CH_OFFSET:
 207                        if (pEid->Len == 1)
 208                        {
 209                                *pNewExtChannelOffset = pEid->Octet[0];
 210                        }
 211                        else
 212                        {
 213                                DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n"));
 214                        }
 215                break;
 216            case IE_AIRONET_CKIP:
 217                // 0. Check Aironet IE length, it must be larger or equal to 28
 218                //    Cisco's AP VxWork version(will not be supported) used this IE length as 28
 219                //    Cisco's AP IOS version used this IE length as 30
 220                if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2))
 221                break;
 222
 223                // 1. Copy CKIP flag byte to buffer for process
 224                *pCkipFlag = *(pEid->Octet + 8);
 225                break;
 226
 227            case IE_AIRONET_IPADDRESS:
 228                if (pEid->Len != 0x0A)
 229                break;
 230
 231                // Get Cisco Aironet IP information
 232                if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1)
 233                    NdisMoveMemory(pAd->StaCfg.AironetIPAddress, pEid->Octet + 4, 4);
 234                break;
 235
 236            // CCX2, WMM use the same IE value
 237            // case IE_CCX_V2:
 238            case IE_VENDOR_SPECIFIC:
 239                // handle WME PARAMTER ELEMENT
 240                if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24))
 241                {
 242                    PUCHAR ptr;
 243                    int i;
 244
 245                    // parsing EDCA parameters
 246                    pEdcaParm->bValid          = TRUE;
 247                    pEdcaParm->bQAck           = FALSE; // pEid->Octet[0] & 0x10;
 248                    pEdcaParm->bQueueRequest   = FALSE; // pEid->Octet[0] & 0x20;
 249                    pEdcaParm->bTxopRequest    = FALSE; // pEid->Octet[0] & 0x40;
 250                    //pEdcaParm->bMoreDataAck    = FALSE; // pEid->Octet[0] & 0x80;
 251                    pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f;
 252                    pEdcaParm->bAPSDCapable    = (pEid->Octet[6] & 0x80) ? 1 : 0;
 253                    ptr = &pEid->Octet[8];
 254                    for (i=0; i<4; i++)
 255                    {
 256                        UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX
 257                        pEdcaParm->bACM[aci]  = (((*ptr) & 0x10) == 0x10);   // b5 is ACM
 258                        pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f;               // b0~3 is AIFSN
 259                        pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f;             // b0~4 is Cwmin
 260                        pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4;               // b5~8 is Cwmax
 261                        pEdcaParm->Txop[aci]  = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us
 262                        ptr += 4; // point to next AC
 263                    }
 264                }
 265
 266                // handle CCX IE
 267                else
 268                {
 269                    // 0. Check the size and CCX admin control
 270                    if (pAd->StaCfg.CCXControl.field.Enable == 0)
 271                        break;
 272                    if (pEid->Len != 5)
 273                        break;
 274
 275                    // Turn CCX2 if matched
 276                    if (NdisEqualMemory(pEid->Octet, Ccx2IeInfo, 5) == 1)
 277                        pAd->StaCfg.CCXEnable = TRUE;
 278                    break;
 279                }
 280                break;
 281
 282            default:
 283                DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity - ignore unrecognized EID = %d\n", pEid->Eid));
 284                break;
 285        }
 286
 287        Length = Length + 2 + pEid->Len;
 288        pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
 289    }
 290
 291    // Force CCX2 enable to TRUE for those AP didn't replay CCX v2 IE, we still force it to be on
 292    if (pAd->StaCfg.CCXControl.field.Enable == 1)
 293        pAd->StaCfg.CCXEnable = TRUE;
 294
 295    return TRUE;
 296}
 297
 298/*
 299    ==========================================================================
 300    Description:
 301        MLME message sanity check
 302    Return:
 303        TRUE if all parameters are OK, FALSE otherwise
 304
 305        IRQL = DISPATCH_LEVEL
 306
 307    ==========================================================================
 308 */
 309BOOLEAN PeerProbeReqSanity(
 310    IN PRTMP_ADAPTER pAd,
 311    IN VOID *Msg,
 312    IN ULONG MsgLen,
 313    OUT PUCHAR pAddr2,
 314    OUT CHAR Ssid[],
 315    OUT UCHAR *pSsidLen)
 316{
 317    UCHAR         Idx;
 318    UCHAR             RateLen;
 319    CHAR          IeType;
 320    PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
 321
 322    COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
 323
 324    if ((pFrame->Octet[0] != IE_SSID) || (pFrame->Octet[1] > MAX_LEN_OF_SSID))
 325    {
 326        DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SSID IE(Type=%d,Len=%d)\n",pFrame->Octet[0],pFrame->Octet[1]));
 327        return FALSE;
 328    }
 329
 330    *pSsidLen = pFrame->Octet[1];
 331    NdisMoveMemory(Ssid, &pFrame->Octet[2], *pSsidLen);
 332
 333    Idx = *pSsidLen + 2;
 334
 335    // -- get supported rates from payload and advance the pointer
 336    IeType = pFrame->Octet[Idx];
 337    RateLen = pFrame->Octet[Idx + 1];
 338    if (IeType != IE_SUPP_RATES)
 339    {
 340        DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SupportRates IE(Type=%d,Len=%d)\n",pFrame->Octet[Idx],pFrame->Octet[Idx+1]));
 341        return FALSE;
 342    }
 343    else
 344    {
 345        if ((pAd->CommonCfg.PhyMode == PHY_11G) && (RateLen < 8))
 346            return (FALSE);
 347    }
 348
 349    return TRUE;
 350}
 351
 352/*
 353    ==========================================================================
 354    Description:
 355
 356        IRQL = DISPATCH_LEVEL
 357
 358    ==========================================================================
 359 */
 360BOOLEAN GetTimBit(
 361    IN CHAR *Ptr,
 362    IN USHORT Aid,
 363    OUT UCHAR *TimLen,
 364    OUT UCHAR *BcastFlag,
 365    OUT UCHAR *DtimCount,
 366    OUT UCHAR *DtimPeriod,
 367    OUT UCHAR *MessageToMe)
 368{
 369    UCHAR          BitCntl, N1, N2, MyByte, MyBit;
 370    CHAR          *IdxPtr;
 371
 372    IdxPtr = Ptr;
 373
 374    IdxPtr ++;
 375    *TimLen = *IdxPtr;
 376
 377    // get DTIM Count from TIM element
 378    IdxPtr ++;
 379    *DtimCount = *IdxPtr;
 380
 381    // get DTIM Period from TIM element
 382    IdxPtr++;
 383    *DtimPeriod = *IdxPtr;
 384
 385    // get Bitmap Control from TIM element
 386    IdxPtr++;
 387    BitCntl = *IdxPtr;
 388
 389    if ((*DtimCount == 0) && (BitCntl & 0x01))
 390        *BcastFlag = TRUE;
 391    else
 392        *BcastFlag = FALSE;
 393
 394    // Parse Partial Virtual Bitmap from TIM element
 395    N1 = BitCntl & 0xfe;    // N1 is the first bitmap byte#
 396    N2 = *TimLen - 4 + N1;  // N2 is the last bitmap byte#
 397
 398    if ((Aid < (N1 << 3)) || (Aid >= ((N2 + 1) << 3)))
 399        *MessageToMe = FALSE;
 400    else
 401    {
 402        MyByte = (Aid >> 3) - N1;                       // my byte position in the bitmap byte-stream
 403        MyBit = Aid % 16 - ((MyByte & 0x01)? 8:0);
 404
 405        IdxPtr += (MyByte + 1);
 406
 407        //if (*IdxPtr)
 408        //    DBGPRINT(RT_DEBUG_WARN, ("TIM bitmap = 0x%02x\n", *IdxPtr));
 409
 410        if (*IdxPtr & (0x01 << MyBit))
 411            *MessageToMe = TRUE;
 412        else
 413            *MessageToMe = FALSE;
 414    }
 415
 416    return TRUE;
 417}
 418
 419