Beispiel #1
0
NDIS_STATUS
HelperPortReceiveMgmtPacket(
    __in  PMP_HELPER_PORT         HelperPort,
    __in  PMP_RX_MPDU             pNicFragment,
    __in  USHORT                  FragmentSize
    )
{
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    PDOT11_MGMT_HEADER  pMgmtPktHeader;
    
    // This is a management packet, reject if size isnt right
    if (FragmentSize < sizeof(DOT11_MGMT_HEADER))
    {
        return NDIS_STATUS_NOT_ACCEPTED;
    }

    pMgmtPktHeader = MP_RX_MPDU_DATA(pNicFragment);
    switch(pMgmtPktHeader->FrameControl.Subtype)
    {
        case DOT11_MGMT_SUBTYPE_BEACON:
        case DOT11_MGMT_SUBTYPE_PROBE_RESPONSE:
            HelperPortReceiveBeacon(
                HelperPort,
                pNicFragment,
                FragmentSize
                );
            break;

        default:
            break;
    }

    return ndisStatus;    
Beispiel #2
0
VOID 
HelperPortReceiveBeacon(
    __in  PMP_HELPER_PORT         HelperPort,
    __in  PMP_RX_MPDU             pFragment,
    __in  ULONG                   TotalLength
    )
{
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    PUCHAR              pPacketBuffer;
    PDOT11_BEACON_FRAME pDot11BeaconFrame;
    ULONG               uOffsetOfInfoElemBlob =
                            FIELD_OFFSET(DOT11_BEACON_FRAME, InfoElements) + sizeof(DOT11_MGMT_HEADER);
    ULONG               uInfoElemBlobSize = 0;

    pPacketBuffer = MP_RX_MPDU_DATA(pFragment);
    do
    {
        // 
        // Drop if its doesnt contain atleast the
        // fixed size portion (DOT11_BEACON_FRAME)
        //
        if (uOffsetOfInfoElemBlob > TotalLength)
        {
            break;
        }

        // Get/Validate beacon is okay
        pDot11BeaconFrame = (PDOT11_BEACON_FRAME)(pPacketBuffer + sizeof(DOT11_MGMT_HEADER));
        ndisStatus = HelperPortValidateBeacon(pDot11BeaconFrame);
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            break;
        }

        // Validate information elements blob
        ndisStatus = Dot11GetInfoBlobSize(
            pPacketBuffer,
            TotalLength,
            uOffsetOfInfoElemBlob,
            &uInfoElemBlobSize
            );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            break;
        }

        // Save information from this beacon into our BSS list
        ndisStatus = HelperPortSaveBSSInformation(
            HelperPort,
            pFragment,
            pDot11BeaconFrame,
            (uInfoElemBlobSize + FIELD_OFFSET(DOT11_BEACON_FRAME, InfoElements))    // Info elements + header
            );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            break;
        }
    } while (FALSE);
