예제 #1
0
NDIS_STATUS
MPSend(
    IN NDIS_HANDLE             MiniportAdapterContext,
    IN PNDIS_PACKET            Packet,
    IN UINT                    Flags
    )
/*++

Routine Description:

    Send Packet handler. Either this or our SendPackets (array) handler is called
    based on which one is enabled in our Miniport Characteristics.

Arguments:

    MiniportAdapterContext    Pointer to the adapter
    Packet                    Packet to send
    Flags                     Unused, passed down below

Return Value:

    Return code from NdisSend

--*/
{
    PADAPT              pAdapt = (PADAPT)MiniportAdapterContext;
    NDIS_STATUS         Status;
	FILTER_STATUS		fStatus;
    PNDIS_PACKET        MyPacket;
    PVOID               MediaSpecificInfo = NULL;
    ULONG               MediaSpecificInfoSize = 0;

    //
    // The driver should fail the send if the virtual miniport is in low 
    // power state
    //
    if (pAdapt->MPDeviceState > NdisDeviceStateD0)
    {
         return NDIS_STATUS_FAILURE;
    }
	//***************************此函数作废!!!!!!!!!!!!!!!************************************
	//KdPrint(("微端口MPSend方法,开始报文分析\n"));
	fStatus = AnalysisPacket(Packet, MODE_SEND);
	//getPacketBuffer(Packet, )
	//fStatus = FILTER_STATUS_PASS;
	if (fStatus == FILTER_STATUS_DROP)
	{
		return NDIS_STATUS_FAILURE;
	}
	else if(fStatus == FILTER_STATUS_MODIFY_REDIRECT)
	{
		// 转发......
		// 修改包中的目标地址,和正常发送一样将包向下发送
		// TODO.
	}

#ifdef NDIS51
    //
    // Use NDIS 5.1 packet stacking:
    //
    {
        PNDIS_PACKET_STACK        pStack;
        BOOLEAN                   Remaining;

        //
        // Packet stacks: Check if we can use the same packet for sending down.
        //

        pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining);
        if (Remaining)
        {
            //
            // We can reuse "Packet".
            //
            // NOTE: if we needed to keep per-packet information in packets
            // sent down, we can use pStack->IMReserved[].
            //
            ASSERT(pStack);
            //
            // If the below miniport is going to low power state, stop sending down any packet.
            //
            NdisAcquireSpinLock(&pAdapt->Lock);
            if (pAdapt->PTDeviceState > NdisDeviceStateD0)
            {
                NdisReleaseSpinLock(&pAdapt->Lock);
                return NDIS_STATUS_FAILURE;
            }
            pAdapt->OutstandingSends++;
            NdisReleaseSpinLock(&pAdapt->Lock);
            NdisSend(&Status,
                     pAdapt->BindingHandle,
                     Packet);

            if (Status != NDIS_STATUS_PENDING)
            {
                ADAPT_DECR_PENDING_SENDS(pAdapt);
            }

            return(Status);
        }
    }
#endif // NDIS51

    //
    // We are either not using packet stacks, or there isn't stack space
    // in the original packet passed down to us. Allocate a new packet
    // to wrap the data with.
    //
    //
    // If the below miniport is going to low power state, stop sending down any packet.
    //
    NdisAcquireSpinLock(&pAdapt->Lock);
    if (pAdapt->PTDeviceState > NdisDeviceStateD0)
    {
        NdisReleaseSpinLock(&pAdapt->Lock);
        return NDIS_STATUS_FAILURE;
    
    }
    pAdapt->OutstandingSends++;
    NdisReleaseSpinLock(&pAdapt->Lock);
    
    NdisAllocatePacket(&Status,
                       &MyPacket,
                       pAdapt->SendPacketPoolHandle);

    if (Status == NDIS_STATUS_SUCCESS)
    {
        PSEND_RSVD            SendRsvd;

        //
        // Save a pointer to the original packet in our reserved
        // area in the new packet. This is needed so that we can
        // get back to the original packet when the new packet's send
        // is completed.
        //
        SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved);
        SendRsvd->OriginalPkt = Packet;

        NdisGetPacketFlags(MyPacket) = Flags;

        //
        // Set up the new packet so that it describes the same
        // data as the original packet.
        //
        NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);
        NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);
#ifdef WIN9X
        //
        // Work around the fact that NDIS does not initialize this
        // to FALSE on Win9x.
        //
        NDIS_PACKET_VALID_COUNTS(MyPacket) = FALSE;
#endif

        //
        // Copy the OOB Offset from the original packet to the new
        // packet.
        //
        NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),
                       NDIS_OOB_DATA_FROM_PACKET(Packet),
                       sizeof(NDIS_PACKET_OOB_DATA));

