Example #1
0
// Used on PortReturn to free the RX_PACKETs 
// allocated via BasePortTranslateRxPacketsToRxNBLs 
VOID
BasePortFreeTranslatedRxNBLs(
    __in  PMP_PORT                Port,
    __out PNET_BUFFER_LIST        NetBufferLists
    )
{
    PNET_BUFFER_LIST            currentNetBufferList, nextNetBufferList;
    PMDL                        currentMdl, nextMdl;

    UNREFERENCED_PARAMETER(Port);

    currentNetBufferList = NetBufferLists;
    while (currentNetBufferList != NULL)
    {
        nextNetBufferList = NET_BUFFER_LIST_NEXT_NBL(currentNetBufferList);
        NET_BUFFER_LIST_NEXT_NBL(currentNetBufferList) = NULL;

        currentMdl = NET_BUFFER_CURRENT_MDL(NET_BUFFER_LIST_FIRST_NB(currentNetBufferList));
        while (currentMdl != NULL)
        {
            nextMdl = NDIS_MDL_LINKAGE(currentMdl);

            // Free the MDL
            NdisFreeMdl(currentMdl);

            currentMdl = nextMdl;
        }

        // Free the NET_BUFFER and NET_BUFFER_LIST
        NdisFreeNetBufferList(currentNetBufferList);
        
        currentNetBufferList = nextNetBufferList;
    }
}
BOOLEAN ParaNdis_BindRxBufferToPacket(
    PARANDIS_ADAPTER *pContext,
    pRxNetDescriptor p)
{
    ULONG i;
    PMDL *NextMdlLinkage = &p->Holder;

    for(i = PARANDIS_FIRST_RX_DATA_PAGE; i < p->BufferSGLength; i++)
    {
        *NextMdlLinkage = NdisAllocateMdl(
            pContext->MiniportHandle,
            p->PhysicalPages[i].Virtual,
            p->PhysicalPages[i].size);
        if(*NextMdlLinkage == NULL) goto error_exit;

        NextMdlLinkage = &(NDIS_MDL_LINKAGE(*NextMdlLinkage));
    }
    *NextMdlLinkage = NULL;

    return TRUE;

error_exit:

    ParaNdis_UnbindRxBufferFromPacket(p);
    return FALSE;
}
void ParaNdis_UnbindRxBufferFromPacket(
    pRxNetDescriptor p)
{
    PMDL NextMdlLinkage = p->Holder;

    while(NextMdlLinkage != NULL)
    {
        PMDL pThisMDL = NextMdlLinkage;
        NextMdlLinkage = NDIS_MDL_LINKAGE(pThisMDL);

        NdisAdjustMdlLength(pThisMDL, PAGE_SIZE);
        NdisFreeMdl(pThisMDL);
    }
}
void ParaNdis_UnbindRxBufferFromPacket(
    pRxNetDescriptor p)
{
    PMDL NextMdlLinkage = p->Holder;
    ULONG ulPageDescIndex = PARANDIS_FIRST_RX_DATA_PAGE;

    while(NextMdlLinkage != NULL)
    {
        PMDL pThisMDL = NextMdlLinkage;
        NextMdlLinkage = NDIS_MDL_LINKAGE(pThisMDL);

        NdisAdjustMdlLength(pThisMDL, p->PhysicalPages[ulPageDescIndex].size);
        NdisFreeMdl(pThisMDL);
        ulPageDescIndex++;
    }
}
static
void ParaNdis_AdjustRxBufferHolderLength(
    pRxNetDescriptor p,
    ULONG ulDataOffset)
{
    PMDL NextMdlLinkage = p->Holder;
    ULONG ulBytesLeft = p->PacketInfo.dataLength + ulDataOffset;

    while(NextMdlLinkage != NULL)
    {
        ULONG ulThisMdlBytes = min(PAGE_SIZE, ulBytesLeft);
        NdisAdjustMdlLength(NextMdlLinkage, ulThisMdlBytes);
        ulBytesLeft -= ulThisMdlBytes;
        NextMdlLinkage = NDIS_MDL_LINKAGE(NextMdlLinkage);
    }
    NETKVM_ASSERT(ulBytesLeft == 0);
}
static
void ParaNdis_AdjustRxBufferHolderLength(
    pRxNetDescriptor p,
    ULONG ulDataOffset)
{
    PMDL NextMdlLinkage = p->Holder;
    ULONG ulBytesLeft = p->PacketInfo.dataLength + ulDataOffset;
    ULONG ulPageDescIndex = PARANDIS_FIRST_RX_DATA_PAGE;

    while(NextMdlLinkage != NULL)
    {
        ULONG ulThisMdlBytes = min(p->PhysicalPages[ulPageDescIndex].size, ulBytesLeft);
        NdisAdjustMdlLength(NextMdlLinkage, ulThisMdlBytes);
        ulBytesLeft -= ulThisMdlBytes;
        NextMdlLinkage = NDIS_MDL_LINKAGE(NextMdlLinkage);
        ulPageDescIndex++;
    }
    NETKVM_ASSERT(ulBytesLeft == 0);
}
Example #7
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;
}
Example #8
0
NDIS_STATUS
CopyBytesFromNetBuffer(  PNET_BUFFER_KK        NetBuffer,  PULONG             cbDest, PVOID Dest)
/*++

Routine Description:

    Copies the first cbDest bytes from a NET_BUFFER. In order to show how the various data structures fit together, this 
    implementation copies the data by iterating through the MDLs for the NET_BUFFER. The NdisGetDataBuffer API also allows you
    to copy a contiguous block of data from a NET_BUFFER. 

    Runs at IRQL <= DISPATCH_LEVEL.

Arguments:

    NetBuffer                   The NB to read
    cbDest                      On input, the number of bytes in the buffer Dest
                                On return, the number of bytes actually copied
    Dest                        On return, receives the first cbDest bytes of
                                the network frame in NetBuffer

Return Value:

    None.

Notes:

    If the output buffer is larger than the NB's frame size, *cbDest will
    contain the number of bytes in the frame size.

    If the output buffer is smaller than the NB's frame size, only the first
    *cbDest bytes will be copied (the buffer will receive a truncated copy of
    the frame).

--*/
{
    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
    //
    // Start copy from current MDL
    //
    PMDL CurrentMdl = NET_BUFFER_CURRENT_MDL(NetBuffer);
    //
    // Data on current MDL may be offset from start of MDL
    //
    ULONG DestOffset = 0;
    while (DestOffset < *cbDest && CurrentMdl)
    {
        //
        // Map MDL memory to System Address Space. LowPagePriority means mapping may fail if 
        // system is low on memory resources. 
        //
        PUCHAR SrcMemory = MmGetSystemAddressForMdlSafe(CurrentMdl, LowPagePriority);
        ULONG Length = MmGetMdlByteCount(CurrentMdl);
        if (!SrcMemory)
        {
            Status = NDIS_STATUS_RESOURCES;
            break;
        }

        if(DestOffset==0)
        {
            //
            // The first MDL segment should be accessed from the current MDL offset
            //
            ULONG MdlOffset = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
            SrcMemory += MdlOffset;
            Length -= MdlOffset;
        }

        Length = min(Length, *cbDest-DestOffset);

        //
        // Copy Memory
        //
        NdisMoveMemory((PUCHAR)Dest+DestOffset, SrcMemory, Length);
        DestOffset += Length;

        //
        // Get next MDL (if any available) 
        //
        CurrentMdl = NDIS_MDL_LINKAGE(CurrentMdl);
    }

    if(Status == NDIS_STATUS_SUCCESS)
    {
        *cbDest = DestOffset;
    }

    return Status;
}
Example #9
0
NTSTATUS
NdisprotWrite(
    IN PDEVICE_OBJECT       pDeviceObject,
    IN PIRP                 pIrp
    )