Beispiel #3
0
NDIS_STATUS 
HelperPortReceiveEventHandler(
    __in  PMP_PORT                Port,
    __in  PMP_RX_MSDU             PacketList,
    __in  ULONG                   ReceiveFlags
    )
{
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    PDOT11_MAC_HEADER   packetHeader;
    PMP_RX_MPDU         rxFragment;
    USHORT              fragmentSize;
    PMP_RX_MSDU         currentPacket = PacketList;

    UNREFERENCED_PARAMETER(ReceiveFlags);
    
    // Process each of the packets internally
    while (currentPacket != NULL)
    {
        // We only accept 1 fragment
        rxFragment = MP_RX_MSDU_MPDU_AT(currentPacket, 0);    
        packetHeader = MP_RX_MPDU_DATA(rxFragment);
        fragmentSize = (USHORT)MP_RX_MPDU_LENGTH(rxFragment);
        
        switch(packetHeader->FrameControl.Type)
        {
            case DOT11_FRAME_TYPE_MANAGEMENT:
                //
                // Process management packet
                //
                ndisStatus = HelperPortReceiveMgmtPacket(
                    MP_GET_HELPPORT(Port),
                    rxFragment,
                    fragmentSize
                    );
                break;
                
            default:
                break;
        }

        //
        // Set the status. This determines if this packet should
        // be forwarded up or not
        //
        MP_RX_MSDU_STATUS(currentPacket) = ndisStatus;

        // Next packet
        currentPacket = MP_RX_MSDU_NEXT_MSDU(currentPacket);
    }

    return NDIS_STATUS_SUCCESS;
Beispiel #4
0
NDIS_STATUS
BasePortTranslateRxPacketsToRxNBLs(
    __in  PMP_PORT                Port,
    __in  PMP_RX_MSDU             PacketList,
    __out PNET_BUFFER_LIST*       NetBufferLists
    )
{
    PNET_BUFFER_LIST            outputNetBufferList = NULL;
    PNET_BUFFER_LIST            currentNetBufferList, prevNetBufferList = NULL;
    USHORT                      fragmentIndex = 0;
    PMP_RX_MSDU                 currentPacket = PacketList, nextPacket;
    PMP_RX_MPDU                 currentFragment;
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    PDOT11_EXTSTA_RECV_CONTEXT  osRecvContext;  // This is same for ExtAP & ExtSTA
    PMDL                        currentMdl, prevMdl = NULL, mdlChain = NULL;
    ULONG                       totalLength = 0;
    
    *NetBufferLists = NULL;

    // Convert each PACKET and FRAGMENT to OS structures
    while (currentPacket != NULL)
    {
        nextPacket = MP_RX_MSDU_NEXT_MSDU(currentPacket);
        
        // Go through the FRAGMENTs in this PACKET & create an MDL chain
        mdlChain = NULL;
        totalLength = 0;
        
        for (fragmentIndex = 0; 
             fragmentIndex < MP_RX_MSDU_MPDU_COUNT(currentPacket);
             fragmentIndex++)
        {
            currentFragment = MP_RX_MSDU_MPDU_AT(currentPacket, fragmentIndex);
            totalLength += MP_RX_MPDU_LENGTH(currentFragment);
            
            // Populate the MDL with Fragment contents
            currentMdl = NdisAllocateMdl(Port->MiniportAdapterHandle,
                                MP_RX_MPDU_DATA(currentFragment),
                                MP_RX_MPDU_LENGTH(currentFragment)
                                );
            if (currentMdl == NULL)
            {
                MpTrace(COMP_RECV, DBG_SERIOUS, ("Failed to allocate MDL for a MP_RX_MPDU data\n"));
                ndisStatus = NDIS_STATUS_RESOURCES;
                break;
            }

            // Add this to the MDL chain
            if (mdlChain == NULL)
            {
                // Add this to the head
                mdlChain = currentMdl;
            }
            else
            {
                NDIS_MDL_LINKAGE(prevMdl) = currentMdl;
            }
            prevMdl = currentMdl;
        }
        
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            while (mdlChain != NULL)
            {
                currentMdl = mdlChain;
                mdlChain = NDIS_MDL_LINKAGE(currentMdl);
                
                // MDL was allocated
                NdisFreeMdl(currentMdl);
            }            
            break;
        }

        // Allocate the NET_BUFFER_LIST and the NET_BUFFER
        currentNetBufferList = NdisAllocateNetBufferAndNetBufferList(
                                    Port->RxNetBufferListPool,
                                    0,
                                    0,
                                    mdlChain,
                                    0,
                                    totalLength
                                    );
        if (currentNetBufferList == NULL)
        {
            MpTrace(COMP_SEND, DBG_SERIOUS, ("Failed to allocate NET_BUFFER_LIST for MP_RX_MSDU  \n"));        
            ndisStatus = NDIS_STATUS_RESOURCES;
            break;
        }
        
        // Populate the RX_PACKET
        MP_NBL_WRAPPED_RX_MSDU(currentNetBufferList) = currentPacket;
        MP_NBL_SOURCE_PORT(currentNetBufferList) = Port;
        
        if (outputNetBufferList == NULL)
        {
            outputNetBufferList = currentNetBufferList;
        }
        else
        {
            NET_BUFFER_LIST_NEXT_NBL(prevNetBufferList) = currentNetBufferList;
        }
        
        // The Next PACKET's NBL would be added after the current PACKET's NBL
        prevNetBufferList = currentNetBufferList;

        osRecvContext = MP_RX_MSDU_RECV_CONTEXT(currentPacket);

        MP_ASSIGN_NDIS_OBJECT_HEADER(osRecvContext->Header, 
             NDIS_OBJECT_TYPE_DEFAULT,
             DOT11_EXTSTA_RECV_CONTEXT_REVISION_1,
             sizeof(DOT11_EXTSTA_RECV_CONTEXT));
        
        MP_SET_RECEIVE_CONTEXT(currentNetBufferList, osRecvContext);        
        
        currentPacket = nextPacket;
    }


    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        if (outputNetBufferList != NULL)
        {
            BasePortFreeTranslatedRxNBLs(Port, outputNetBufferList);
            outputNetBufferList = NULL;
        }
    }

    *NetBufferLists = outputNetBufferList;

    return ndisStatus;
}
Beispiel #5
0
BOOLEAN
BasePortFilterFragment(
    __in  PMP_PORT                Port,
    __in  PMP_RX_MSDU             Packet
    )
{
    PUCHAR      pktbuf = MP_RX_MPDU_DATA(MP_RX_MSDU_MPDU_AT(Packet, 0));
    UCHAR       type = (pktbuf[0] & 0x0f) >> 2;
    BOOLEAN     bAddrMatch = MP_COMPARE_MAC_ADDRESS(pktbuf + 4, VNic11QueryMACAddress(PORT_GET_VNIC(Port)));
    BOOLEAN     bIsBroadcast = DOT11_IS_BROADCAST(&pktbuf[4]);
    BOOLEAN     bIsMulticast = DOT11_IS_MULTICAST(&pktbuf[4]);

    switch(type)
    {
    case DOT11_FRAME_TYPE_MANAGEMENT:
        if (bAddrMatch && (Port->PacketFilter & NDIS_PACKET_TYPE_802_11_DIRECTED_MGMT))
            return TRUE;
        
        if (bIsBroadcast && (Port->PacketFilter & NDIS_PACKET_TYPE_802_11_BROADCAST_MGMT))
            return TRUE;

        if (bIsMulticast && (Port->PacketFilter & (NDIS_PACKET_TYPE_802_11_MULTICAST_MGMT | 
                                                           NDIS_PACKET_TYPE_802_11_ALL_MULTICAST_MGMT)))
            return TRUE;

        if (Port->PacketFilter & NDIS_PACKET_TYPE_802_11_PROMISCUOUS_MGMT)
            return TRUE;

        break;
        
    case DOT11_FRAME_TYPE_CONTROL:
        if (bAddrMatch && (Port->PacketFilter & NDIS_PACKET_TYPE_802_11_DIRECTED_CTRL))
            return TRUE;

        if (bIsBroadcast && (Port->PacketFilter & NDIS_PACKET_TYPE_802_11_BROADCAST_CTRL))
            return TRUE;

        if (Port->PacketFilter & NDIS_PACKET_TYPE_802_11_PROMISCUOUS_CTRL)
            return TRUE;

        //
        // Note: no multicast control frame.
        //

        break;
        
    case DOT11_FRAME_TYPE_DATA:
        if (bAddrMatch && (Port->PacketFilter & NDIS_PACKET_TYPE_DIRECTED))
            return TRUE;

        if (bIsBroadcast && (Port->PacketFilter & NDIS_PACKET_TYPE_BROADCAST))
            return TRUE;

        if (bIsMulticast&& (Port->PacketFilter & (NDIS_PACKET_TYPE_MULTICAST | 
                                                          NDIS_PACKET_TYPE_ALL_MULTICAST)))
            return TRUE;

        if (Port->PacketFilter & (NDIS_PACKET_TYPE_PROMISCUOUS | 
                                          NDIS_PACKET_TYPE_802_11_RAW_DATA))
            return TRUE;

        break;
        
    default:
        //
        // Reserved packet should always be filtered
        //
        return FALSE;
    }

    return FALSE;
}
Beispiel #6
0
NDIS_STATUS
Ap11ReceiveHandler(
    __in PMP_PORT Port,
    __in PMP_RX_MSDU   PacketList,
    __in ULONG ReceiveFlags
    )
{
    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
    PAP_ASSOC_MGR assocMgr = AP_GET_ASSOC_MGR(MP_GET_AP_PORT(Port));
    PDOT11_MGMT_HEADER mgmtPktHeader;
    PMP_RX_MPDU     rxFragment;
    USHORT fragmentSize;
    PMP_RX_MSDU   currentPacket;
    PMAC_HASH_ENTRY macEntry;
    PAP_STA_ENTRY staEntry;
    DOT11_ASSOCIATION_STATE assocState;
    DOT11_FRAME_CLASS frameClass;
    MP_RW_LOCK_STATE lockState;
    //
    // The following boolean is used to improve the performance w.r.t. lock
    //
    BOOLEAN holdReadLock = FALSE;

    UNREFERENCED_PARAMETER(ReceiveFlags);
    
    // 
    // Reference AP port first
    //
    ApRefPort(MP_GET_AP_PORT(Port));
    
    do
    {
        // 
        // Only process packets when AP is started
        //
        if (ApGetState(MP_GET_AP_PORT(Port)) != AP_STATE_STARTED)
        {
            ndisStatus = NDIS_STATUS_INVALID_STATE;
            break;
        }
        
        // 
        // Process each of the packets internally
        //
        for (currentPacket = PacketList;
             currentPacket != NULL;
             currentPacket = MP_RX_MSDU_NEXT_MSDU(currentPacket)
             )
        {
            // 
            // We only accept 1 fragment
            //
            rxFragment = MP_RX_MSDU_MPDU_AT(currentPacket, 0);
            fragmentSize = (USHORT)MP_RX_MPDU_LENGTH(rxFragment);
            if (fragmentSize < DOT11_MGMT_HEADER_SIZE)
            {
                continue;
            }

            mgmtPktHeader = MP_RX_MPDU_DATA(rxFragment);

            //
            // TODO: ignore packets that are not in this BSSID?
            //
            if (!MP_COMPARE_MAC_ADDRESS(mgmtPktHeader->BSSID, assocMgr->Bssid))
            {
                continue;
            }
            
            //
            // Check whether ExtAP needs to process the packet
            //
            // If ExtAP will process the packet, a write lock will be acquired later.
            // The association state of the send station is validated when the packet
            // is processed.
            //
            // Otherwise, we need to hold a read lock on the 
            // Mac table to check the association state of the sending station.
            // We don't hold a write lock because we can tolerate
            // inconsistency in statistics to achieve better performance.
            //
            if (ApNeedToProcessPacket(
                    mgmtPktHeader, 
                    fragmentSize
                    ))
            {
                //
                // Process the management packet
                //
                
                //
                // 1. Release the read lock if it is held because a write lock may be acquired
                //    in the process of the management packet
                // 2. Process the management packet
                // This improves the performance if we receive a bunch of data packets.
                //
                if (holdReadLock)
                {
                    MP_RELEASE_READ_LOCK(&assocMgr->MacHashTableLock, &lockState);
                    holdReadLock = FALSE;
                }
                
                //
                // Don't pass the packet up if it is not valid
                //
                ndisStatus = ApProcessPacket(
                                MP_GET_AP_PORT(Port),
                                mgmtPktHeader,
                                fragmentSize
                                );
            }
            else
            {
                //
                // Need to know the association state of the sending station
                //
                
                //
                // Acquire read lock if we don't hold it
                //
                if (!holdReadLock)
                {
                    MP_ACQUIRE_READ_LOCK(&assocMgr->MacHashTableLock, &lockState);
                    holdReadLock = TRUE;
                }

                //
                // Lookup the station entry from Mac table if it exists
                //
                macEntry = LookupMacHashTable(
                            &assocMgr->MacHashTable, 
                            &mgmtPktHeader->SA
                            );
                
                // 
                // Get the station association state
                //
                if (macEntry != NULL)
                {
                    staEntry = CONTAINING_RECORD(macEntry, AP_STA_ENTRY, MacHashEntry);
                    assocState = ApGetStaAssocState(staEntry);
                    
                    //
                    // Reset station inactive time.
                    // No need to check the association state.
                    // Ignore the returned original value.
                    //
                    ApResetStaInactiveTime(staEntry);
                }
                else
                {
                    assocState = dot11_assoc_state_unauth_unassoc;
                }
                
                //
                // Get the frame class
                //
                frameClass = Dot11GetFrameClass(&mgmtPktHeader->FrameControl);

                switch(frameClass)
                {
                    case DOT11_FRAME_CLASS_1:
                        //
                        // Class 1 frames are always allowed
                        //
                        break;

                    case DOT11_FRAME_CLASS_2:
                        //
                        // Class 2 frames are allowed if the station is authenticated
                        //
                        if (dot11_assoc_state_unauth_unassoc == assocState)
                        {
                            ndisStatus = NDIS_STATUS_INVALID_STATE;
                        }
                        break;

                    case DOT11_FRAME_CLASS_3:
                        //
                        // Class 3 frames are allowed if the station is associated
                        //
                        if (assocState != dot11_assoc_state_auth_assoc)
                        {
                            ndisStatus = NDIS_STATUS_INVALID_STATE;
                        }
                        break;

                    default:
                        ndisStatus = NDIS_STATUS_INVALID_STATE;
                }

                //
                // Validate data packet
                //
                if (NDIS_STATUS_SUCCESS == ndisStatus && DOT11_FRAME_TYPE_DATA == mgmtPktHeader->FrameControl.Type)
                {
                    ndisStatus = ApValidateDataPacket(
                                    MP_GET_AP_PORT(Port), 
                                    rxFragment, 
                                    fragmentSize
                                    );
                }
            }

            //
            // Mark the status for the current packet and reset ndis status
            //
            MP_TX_MSDU_STATUS(currentPacket) = ndisStatus;
            ndisStatus = NDIS_STATUS_SUCCESS;
        }
             
        //
        // Release the read lock
        //
        if (holdReadLock)
        {
            MP_RELEASE_READ_LOCK(&assocMgr->MacHashTableLock, &lockState);
        }

    } while (FALSE);

    // 
    // Dereference AP port
    //
    ApDerefPort(MP_GET_AP_PORT(Port));

    return ndisStatus;
}
Beispiel #7
0
/**
 * Validate data packet.
 * Will check encryption in the validation.
 */