#ifndef WIN9X
        //
        // Copy the right parts of per packet info into the new packet.
        // This API is not available on Win9x since task offload is
        // not supported on that platform.
        //
        NdisIMCopySendPerPacketInfo(MyPacket, Packet);
#endif
        
        //
        // Copy the Media specific information
        //
        NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,
                                            &MediaSpecificInfo,
                                            &MediaSpecificInfoSize);

        if (MediaSpecificInfo || MediaSpecificInfoSize)
        {
            NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,
                                                MediaSpecificInfo,
                                                MediaSpecificInfoSize);
        }

        NdisSend(&Status,
                 pAdapt->BindingHandle,
                 MyPacket);


        if (Status != NDIS_STATUS_PENDING)
        {
#ifndef WIN9X
            NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
#endif
            NdisFreePacket(MyPacket);
            ADAPT_DECR_PENDING_SENDS(pAdapt);
        }
    }
    else
    {
        ADAPT_DECR_PENDING_SENDS(pAdapt);
        //
        // We are out of packets. Silently drop it. Alternatively we can deal with it:
        //    - By keeping separate send and receive pools
        //    - Dynamically allocate more pools as needed and free them when not needed
        //
    }

    return(Status);
}
예제 #2
0
VOID
MPSendPackets(
    IN NDIS_HANDLE             MiniportAdapterContext,
    IN PPNDIS_PACKET           PacketArray,
    IN UINT                    NumberOfPackets
    )