/*++

Routine Description:

    Dispatch routine to handle IRP_MJ_WRITE. 

Arguments:

    pDeviceObject - pointer to our device object
    pIrp - Pointer to request packet

Return Value:

    NT status code.

--*/
{
    PIO_STACK_LOCATION      pIrpSp;
    ULONG                   DataLength;
    NTSTATUS                NtStatus;
    PNDISPROT_OPEN_CONTEXT  pOpenContext;
    PNET_BUFFER_LIST        pNetBufferList;
    PMDL                    pMdl;
    NDISPROT_ETH_HEADER UNALIGNED *pEthHeader;
    PVOID                   CancelId;
    ULONG                   SendFlags = 0;

    UNREFERENCED_PARAMETER(pDeviceObject);

    pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
    pOpenContext = pIrpSp->FileObject->FsContext;


    do
    {
        if (pOpenContext == NULL)
        {
            DEBUGP(DL_WARN, ("Write: FileObject %p not yet associated with a device\n",
                pIrpSp->FileObject));
            NtStatus = STATUS_INVALID_HANDLE;
            break;
        }
               
        NPROT_STRUCT_ASSERT(pOpenContext, oc);

        if (pIrp->MdlAddress == NULL)
        {
            DEBUGP(DL_FATAL, ("Write: NULL MDL address on IRP %p\n", pIrp));
            NtStatus = STATUS_INVALID_PARAMETER;
            break;
        }

        //
        // Try to get a virtual address for the MDL.
        //
        
        pEthHeader = NULL;
        NdisQueryMdl(pIrp->MdlAddress, &pEthHeader, &DataLength, NormalPagePriority);

        if (pEthHeader == NULL)
        {
            DEBUGP(DL_FATAL, ("Write: MmGetSystemAddr failed for"
                    " IRP %p, MDL %p\n",
                    pIrp, pIrp->MdlAddress));
            NtStatus = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        //
        // Sanity-check the length.
        //
        if (DataLength < sizeof(NDISPROT_ETH_HEADER))
        {
            DEBUGP(DL_WARN, ("Write: too small to be a valid packet (%d bytes)\n",
                DataLength));
            NtStatus = STATUS_BUFFER_TOO_SMALL;
            break;
        }

        if (DataLength > (pOpenContext->MaxFrameSize + sizeof(NDISPROT_ETH_HEADER)))
        {
            DEBUGP(DL_WARN, ("Write: Open %p: data length (%d)"
                    " larger than max frame size (%d)\n",
                    pOpenContext, DataLength, pOpenContext->MaxFrameSize));

            NtStatus = STATUS_INVALID_BUFFER_SIZE;
            break;
        }

        if (pEthHeader->EthType != Globals.EthType)
        {
            DEBUGP(DL_WARN, ("Write: Failing send with EthType %x\n",
                pEthHeader->EthType));
            NtStatus = STATUS_INVALID_PARAMETER;
            break;
        }
       
        if (!NPROT_MEM_CMP(pEthHeader->SrcAddr, pOpenContext->CurrentAddress, NPROT_MAC_ADDR_LEN))
        {
            DEBUGP(DL_WARN, ("Write: Failing with invalid Source address"));
            NtStatus = STATUS_INVALID_PARAMETER;
            break;
        }
        

        NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE);

        if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NPROTO_BIND_FLAGS, NPROTO_BIND_ACTIVE))
        {
            NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE);

            DEBUGP(DL_FATAL, ("Write: Open %p is not bound"
            " or in low power state\n", pOpenContext));

            NtStatus = STATUS_INVALID_HANDLE;
            break;
        } 

        if (pOpenContext->State != NdisprotRunning  ||
            pOpenContext->PowerState != NetDeviceStateD0)
        {
            NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE);
            
            DEBUGP(DL_INFO, ("Device is not ready.\n"));
            NtStatus = STATUS_UNSUCCESSFUL;
            break;
        }


        pMdl = pIrp->MdlAddress;
        NPROT_ASSERT(pOpenContext->SendNetBufferListPool != NULL);
        pNetBufferList = NdisAllocateNetBufferAndNetBufferList(
                                pOpenContext->SendNetBufferListPool,
                                sizeof(NPROT_SEND_NETBUFLIST_RSVD), //Request control offset delta
                                0,           // back fill size
                                pMdl,
                                0,          // Data offset
                                DataLength);
        
        if (pNetBufferList == NULL)
        {
            NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE);
            
            DEBUGP(DL_FATAL, ("Write: open %p, failed to alloc send net buffer list\n",
                    pOpenContext));
            NtStatus = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }
        pOpenContext->PendedSendCount++;

        NPROT_REF_OPEN(pOpenContext);  // pended send

        IoMarkIrpPending(pIrp);

        //
        //  Initialize the NetBufferList ref count. This NetBufferList will be freed
        //  when this count goes to zero.
        //
        NPROT_SEND_NBL_RSVD(pNetBufferList)->RefCount = 1;

        //
        //  We set up a cancel ID on each send NetBufferList (which maps to a Write IRP), 
        //  and save the NetBufferList pointer in the IRP. If the IRP gets cancelled, we use
        //  NdisCancelSendNetBufferLists() to cancel the NetBufferList.
        //
       
        CancelId = NPROT_GET_NEXT_CANCEL_ID();
        NDIS_SET_NET_BUFFER_LIST_CANCEL_ID(pNetBufferList, CancelId);
        pIrp->Tail.Overlay.DriverContext[0] = (PVOID)pOpenContext;
        pIrp->Tail.Overlay.DriverContext[1] = (PVOID)pNetBufferList;
        pIrp->Tail.Overlay.DriverContext[2] = CancelId;

        NPROT_INSERT_TAIL_LIST(&pOpenContext->PendedWrites, &pIrp->Tail.Overlay.ListEntry);

        IoSetCancelRoutine(pIrp, NdisprotCancelWrite);


        NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE);

        //
        //  Set a back pointer from the packet to the IRP.
        //
        NPROT_IRP_FROM_SEND_NBL(pNetBufferList) = pIrp;

        NtStatus = STATUS_PENDING;


#if SEND_DBG
        {
            PUCHAR      pData;

            pData = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority);
            NPROT_ASSERT(pEthHeader == pData);

            DEBUGP(DL_VERY_LOUD, 
                ("Write: MDL %p, MdlFlags %x, SystemAddr %p, %d bytes\n",
                    pIrp->MdlAddress, pIrp->MdlAddress->MdlFlags, pData, DataLength));

            DEBUGPDUMP(DL_VERY_LOUD, pData, MIN(DataLength, 48));
        }
#endif // SEND_DBG

        pNetBufferList->SourceHandle = pOpenContext->BindingHandle;
        ASSERT (NDIS_MDL_LINKAGE(pMdl) == NULL);
        
        SendFlags |= NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK;

        NdisSendNetBufferLists(        
                        pOpenContext->BindingHandle,
                        pNetBufferList,
                        NDIS_DEFAULT_PORT_NUMBER,
                        SendFlags);

    }
    while (FALSE);

    if (NtStatus != STATUS_PENDING)
    {
        pIrp->IoStatus.Status = NtStatus;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    }

    return (NtStatus);
}