NDIS_STATUS
ApValidateDataPacket(
    __in PMP_EXTAP_PORT ApPort,
    __in PMP_RX_MPDU Fragment,
    __in USHORT FragmentSize
    )
{
    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
    PDOT11_PRIVACY_EXEMPTION_LIST privacyExemptionList = AP_GET_ASSOC_MGR(ApPort)->PrivacyExemptionList;
    USHORT etherType;
    USHORT packetType;
    PDOT11_PRIVACY_EXEMPTION privacyExemption;
    ULONG index;
    BOOLEAN isUnicast;
    USHORT sequenceNumber;
    PDOT11_DATA_SHORT_HEADER fragmentHdr = (PDOT11_DATA_SHORT_HEADER)MP_RX_MPDU_DATA(Fragment);
    BOOLEAN checkExcludeUnencrypted = TRUE;

    do
    {
        //
        // We don't check the fragmented data frame that is not the first fragment.
        //
        if (FragmentSize < DOT11_DATA_SHORT_HEADER_SIZE)
        {
            ndisStatus = NDIS_STATUS_NOT_ACCEPTED;
            break;
        }
        
        RtlCopyMemory(
            &sequenceNumber, 
            &fragmentHdr->SequenceControl, 
            2
            );
        
        if ((sequenceNumber & 0x0f) != 0)
        {
            break;
        }
        
        //
        // Data frame must also contain 802.2 LLC and 802.2 SNAP (8 bytes total)
        //
        if (FragmentSize < DOT11_DATA_SHORT_HEADER_SIZE + sizeof(IEEE_8022_LLC_SNAP))
        {
            ndisStatus = NDIS_STATUS_NOT_ACCEPTED;
            break;
        }

        //
        // Go through the privacy exemption list to see if we can accept the data frame.
        //
        if (privacyExemptionList && privacyExemptionList->uNumOfEntries > 0)
        {
            //
            // Find the EtherType and PacketType of the frame
            //

            etherType = ((PIEEE_8022_LLC_SNAP)Add2Ptr(fragmentHdr, DOT11_DATA_SHORT_HEADER_SIZE))->sh_etype;
            isUnicast = (BOOLEAN)DOT11_IS_UNICAST(fragmentHdr->Address1);
            packetType = isUnicast ? DOT11_EXEMPT_UNICAST : DOT11_EXEMPT_MULTICAST;

            //
            // Check the disposition of the frame.
            //

            privacyExemption = privacyExemptionList->PrivacyExemptionEntries;
            for (index = 0; index < privacyExemptionList->uNumOfEntries; index++, privacyExemption++)
            {
                //
                // Skip if EtherType does not match
                //

                if (privacyExemption->usEtherType != etherType)
                {
                    continue;
                }

                //
                // Skip if PacketType does not match
                //

                if (privacyExemption->usExemptionPacketType != packetType &&
                    privacyExemption->usExemptionPacketType != DOT11_EXEMPT_BOTH)
                {
                    continue;
                }

                if (privacyExemption->usExemptionActionType == DOT11_EXEMPT_ALWAYS)
                {
                    //
                    // In this case, we drop the frame if it was originally
                    // encrypted.
                    //
                    if (MP_TEST_FLAG(Fragment->Msdu->Flags, MP_RX_MSDU_FLAG_ENCRYPTED))
                    {
                        ndisStatus = NDIS_STATUS_NOT_ACCEPTED;
                    }

                    //
                    // No need to check exclude unencrypted
                    //
                    checkExcludeUnencrypted = FALSE;
                    
                    break;
                }
                else if (privacyExemption->usExemptionActionType == DOT11_EXEMPT_ON_KEY_MAPPING_KEY_UNAVAILABLE)
                {
                    //
                    // In this case, we reject the frame if it was originally NOT encrypted but 
                    // we have the key mapping key for this frame.
                    //
                    if (!MP_TEST_FLAG(Fragment->Msdu->Flags, MP_RX_MSDU_FLAG_ENCRYPTED) && 
                        isUnicast && 
                        VNic11IsKeyMappingKeyAvailable(AP_GET_VNIC(ApPort), fragmentHdr->Address2)
                        )
                    {
                        ndisStatus = NDIS_STATUS_NOT_ACCEPTED;
                    }

                    //
                    // No need to check exclude unencrypted
                    //
                    checkExcludeUnencrypted = FALSE;
                    
                    break;
                }
                else 
                {
                    //
                    // The privacy exemption does not apply to this frame.
                    //

                    break;
                }
            }
        }

        //
        // If the privacy exemption list does not apply to the frame, check ExcludeUnencrypted.
        // if ExcludeUnencrypted is set and this frame was not oringially an encrypted frame, 
        // dropped it.
        //
        if (checkExcludeUnencrypted)
        {
            if (AP_GET_ASSOC_MGR(ApPort)->ExcludeUnencrypted && !MP_TEST_FLAG(Fragment->Msdu->Flags, MP_RX_MSDU_FLAG_ENCRYPTED))
            {
                ndisStatus = NDIS_STATUS_NOT_ACCEPTED;
            }
        }

    } while (FALSE);   
    
    return ndisStatus;
}
Beispiel #8
0
VOID 
StaReceiveBeacon(
    _In_  PMP_EXTSTA_PORT                        pStation,
    _In_  PMP_RX_MPDU                    pFragment,
    _In_  ULONG                           TotalLength
    )
{
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    PUCHAR              pPacketBuffer;
    PDOT11_BEACON_FRAME pDot11BeaconFrame;
    ULONG               uOffsetOfInfoElemBlob =
                            FIELD_OFFSET(DOT11_BEACON_FRAME, InfoElements) + sizeof(DOT11_MGMT_HEADER);
    ULONG               uInfoElemBlobSize = 0;

    pPacketBuffer = MP_RX_MPDU_DATA(pFragment);
    do
    {
        // 
        // Drop if its doesnt contain atleast the
        // fixed size portion (DOT11_BEACON_FRAME)
        //
        if (uOffsetOfInfoElemBlob > TotalLength)
        {
            break;
        }

        pDot11BeaconFrame = (PDOT11_BEACON_FRAME)(pPacketBuffer + sizeof(DOT11_MGMT_HEADER));
        
        // Validate information elements blob
        ndisStatus = Dot11GetInfoBlobSize(
            pPacketBuffer,
            TotalLength,
            uOffsetOfInfoElemBlob,
            &uInfoElemBlobSize
            );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            break;
        }

        if (pDot11BeaconFrame->Capability.IBSS) {
            ndisStatus = StaSaveAdHocStaInfo(
                pStation,
                pFragment,
                pDot11BeaconFrame,
                uInfoElemBlobSize
                );
        }
            
        ndisStatus = StaProcessBeaconForConfigInfo(
            pStation,
            pFragment,
            (PUCHAR)&pDot11BeaconFrame->InfoElements,
            TotalLength
            );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            break;
        }
    } while (FALSE);
}
Beispiel #9
0
NDIS_STATUS 
HelperPortSaveBSSInformation(
    __in  PMP_HELPER_PORT        HelperPort,
    __in  PMP_RX_MPDU        pFragment,
    __in  PDOT11_BEACON_FRAME pDot11BeaconFrame,
    __in  ULONG           BeaconDataLength
    )
{
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    MP_RW_LOCK_STATE          LockState;
    PMP_BSS_ENTRY      pBSSEntry = NULL;
    PDOT11_MGMT_HEADER  pMgmtPktHeader;
    PMP_BSS_LIST       pDiscoveredBSSList = &(HelperPort->BSSList);

    pMgmtPktHeader = (PDOT11_MGMT_HEADER)MP_RX_MPDU_DATA(pFragment);

    //
    // In most cases, we would be updating information about this
    // AP in our list. For this reason, we only acquire read lock
    // for most cases
    //
    MP_ACQUIRE_READ_LOCK(&(HelperPort->BSSList.ListLock), &LockState);

    //
    // See if this entry already exists in the list
    //
    pBSSEntry = HelperPortFindBSSEntry(
        pDiscoveredBSSList,
        pMgmtPktHeader->SA
        );

    if (pBSSEntry == NULL)
    {
        //
        // Entry does not exist, we are adding information about a new BSS
        //

        MP_RELEASE_READ_LOCK(&(HelperPort->BSSList.ListLock), &LockState);

        ndisStatus = HelperPortInsertBSSEntry(
            HelperPort, 
            pFragment, 
            pDot11BeaconFrame, 
            BeaconDataLength
            );
        
    }
    else
    {
        //
        // Entry already exists, we are just updating
        //
        
        ndisStatus = HelperPortUpdateBSSEntry(
            HelperPort, 
            pBSSEntry,
            pFragment, 
            pDot11BeaconFrame, 
            BeaconDataLength
            );  // Read lock still held

        MP_RELEASE_READ_LOCK(&(HelperPort->BSSList.ListLock), &LockState);
    }

    return ndisStatus;
Beispiel #10
0
// BSS list lock acquired & called at Dispatch
NDIS_STATUS 
HelperPortUpdateBSSEntry(
    __in  PMP_HELPER_PORT        HelperPort,
    __in  PMP_BSS_ENTRY  pBSSEntry,
    __in  PMP_RX_MPDU        pFragment,
    __in  PDOT11_BEACON_FRAME pDot11BeaconPRFrame,
    __in  ULONG           BeaconPRDataLength
    )
{
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    PDOT11_MGMT_HEADER  pMgmtPktHeader;
    ULONGLONG           ullHostTimeStamp;
    PVOID               pSavedBeaconPRBuffer = NULL;
    ULONG               uOffsetOfInfoElemBlob = FIELD_OFFSET(DOT11_BEACON_FRAME, InfoElements);
    UCHAR               channel;
    DOT11_PHY_TYPE      PhyType;

    pMgmtPktHeader = (PDOT11_MGMT_HEADER)MP_RX_MPDU_DATA(pFragment);
    NdisGetCurrentSystemTime((PLARGE_INTEGER)&ullHostTimeStamp);
    
    do
    {
        // 
        // Modifying data in the AP entry
        //
        NdisDprAcquireSpinLock(&(pBSSEntry->Lock));

        if (pDot11BeaconPRFrame->Capability.IBSS)
        {
            pBSSEntry->Dot11BSSType = dot11_BSS_type_independent;
        }
        else
        {   
            pBSSEntry->Dot11BSSType = dot11_BSS_type_infrastructure;
        }
        
        //
        // Adhoc station can leave adhoc cell and create a new cell. SoftAPs
        // can move. This means the BSSID can change
        //
        NdisMoveMemory(
            pBSSEntry->Dot11BSSID,
            pMgmtPktHeader->BSSID,
            sizeof(DOT11_MAC_ADDRESS)
            );

        pBSSEntry->HostTimestamp = ullHostTimeStamp;
        pBSSEntry->BeaconTimestamp = pDot11BeaconPRFrame->Timestamp;
        pBSSEntry->BeaconInterval = pDot11BeaconPRFrame->BeaconInterval;
        pBSSEntry->Dot11Capability = pDot11BeaconPRFrame->Capability;
        pBSSEntry->RSSI = pFragment->Msdu->RecvContext.lRSSI;
        pBSSEntry->LinkQuality = pFragment->Msdu->LinkQuality;
        pBSSEntry->ChannelCenterFrequency 
            = pFragment->Msdu->RecvContext.uChCenterFrequency;

        //
        // If signal strength was below our threshold, catch that
        //
        if (pBSSEntry->LinkQuality < HelperPort->RegInfo->RSSILinkQualityThreshold)
        {
            pBSSEntry->LowQualityCount++;
        }
        else
        {
            pBSSEntry->LowQualityCount = 0;
        }

#if 0
        if (pBSSEntry->AssocState == dot11_assoc_state_auth_assoc)
        {
            MpTrace(COMP_ASSOC, DBG_LOUD, ("Received beacon from associated AP: %02X-%02X-%02X-%02X-%02X-%02X\n",
                pMgmtPktHeader->SA[0], pMgmtPktHeader->SA[1], pMgmtPktHeader->SA[2], 
                pMgmtPktHeader->SA[3], pMgmtPktHeader->SA[4], pMgmtPktHeader->SA[5]));
        }
#endif

        //
        // Get channel number at which the frame was received.
        //
        if (Dot11GetChannelForDSPhy(Add2Ptr(pDot11BeaconPRFrame, uOffsetOfInfoElemBlob),
                                    BeaconPRDataLength - uOffsetOfInfoElemBlob, 
                                    &channel) != NDIS_STATUS_SUCCESS)
        {
            channel = pFragment->Msdu->Channel;
        }

        if (channel != 0)
        {
            pBSSEntry->Channel = channel;
        }

        //
        // Get PhyType and PhyId
        //
        PhyType = VNic11DeterminePHYType(HELPPORT_GET_VNIC(HelperPort), 
                                       pBSSEntry->Dot11Capability,
                                       pBSSEntry->Channel);
        if (pBSSEntry->Dot11PhyType != PhyType)
        {
            pBSSEntry->Dot11PhyType = PhyType;
            pBSSEntry->PhyId = BasePortGetPhyIdFromType(HELPPORT_GET_MP_PORT(HelperPort), PhyType);
        }

        if (pMgmtPktHeader->FrameControl.Subtype == DOT11_MGMT_SUBTYPE_BEACON)
        {
            //
            // Increase the beacon frame size if necessary
            //
            if (pBSSEntry->MaxBeaconFrameSize < BeaconPRDataLength)
            {
                MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, 
                    &pSavedBeaconPRBuffer, 
                    BeaconPRDataLength,
                    PORT_MEMORY_TAG
                    );
                    
                if (pSavedBeaconPRBuffer == NULL)
                {
                    //
                    // Unable to allocate memory for information elements.
                    // If this is a new AP entry, we wont be adding it to the list.
                    // For existing entries, we end up ignoring the new IE blob
                    //
                    ndisStatus = NDIS_STATUS_RESOURCES;
                    NdisDprReleaseSpinLock(&(pBSSEntry->Lock));
                    break;
                }
                //
                // Delete any old blob buffer
                //
                if (pBSSEntry->pDot11BeaconFrame != NULL)
                {
                    MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame);
                }

                pBSSEntry->pDot11BeaconFrame = pSavedBeaconPRBuffer;
                pBSSEntry->MaxBeaconFrameSize = BeaconPRDataLength;
            }

            // Update the beacon
            pBSSEntry->BeaconFrameSize = BeaconPRDataLength;
            
            // Also save this as the IE blob pointer
            pBSSEntry->InfoElemBlobSize = BeaconPRDataLength - uOffsetOfInfoElemBlob;
            pBSSEntry->pDot11InfoElemBlob = (PUCHAR)pBSSEntry->pDot11BeaconFrame + uOffsetOfInfoElemBlob;
            
            //
            // Update/Save the beacon information element block
            //
            NdisMoveMemory(
                pBSSEntry->pDot11BeaconFrame,
                pDot11BeaconPRFrame,
                BeaconPRDataLength
                );
        }
    
        if (pMgmtPktHeader->FrameControl.Subtype == DOT11_MGMT_SUBTYPE_PROBE_RESPONSE)
        {
            //
            // Increase the probe response frame size if necessary
            //
            if (pBSSEntry->MaxProbeFrameSize < BeaconPRDataLength)
            {
                MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, 
                    &pSavedBeaconPRBuffer, 
                    BeaconPRDataLength,
                    PORT_MEMORY_TAG
                    );
                    
                if (pSavedBeaconPRBuffer == NULL)
                {
                    //
                    // Unable to allocate memory for information elements.
                    // If this is a new AP entry, we wont be adding it to the list.
                    // For existing entries, we end up ignoring the new IE blob
                    //
                    ndisStatus = NDIS_STATUS_RESOURCES;
                    NdisDprReleaseSpinLock(&(pBSSEntry->Lock));
                    break;
                }
                //
                // Delete any old blob buffer
                //
                if (pBSSEntry->pDot11ProbeFrame != NULL)
                {
                    MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame);
                }

                pBSSEntry->pDot11ProbeFrame = pSavedBeaconPRBuffer;
                pBSSEntry->MaxProbeFrameSize = BeaconPRDataLength;
            }
            
            pBSSEntry->ProbeFrameSize = BeaconPRDataLength;

            // Also save this as the IE blob pointer
            pBSSEntry->InfoElemBlobSize = BeaconPRDataLength - uOffsetOfInfoElemBlob;
            pBSSEntry->pDot11InfoElemBlob = (PUCHAR)pBSSEntry->pDot11ProbeFrame + uOffsetOfInfoElemBlob;

            //
            // Update/Save the beacon information element block
            //
            NdisMoveMemory(
                pBSSEntry->pDot11ProbeFrame,
                pDot11BeaconPRFrame,
                BeaconPRDataLength
                );

        }