/*++

Routine Description:

    Send Packet Array handler. Either this or our SendPacket handler is called
    based on which one is enabled in our Miniport Characteristics.

Arguments:

    MiniportAdapterContext     Pointer to our adapter
    PacketArray                Set of packets to send
    NumberOfPackets            Self-explanatory

Return Value:

    None

--*/
{
    PADAPT              pAdapt = (PADAPT)MiniportAdapterContext;
    NDIS_STATUS         Status;
    UINT                i;
    PVOID               MediaSpecificInfo = NULL;
    UINT                MediaSpecificInfoSize = 0;
	FILTER_STATUS		fStatus;
	PUCHAR				pBuffer;
	int					nBufLen;
    

    for (i = 0; i < NumberOfPackets; i++)
    {
        PNDIS_PACKET    Packet, MyPacket;

        Packet = PacketArray[i];

		//KdPrint(("微端口MPSendPackets方法,开始报文分析\n"));
		getMemoryCopyFromPacket(Packet, &pBuffer, &nBufLen);
		KdPrint(("\n==> 微端口MPSendPackets方法,开始分析报文\n"));
		fStatus = analyzeBuffer(pAdapt, pBuffer, &nBufLen, MODE_SEND);
		//fStatus = AnalysisPacket(Packet, FALSE);
		//fStatus = FILTER_STATUS_PASS;
		if (fStatus == FILTER_STATUS_DROP)
		{
			//丢弃
			KdPrint(("<== 微端口MPSendPackets方法,进入FILTER_STATUS_DROP模式\n"));
			freeMemory(pBuffer);
			// 在这个函数中,任何一个被放弃的包,都必须调用NdisMSendComplete。
			NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, NDIS_STATUS_FAILURE);
			continue; 
		}
		/*
		else if (fStatus == FILTER_STATUS_MODIFY_REDIRECT)
		{
			//没有发送时接收转发这种情况
		}
		*/
		else if (fStatus == FILTER_STATUS_MODIFY_SEND)
		{
			//修改+发送
			KdPrint(("<== 微端口MPSendPackets方法,进入FILTER_STATUS_MODIFY_SEND模式\n"));
			MyPacket = createPacketFromMemory_SendPool(pAdapt, pBuffer, nBufLen);
			//freePacketBufferOnly(Packet);

			// The driver should fail the send if the virtual miniport is in low 
			// power state
			//
			if (pAdapt->MPDeviceState > NdisDeviceStateD0)
			{
				NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),
					Packet,
					NDIS_STATUS_FAILURE);
				continue;
			}
			//这里原来有NDIS51的一个简化处理,放在此文件最下面了
			do 
			{
				PSEND_RSVD        SendRsvd;

				NdisAcquireSpinLock(&pAdapt->Lock);
				//
				// If the below miniport is going to low power state, stop sending down any packet.
				//
				if (pAdapt->PTDeviceState > NdisDeviceStateD0)
				{
					NdisReleaseSpinLock(&pAdapt->Lock);
					Status = NDIS_STATUS_FAILURE;
					break;
				}
				pAdapt->OutstandingSends++;
				NdisReleaseSpinLock(&pAdapt->Lock);
				
				//NdisAllocatePacket(&Status,
				//	&MyPacket,
				//	pAdapt->SendPacketPoolHandle);
				
				SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved);
				SendRsvd->OriginalPkt = Packet;
				
				NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
				NdisSetPacketFlags(MyPacket, NDIS_FLAGS_RESERVED4); //我们做个标记
				
				//现在我们自己构造buffer,所以不需要用原packet的buffer了
				//NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);
				//NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);
				
				//
				// Copy the OOB data from the original packet to the new
				// packet.
				//
				NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),
					NDIS_OOB_DATA_FROM_PACKET(Packet),
					sizeof(NDIS_PACKET_OOB_DATA));
				//
				// Copy relevant parts of the per packet info into the new packet
				//
				NdisIMCopySendPerPacketInfo(MyPacket, Packet);
				
				//
				// Copy the Media specific information
				//
				NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,
					&MediaSpecificInfo,
					&MediaSpecificInfoSize);
				
				if (MediaSpecificInfo || MediaSpecificInfoSize)
				{
					NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,
						MediaSpecificInfo,
						MediaSpecificInfoSize);
				}
				
				NdisSend(&Status,
					pAdapt->BindingHandle,
					MyPacket);
				
				if (Status != NDIS_STATUS_PENDING)
				{
					NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
					//NdisFreePacket(MyPacket);
					freePacketBufferAndMemory(MyPacket);
					ADAPT_DECR_PENDING_SENDS(pAdapt);
				}
			}
			while (FALSE);
			
			if (Status != NDIS_STATUS_PENDING)
			{
				NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),
					Packet,
					Status);
			}
		}
		else //FILTER_STATUS_PASS
		{
			//按PASS处理
			KdPrint(("<== 微端口MPSendPackets方法,进入FILTER_STATUS_PASS模式\n"));
			freeMemory(pBuffer);
			//
			// The driver should fail the send if the virtual miniport is in low 
			// power state
			//
			if (pAdapt->MPDeviceState > NdisDeviceStateD0)
			{
				NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),
								Packet,
								NDIS_STATUS_FAILURE);
				continue;
			}
			//这里原来有NDIS51的一个简化处理,放在此文件最下面了
			do 
			{
				NdisAcquireSpinLock(&pAdapt->Lock);
				//
				// If the below miniport is going to low power state, stop sending down any packet.
				//
				if (pAdapt->PTDeviceState > NdisDeviceStateD0)
				{
					NdisReleaseSpinLock(&pAdapt->Lock);
					Status = NDIS_STATUS_FAILURE;
					break;
				}
				pAdapt->OutstandingSends++;
				NdisReleaseSpinLock(&pAdapt->Lock);
            
				NdisAllocatePacket(&Status,
								   &MyPacket,
								   pAdapt->SendPacketPoolHandle);

				if (Status == NDIS_STATUS_SUCCESS)
				{
					PSEND_RSVD        SendRsvd;

					SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved);
					SendRsvd->OriginalPkt = Packet;

					NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
					NdisClearPacketFlags(MyPacket, NDIS_FLAGS_RESERVED4); //防止和上面的包混淆

					NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);
					NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);

					//
					// Copy the OOB data from the original packet to the new
					// packet.
					//
					NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),
								NDIS_OOB_DATA_FROM_PACKET(Packet),
								sizeof(NDIS_PACKET_OOB_DATA));
					//
					// Copy relevant parts of the per packet info into the new packet
					//
					NdisIMCopySendPerPacketInfo(MyPacket, Packet);

					//
					// Copy the Media specific information
					//
					NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,
														&MediaSpecificInfo,
														&MediaSpecificInfoSize);

					if (MediaSpecificInfo || MediaSpecificInfoSize)
					{
						NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,
															MediaSpecificInfo,
															MediaSpecificInfoSize);
					}

					NdisSend(&Status,
							 pAdapt->BindingHandle,
							 MyPacket);

					if (Status != NDIS_STATUS_PENDING)
					{
						NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
						NdisFreePacket(MyPacket);
						ADAPT_DECR_PENDING_SENDS(pAdapt);
					}
				}
				else
				{
					//
					// The driver cannot allocate a packet.
					// 
					ADAPT_DECR_PENDING_SENDS(pAdapt);
				}
			}
			while (FALSE);

			if (Status != NDIS_STATUS_PENDING)
			{
				NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),
								  Packet,
								  Status);
			}
		}
    }
}
예제 #3
0
VOID
ndisprotServiceReads(
    IN PNDISPROT_OPEN_CONTEXT        pOpenContext
    )
/*++

Routine Description:

    Utility routine to copy received data into user buffers and
    complete READ IRPs.

Arguments:

    pOpenContext - pointer to open context

Return Value:

    None

--*/
{
    PIRP                pIrp = NULL;
    PLIST_ENTRY         pIrpEntry;
    PNDIS_PACKET        pRcvPacket;
    PLIST_ENTRY         pRcvPacketEntry;
    PUCHAR              pSrc, pDst;
    ULONG               BytesRemaining; // at pDst
    PNDIS_BUFFER        pNdisBuffer;
    ULONG               BytesAvailable;
    BOOLEAN             FoundPendingIrp;

    DEBUGP(DL_VERY_LOUD, ("ServiceReads: open %p/%x\n",
            pOpenContext, pOpenContext->Flags));

    NPROT_REF_OPEN(pOpenContext);  // temp ref - service reads

    NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);

    while (!NPROT_IS_LIST_EMPTY(&pOpenContext->PendedReads) &&
           !NPROT_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue))
    {
        FoundPendingIrp = FALSE;
        //
        //  Get the first pended Read IRP
        //
        pIrpEntry = pOpenContext->PendedReads.Flink;
        while (pIrpEntry != &pOpenContext->PendedReads)
        {
            pIrp = CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry);

            //
            //  Check to see if it is being cancelled.
            //
            if (IoSetCancelRoutine(pIrp, NULL))
            {
                //
                //  It isn't being cancelled, and can't be cancelled henceforth.
                //
                NPROT_REMOVE_ENTRY_LIST(pIrpEntry);
                FoundPendingIrp = TRUE;
                break;

                //
                //  NOTE: we decrement PendedReadCount way below in the
                //  while loop, to avoid letting through a thread trying
                //  to unbind.
                //
            }
            else
            {
                //
                //  The IRP is being cancelled; let the cancel routine handle it.
                //
                DEBUGP(DL_INFO, ("ServiceReads: open %p, skipping cancelled IRP %p\n",
                        pOpenContext, pIrp));
                pIrpEntry = pIrpEntry->Flink;

            }
        }
        //
        // If no pending IRP
        //
        if (FoundPendingIrp == FALSE)
        {
            break;
        }
        //
        //  Get the first queued receive packet
        //
        pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink;
        NPROT_REMOVE_ENTRY_LIST(pRcvPacketEntry);

        pOpenContext->RecvPktCount --;

        NPROT_RELEASE_LOCK(&pOpenContext->Lock);

        NPROT_DEREF_OPEN(pOpenContext);  // Service: dequeue rcv packet

        pRcvPacket = NPROT_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);

        //
        //  Copy as much data as possible from the receive packet to
        //  the IRP MDL.
        //
        pDst = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
        __analysis_assume(pDst);
        NPROT_ASSERT(pDst != NULL);  // since it was already mapped
        BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress);

        pNdisBuffer = NDIS_PACKET_FIRST_NDIS_BUFFER(pRcvPacket);

        //
        // Copy the data in the received packet into the buffer provided by the client.
        // If the length of the receive packet is greater than length of the given buffer, 
        // we just copy as many bytes as we can. Once the buffer is full, we just discard 
        // the rest of the data, and complete the IRP sucessfully even we only did a partial copy.
        // 
        while (BytesRemaining && (pNdisBuffer != NULL))
        {
#ifndef WIN9X
            NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority);

            if (pSrc == NULL) 
            {
                DEBUGP(DL_FATAL,
                    ("ServiceReads: Open %p, QueryBuffer failed for buffer %p\n",
                            pOpenContext, pNdisBuffer));
                break;
            }
#else
            NdisQueryBuffer(pNdisBuffer, &pSrc, &BytesAvailable);
#endif

            if (BytesAvailable)
            {
                ULONG       BytesToCopy = MIN(BytesAvailable, BytesRemaining);

                NPROT_COPY_MEM(pDst, pSrc, BytesToCopy);
                BytesRemaining -= BytesToCopy;
                pDst += BytesToCopy;
            }

            NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer);
        }

        //
        //  Complete the IRP.
        //
        pIrp->IoStatus.Status = STATUS_SUCCESS;
        pIrp->IoStatus.Information = MmGetMdlByteCount(pIrp->MdlAddress) - BytesRemaining;

        DEBUGP(DL_INFO, ("ServiceReads: Open %p, IRP %p completed with %d bytes\n",
            pOpenContext, pIrp, pIrp->IoStatus.Information));

        IoCompleteRequest(pIrp, IO_NO_INCREMENT);

        //
        //  Free up the receive packet - back to the miniport if it
        //  belongs to it, else reclaim it (local copy).
        //
        if (NdisGetPoolFromPacket(pRcvPacket) != pOpenContext->RecvPacketPool)
        {
            NdisReturnPackets(&pRcvPacket, 1);
        }
        else
        {
            ndisprotFreeReceivePacket(pOpenContext, pRcvPacket);
        }

        NPROT_DEREF_OPEN(pOpenContext);    // took out pended Read

        NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
        pOpenContext->PendedReadCount--;

    }

    NPROT_RELEASE_LOCK(&pOpenContext->Lock);

    NPROT_DEREF_OPEN(pOpenContext);    // temp ref - service reads
}