#if 0
        if (pBSSEntry->AssocState == dot11_assoc_state_auth_assoc)
        {
            MpTrace(COMP_SCAN, DBG_LOUD, ("Received %d for AP %02X-%02X-%02X-%02X-%02X-%02X \n", 
                    pMgmtPktHeader->FrameControl.Subtype,
                    pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], 
                    pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5]));
        }
#endif

        //
        // Done with our modification of the AP entry
        //
        NdisDprReleaseSpinLock(&(pBSSEntry->Lock));
        
    } while (FALSE);

    return ndisStatus;
Beispiel #11
0
NDIS_STATUS 
HelperPortInsertBSSEntry(
    __in  PMP_HELPER_PORT        HelperPort,
    __in  PMP_RX_MPDU        pFragment,
    __in  PDOT11_BEACON_FRAME pDot11BeaconFrame,
    __in  ULONG           BeaconDataLength
    )
{
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    ULONGLONG           ullHostTimeStamp;
    MP_RW_LOCK_STATE          LockState;
    PMP_BSS_ENTRY      pBSSEntry = NULL;
    PDOT11_MGMT_HEADER  pMgmtPktHeader;
    BOOLEAN             bNewAp = FALSE;
    PMP_BSS_LIST       pDiscoveredBSSList = &(HelperPort->BSSList);

    pMgmtPktHeader = (PDOT11_MGMT_HEADER)MP_RX_MPDU_DATA(pFragment);
    NdisGetCurrentSystemTime((PLARGE_INTEGER)&ullHostTimeStamp);

    //
    // We acquire the write lock as we are adding entries to the list
    //
    MP_ACQUIRE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);

    do
    {
        //
        // Check again if this entry already exists in the list. This is to handle
        // if the AP was added since we first checked (possible if the
        // flush routine was running)
        //
        pBSSEntry = HelperPortFindBSSEntry(
            pDiscoveredBSSList,
            pMgmtPktHeader->SA
            );

        if (pBSSEntry == NULL)
        {
            bNewAp = TRUE;      // New AP
            //
            // We havent found this AP yet, we would add it to the list
            //
            if (pDiscoveredBSSList->NumOfBSSEntries >= pDiscoveredBSSList->MaxNumOfBSSEntries)
            {
                //
                // We need to replace an entry thats in the list
                //
                pBSSEntry = HelperPortExpireBSSEntry(
                    pDiscoveredBSSList,
                    HelperPort->RegInfo->BSSEntryExpireTime,
                    ullHostTimeStamp
                    );

                if (pBSSEntry != NULL)
                {
                    //
                    // Add initial in-use refcount
                    //
                    pBSSEntry->RefCount = 1;
                }
                
                //
                // Dont zero out the AP entry so that we can
                // reuse the info element blob
                //
            }
            else
            {
                //
                // Create a new entry for this AP
                //
                MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, 
                    &pBSSEntry, 
                    sizeof(MP_BSS_ENTRY), 
                    PORT_MEMORY_TAG
                    );
                if (pBSSEntry != NULL)
                {
                    //
                    // Initialize the new entry
                    //
                    NdisZeroMemory(pBSSEntry, sizeof(MP_BSS_ENTRY));
                    
                    pBSSEntry->RefCount = 1; // Add initial in-use refcount
                    NdisAllocateSpinLock(&(pBSSEntry->Lock));
                }
            }

            if (pBSSEntry == NULL)
            {
                MpTrace(COMP_SCAN, DBG_SERIOUS, ("Not enough space to add AP: %02X-%02X-%02X-%02X-%02X-%02X\n",
                    pMgmtPktHeader->SA[0], pMgmtPktHeader->SA[1], pMgmtPktHeader->SA[2], 
                    pMgmtPktHeader->SA[3], pMgmtPktHeader->SA[4], pMgmtPktHeader->SA[5]));
            
                ndisStatus = NDIS_STATUS_RESOURCES;
                break;
            }

            //
            // This Entry is not yet in the list
            //
            
            // We will be updating the beacon & probe response frames
            pBSSEntry->BeaconFrameSize = 0;
            pBSSEntry->ProbeFrameSize = 0;
            
            pBSSEntry->AssocCost = 0;

            NdisMoveMemory(
                pBSSEntry->Dot11BSSID,
                pMgmtPktHeader->BSSID,
                sizeof(DOT11_MAC_ADDRESS)
                );

            NdisMoveMemory(
                pBSSEntry->MacAddress,
                pMgmtPktHeader->SA,
                sizeof(DOT11_MAC_ADDRESS)
                );
        }

        // Update the information in this BSS entry (either new or reused entry)
        ndisStatus = HelperPortUpdateBSSEntry(
            HelperPort, 
            pBSSEntry, 
            pFragment, 
            pDot11BeaconFrame, 
            BeaconDataLength
            );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            break;
        }

        //
        // Add the new BSS to our list
        //
        if (bNewAp)
        {
            MpTrace(COMP_SCAN, DBG_LOUD, ("AP %02X-%02X-%02X-%02X-%02X-%02X at channel: %d (%d)\n", 
                    pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], 
                    pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5],
                    pBSSEntry->Channel, pFragment->Msdu->Channel));

            HelperPortAddBSSEntry(pDiscoveredBSSList, pBSSEntry);
        }

        //
        // Note: If any code is added below here, remember to remove entry
        // from the list
        //
    } while (FALSE);

    MP_RELEASE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        // Free the new entry we may have created
        if ((bNewAp) && (pBSSEntry != NULL))
        {
            if (pBSSEntry->pDot11BeaconFrame != NULL)
            {
                MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame);
                pBSSEntry->pDot11BeaconFrame = NULL;
                pBSSEntry->BeaconFrameSize = 0;
                pBSSEntry->MaxBeaconFrameSize= 0;
            }

            if (pBSSEntry->pDot11ProbeFrame != NULL)
            {
                MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame);
                pBSSEntry->pDot11ProbeFrame = NULL;
                pBSSEntry->ProbeFrameSize = 0;
                pBSSEntry->MaxProbeFrameSize= 0;
            }
                        
            pBSSEntry->pDot11InfoElemBlob = NULL;                
            pBSSEntry->InfoElemBlobSize = 0;
            MP_FREE_MEMORY(pBSSEntry);
        }
    }

    return ndisStatus;