Esempio n. 1
0
static VOID
OvsDumpNetBuffer(PNET_BUFFER nb)
{
    OVS_LOG_INFO("NET_BUFFER: %p, ChecksumBias: %d Handle: %p, MDLChain: %p "
                 "CurrMDL: %p, CurrOffset: %d, DataLen: %d, Offset: %d",
                 nb,
                 NET_BUFFER_CHECKSUM_BIAS(nb), nb->NdisPoolHandle,
                 NET_BUFFER_FIRST_MDL(nb),
                 NET_BUFFER_CURRENT_MDL(nb),
                 NET_BUFFER_CURRENT_MDL_OFFSET(nb),
                 NET_BUFFER_DATA_LENGTH(nb),
                 NET_BUFFER_DATA_OFFSET(nb));
    OvsDumpMDLChain(NET_BUFFER_FIRST_MDL(nb));
}
Esempio n. 2
0
static void
shared_free_pkt(ND_PKT* p)
{
#ifndef NDIS60
	PNDIS_BUFFER b;

	NdisQueryPacket(p, NULL, NULL, &b, NULL);
	ASSERT(b);
	NdisFreeBuffer(b);
	NdisFreePacket(p);
#else /* NDIS60 */
	PNET_BUFFER nb;
	PMDL b;

	nb = NET_BUFFER_LIST_FIRST_NB(p);
	b = NET_BUFFER_FIRST_MDL(nb);
	ASSERT(b);
	NdisFreeMdl(b);
	NdisFreeNetBufferList(p);
#endif /* NDIS60 */
}
Esempio n. 3
0
/*
 * --------------------------------------------------------------------------
 * FixSegmentHeader
 *
 *    Fix IP length, IP checksum, TCP sequence number and TCP checksum
 *    in the segment.
 * --------------------------------------------------------------------------
 */
static NDIS_STATUS
FixSegmentHeader(PNET_BUFFER nb, UINT16 segmentSize, UINT32 seqNumber)
{
    EthHdr *dstEth;
    IPHdr *dstIP;
    TCPHdr *dstTCP;
    PMDL mdl;
    PUINT8 bufferStart;

    mdl = NET_BUFFER_FIRST_MDL(nb);

    bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(mdl, LowPagePriority);
    if (!bufferStart) {
        return NDIS_STATUS_RESOURCES;
    }
    dstEth = (EthHdr *)(bufferStart + NET_BUFFER_CURRENT_MDL_OFFSET(nb));
    ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)
            >= sizeof(EthHdr) + sizeof(IPHdr) + sizeof(TCPHdr));
    dstIP = (IPHdr *)((PCHAR)dstEth + sizeof *dstEth);
    dstTCP = (TCPHdr *)((PCHAR)dstIP + dstIP->ihl * 4);
    ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)
            >= sizeof(EthHdr) + dstIP->ihl * 4 + TCP_HDR_LEN(dstTCP));

    /* Fix IP length and checksum */
    ASSERT(dstIP->protocol == IPPROTO_TCP);
    dstIP->tot_len = htons(segmentSize + dstIP->ihl * 4 + TCP_HDR_LEN(dstTCP));
    dstIP->check = 0;
    dstIP->check = IPChecksum((UINT8 *)dstIP, dstIP->ihl * 4, 0);

    /* Fix TCP checksum */
    dstTCP->seq = htonl(seqNumber);
    dstTCP->check =
        IPPseudoChecksum((UINT32 *)&dstIP->saddr,
                         (UINT32 *)&dstIP->daddr,
                         IPPROTO_TCP, segmentSize + TCP_HDR_LEN(dstTCP));
    dstTCP->check = CalculateChecksumNB(nb,
            (UINT16)(NET_BUFFER_DATA_LENGTH(nb) - sizeof *dstEth - dstIP->ihl * 4),
            sizeof *dstEth + dstIP->ihl * 4);
    return STATUS_SUCCESS;
}
Esempio n. 4
0
VOID FreeNetBufferList(PNET_BUFFER_LIST_KK pNetBufferList)
{
	PMDL                pMdl;
	UINT                TotalLength;
	UINT                BufferLength;
	PUCHAR              pCopyData = NULL;
	ULONG               ReturnFlags = 0;

	if (pNetBufferList==NULL)
	{
		return ;
	}
	do
	{
		pMdl = NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(pNetBufferList));
		TotalLength = NET_BUFFER_DATA_LENGTH(NET_BUFFER_LIST_FIRST_NB(pNetBufferList));

		if (pMdl==NULL)
		{
			kprintf("FreeNetBufferList()pMdl==Null\n");
			break;
		}

		NdisQueryMdl(
			pMdl,
			(PVOID *)&pCopyData,
			&BufferLength,
			NormalPagePriority);

		if (BufferLength!=TotalLength)
		{
			kprintf("FreeNetBufferList() NPROT_ASSERT(BufferLength == TotalLength)\n");
			break;
		}

		if (pCopyData==NULL)
		{
			kprintf("FreeNetBufferList() pCopyData==Null\n");
			break;
		}

		if (1)
		{

			if (g_pfnNdisFreeNetBufferList==0)
			{
				break;
			}
			_asm 
			{
				push pNetBufferList
				call g_pfnNdisFreeNetBufferList
			}
		}

		//NdisFreeNetBufferList(pNetBufferList);

		IoFreeMdl(pMdl);

		kfree(pCopyData);
		break;


	}
	while (FALSE);


}
Esempio n. 5
0
VOID
tapCompleteIrpAndFreeReceiveNetBufferList(
    __in  PTAP_ADAPTER_CONTEXT  Adapter,
    __in  PNET_BUFFER_LIST      NetBufferList,  // Only one NB here...
    __in  NTSTATUS              IoCompletionStatus
    )
{
    PIRP    irp;
    ULONG   frameType, netBufferCount, byteCount;
    LONG    nblCount;

    // Fetch NB frame type.
    frameType = tapGetNetBufferFrameType(NET_BUFFER_LIST_FIRST_NB(NetBufferList));

    // Fetch statistics for all NBs linked to the NB.
    netBufferCount = tapGetNetBufferCountsFromNetBufferList(
                        NetBufferList,
                        &byteCount
                        );

    // Update statistics by frame type
    if(IoCompletionStatus == STATUS_SUCCESS)
    {
        switch(frameType)
        {
        case NDIS_PACKET_TYPE_DIRECTED:
            Adapter->FramesRxDirected += netBufferCount;
            Adapter->BytesRxDirected += byteCount;
            break;

        case NDIS_PACKET_TYPE_BROADCAST:
            Adapter->FramesRxBroadcast += netBufferCount;
            Adapter->BytesRxBroadcast += byteCount;
            break;

        case NDIS_PACKET_TYPE_MULTICAST:
            Adapter->FramesRxMulticast += netBufferCount;
            Adapter->BytesRxMulticast += byteCount;
            break;

        default:
            ASSERT(FALSE);
            break;
        }
    }

    //
    // Handle P2P Packet
    // -----------------
    // Free MDL allocated for P2P Ethernet header.
    //
    if(TAP_RX_NBL_FLAG_TEST(NetBufferList,TAP_RX_NBL_FLAGS_IS_P2P))
    {
        PNET_BUFFER     netBuffer;
        PMDL            mdl;

        netBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
        mdl = NET_BUFFER_FIRST_MDL(netBuffer);
        mdl->Next = NULL;

        NdisFreeMdl(mdl);
    }

    //
    // Handle Injected Packet
    // -----------------------
    // Free MDL and data buffer allocated for injected packet.
    //
    if(TAP_RX_NBL_FLAG_TEST(NetBufferList,TAP_RX_NBL_FLAGS_IS_INJECTED))
    {
        PNET_BUFFER     netBuffer;
        PMDL            mdl;
        PUCHAR          injectBuffer;

        netBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
        mdl = NET_BUFFER_FIRST_MDL(netBuffer);

        injectBuffer = (PUCHAR )MmGetSystemAddressForMdlSafe(mdl,NormalPagePriority);

        if(injectBuffer)
        {
            NdisFreeMemory(injectBuffer,0,0);
        }

        NdisFreeMdl(mdl);
    }

    //
    // Complete the IRP
    //
    irp = (PIRP )NetBufferList->MiniportReserved[0];

    if(irp)
    {
        irp->IoStatus.Status = IoCompletionStatus;
        IoCompleteRequest(irp, IO_NO_INCREMENT);
    }

    // Decrement in-flight receive NBL count.
    nblCount = NdisInterlockedDecrement(&Adapter->ReceiveNblInFlightCount);
    ASSERT(nblCount >= 0 );
    if (0 == nblCount)
    {
        NdisSetEvent(&Adapter->ReceiveNblInFlightCountZeroEvent);
    }

    // Free the NBL
    NdisFreeNetBufferList(NetBufferList);
}
Esempio n. 6
0
/*
 * --------------------------------------------------------------------------
 * OvsFullCopyNBL --
 *
 *    Copy the NBL to a new NBL including data.
 *
 * Notes:
 *     The NBL can have multiple NBs, but the final result is one NBL.
 * --------------------------------------------------------------------------
 */
PNET_BUFFER_LIST
OvsFullCopyNBL(PVOID ovsContext,
               PNET_BUFFER_LIST nbl,
               UINT32 headRoom,
               BOOLEAN copyNblInfo)
{
    POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;
    POVS_NBL_POOL ovsPool = &context->ovsPool;
    PNET_BUFFER_LIST newNbl;
    PNET_BUFFER nb, newNb, firstNb = NULL, prevNb = NULL;
    POVS_BUFFER_CONTEXT dstCtx, srcCtx;
    PMDL mdl;
    NDIS_STATUS status;
    UINT32 size, totalSize;
    ULONG copiedSize;
    UINT16 flags;
    PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO dstInfo;

    srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);
    if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) {
        OVS_LOG_INFO("src nbl must have ctx initialized");
        ASSERT(srcCtx && srcCtx->magic == OVS_CTX_MAGIC);
        return NULL;
    }

    nb = NET_BUFFER_LIST_FIRST_NB(nbl);

    if (NET_BUFFER_NEXT_NB(nb) == NULL) {
        return OvsCopySinglePacketNBL(context, nbl, nb, headRoom, copyNblInfo);
    }

    newNbl = NdisAllocateNetBufferList(ovsPool->nblOnlyPool,
                                       (UINT16)sizeof (OVS_BUFFER_CONTEXT),
                                       (UINT16)OVS_DEFAULT_NBL_CONTEXT_FILL);
    if (newNbl == NULL) {
        return NULL;
    }

    while (nb) {
        size = NET_BUFFER_DATA_LENGTH(nb);
        totalSize = MEM_ALIGN_SIZE(size + headRoom);
        mdl = OvsAllocateMDLAndData(ovsPool->ndisHandle, totalSize);

        if (mdl == NULL) {
            goto nblcopy_error;
        }
        newNb = NdisAllocateNetBuffer(ovsPool->nbPool, mdl, totalSize, 0);
        if (newNb == NULL) {
            OvsFreeMDLAndData(mdl);
            goto nblcopy_error;
        }
        if (firstNb == NULL) {
            firstNb = newNb;
        } else {
            NET_BUFFER_NEXT_NB(prevNb) = newNb;
        }
        prevNb = newNb;
#ifdef DBG
        InterlockedIncrement((LONG volatile *)&ovsPool->nbCount);
#endif
        status = NdisRetreatNetBufferDataStart(newNb, size, 0, NULL);
        ASSERT(status == NDIS_STATUS_SUCCESS);

        status = NdisCopyFromNetBufferToNetBuffer(newNb, 0, size, nb, 0,
                                                  &copiedSize);
        if (status != NDIS_STATUS_SUCCESS || size != copiedSize) {
            goto nblcopy_error;
        }

        nb = NET_BUFFER_NEXT_NB(nb);
    }

    NET_BUFFER_LIST_FIRST_NB(newNbl) = firstNb;

    newNbl->SourceHandle = ovsPool->ndisHandle;
    status = context->NdisSwitchHandlers.
         AllocateNetBufferListForwardingContext(ovsPool->ndisContext, newNbl);

    if (status != NDIS_STATUS_SUCCESS) {
        goto nblcopy_error;
    }

    status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, 0, copyNblInfo);
    if (status != NDIS_STATUS_SUCCESS) {
        goto nblcopy_error;
    }

    dstInfo = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl);
    dstInfo->IsPacketDataSafe = TRUE;

    dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl);

    flags = srcCtx->flags & (OVS_BUFFER_RECV_BUFFER | OVS_BUFFER_SEND_BUFFER);

    flags |= OVS_BUFFER_PRIVATE_MDL | OVS_BUFFER_PRIVATE_DATA |
             OVS_BUFFER_PRIVATE_NET_BUFFER | OVS_BUFFER_FROM_NBL_ONLY_POOL |
             OVS_BUFFER_PRIVATE_FORWARD_CONTEXT;

    OvsInitNBLContext(dstCtx, flags, NET_BUFFER_DATA_LENGTH(firstNb),
                      OVS_DEFAULT_PORT_NO);

#ifdef DBG
    OvsDumpNetBufferList(nbl);
    OvsDumpForwardingDetails(nbl);
    InterlockedIncrement((LONG volatile *)&ovsPool->nblOnlyCount);
#endif
    OVS_LOG_LOUD("newNbl: %p", newNbl);
    return newNbl;

nblcopy_error:
    while (firstNb) {
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->nbCount);
#endif
        prevNb = firstNb;
        firstNb = NET_BUFFER_NEXT_NB(prevNb);
        mdl = NET_BUFFER_FIRST_MDL(prevNb);
        NET_BUFFER_FIRST_MDL(prevNb) = NULL;
        NdisFreeNetBuffer(prevNb);
        OvsFreeMDLAndData(mdl);
    }
    NdisFreeNetBufferList(newNbl);
    OVS_LOG_ERROR("OvsFullCopyNBL failed");
    return NULL;
}
Esempio n. 7
0
/*
 * --------------------------------------------------------------------------
 * OvsCompleteNBL --
 *
 *     This function tries to free the NBL allocated by OVS buffer
 *     management module. If it trigger the completion of the parent
 *     NBL, it will recursively call itself. If it trigger the completion
 *     of external NBL, it will be returned to the caller. The caller
 *     is responsible to call API to return to upper layer.
 * --------------------------------------------------------------------------
 */
PNET_BUFFER_LIST
OvsCompleteNBL(POVS_SWITCH_CONTEXT context,
               PNET_BUFFER_LIST nbl,
               BOOLEAN updateRef)
{
    POVS_BUFFER_CONTEXT ctx;
    UINT16 flags;
    PNET_BUFFER_LIST parent;
    NDIS_STATUS status;
    NDIS_HANDLE poolHandle;
    LONG value;
    POVS_NBL_POOL ovsPool = &context->ovsPool;
    PNET_BUFFER nb;


    ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);

    ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC);

    OVS_LOG_TRACE("Enter: nbl: %p, ctx: %p, refCount: %d, updateRef:%d",
                 nbl, ctx, ctx->refCount, updateRef);

    if (updateRef) {
        value = InterlockedDecrement((LONG volatile *)&ctx->refCount);
        if (value != 0) {
            return NULL;
        }
    } else {
        /*
         * This is a special case, the refCount must be zero
         */
        ASSERT(ctx->refCount == 0);
    }

    nb = NET_BUFFER_LIST_FIRST_NB(nbl);

    flags = ctx->flags;
    if (!(flags & OVS_BUFFER_FRAGMENT) &&
        NET_BUFFER_DATA_LENGTH(nb) != ctx->origDataLength) {
        UINT32 diff;
        if (NET_BUFFER_DATA_LENGTH(nb) < ctx->origDataLength) {
            diff = ctx->origDataLength -NET_BUFFER_DATA_LENGTH(nb);
            status = NdisRetreatNetBufferListDataStart(nbl, diff, 0,
                                                       NULL, NULL);
            ASSERT(status == NDIS_STATUS_SUCCESS);
        } else {
            diff = NET_BUFFER_DATA_LENGTH(nb) - ctx->origDataLength;
            NdisAdvanceNetBufferListDataStart(nbl, diff, TRUE, NULL);
        }
    }

    if (ctx->flags & OVS_BUFFER_PRIVATE_CONTEXT) {
        NdisFreeNetBufferListContext(nbl, sizeof (OVS_BUFFER_CONTEXT));
    }

    if (flags & OVS_BUFFER_NEED_COMPLETE) {
        /*
         * return to caller for completion
         */
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->sysNBLCount);
#endif
        return nbl;
    }

    if (flags & OVS_BUFFER_PRIVATE_FORWARD_CONTEXT) {
        context->NdisSwitchHandlers.
              FreeNetBufferListForwardingContext(ovsPool->ndisContext, nbl);
    }

    if (flags & (OVS_BUFFER_PRIVATE_MDL | OVS_BUFFER_PRIVATE_DATA)) {
        PNET_BUFFER nb = NET_BUFFER_LIST_FIRST_NB(nbl);
        while (nb) {
            PMDL mdl = NET_BUFFER_FIRST_MDL(nb);
            NET_BUFFER_FIRST_MDL(nb) = NULL;
            ASSERT(mdl->Next == NULL);
            OvsFreeMDLAndData(mdl);
            nb = NET_BUFFER_NEXT_NB(nb);
        }
    }

    if (flags & OVS_BUFFER_PRIVATE_NET_BUFFER) {
        PNET_BUFFER nb, nextNb;

        nb = NET_BUFFER_LIST_FIRST_NB(nbl);
        while (nb) {
            nextNb = NET_BUFFER_NEXT_NB(nb);
            NdisFreeNetBuffer(nb);
#ifdef DBG
            InterlockedDecrement((LONG volatile *)&ovsPool->nbCount);
#endif
            nb = nextNb;
        }
        NET_BUFFER_LIST_FIRST_NB(nbl) = NULL;
    }

    parent = nbl->ParentNetBufferList;

    poolHandle = NdisGetPoolFromNetBufferList(nbl);
    if (flags & OVS_BUFFER_FROM_FIX_SIZE_POOL) {
        ASSERT(poolHandle == ovsPool->fixSizePool);
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->fixNBLCount);
#endif
        NdisFreeNetBufferList(nbl);
    } else if (flags & OVS_BUFFER_FROM_ZERO_SIZE_POOL) {
        ASSERT(poolHandle == ovsPool->zeroSizePool);
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->zeroNBLCount);
#endif
        NdisFreeNetBufferList(nbl);
    } else if (flags & OVS_BUFFER_FROM_NBL_ONLY_POOL) {
        ASSERT(poolHandle == ovsPool->nblOnlyPool);
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->nblOnlyCount);
#endif
        NdisFreeCloneNetBufferList(nbl, 0);
    } else if (flags & OVS_BUFFER_FRAGMENT) {
        OVS_LOG_TRACE("Free fragment %p parent %p", nbl, parent);
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->fragNBLCount);
#endif
        NdisFreeFragmentNetBufferList(nbl, ctx->dataOffsetDelta, 0);
    }

    if (parent != NULL) {
        ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(parent);
        ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC);
        value = InterlockedDecrement((LONG volatile *)&ctx->refCount);
        if (value == 0) {
            return OvsCompleteNBL(context, parent, FALSE);
        }
    }
    return NULL;
}
Esempio n. 8
0
VOID
FilterSendNetBufferLists(
        IN  NDIS_HANDLE         FilterModuleContext,
        IN  PNET_BUFFER_LIST    NetBufferLists,
        IN  NDIS_PORT_NUMBER    PortNumber,
        IN  ULONG               SendFlags
        )
/*++
 
Routine Description:

    Send Net Buffer List handler
    This function is an optional function for filter drivers. If provided, NDIS
    will call this function to transmit a linked list of NetBuffers, described by a 
    NetBuferList, over the network. If this handler is NULL, NDIS will skip calling
    this fitler when sending a NetBufferList and will call the next lower fitler 
    in the stack with a non_NULL FilterSendNetBufferList handleror the miniport driver.
    A filter that doesn't provide a FilerSendNetBufferList handler can not initiate a 
    send o its own.

Arguments:

    FilterModuleContext: Pointer to our filter context area.
    NetBufferLists: Pointer to a List of NetBufferLists.
    PortNumber - Port Number to which this send is targetted
    SendFlags-  Specifies if the call is at DISPATCH_LEVEL                     
  

Return Value:
 
    NDIS_STATUS_SUCCESS: 
    NDIS_STATUS_PENDING:
    NDIS_STATUS_INVALID_PACKET:
    NDIS_STATUS_RESOURCES:
    NDIS_STATUS_FAILURE:


NOTE: The filter will act like a passthru filter.       
 
--*/
{
    PMS_FILTER          pFilter = (PMS_FILTER)FilterModuleContext;
    NDIS_STATUS         Status = NDIS_STATUS_SUCCESS;
    PNET_BUFFER_LIST    CurrNbl;
    BOOLEAN             DispatchLevel;

	// ++
	PNET_BUFFER_LIST	CurrentBufferList	= NULL;
	PNET_BUFFER			CurrentBuffer		= NULL;
	PNET_BUFFER_DATA	CurrentBufferData	= NULL;
	PMDL				PacketMdl			= NULL;
	ULONG				DataOffset			= 0;
	ULONG				PacketSize			= 0;
	PUCHAR				PacketData			= NULL;
	ARP_PACKET*			ArpPacket			= NULL;
	BOOLEAN				bWanAdapter			= FALSE;
    // --

    
    DEBUGP(DL_TRACE, ("===>SendNetBufferList: NBL = %p.\n", NetBufferLists));

    do
    {

       DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags);
#if DBG
        //
        // we should never get packets to send if we are not in running state
        //
        
        FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
        //
        // If the filter is not in running state, fail the send
        // 
        if (pFilter->State != FilterRunning)
        {
            FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
            
            CurrNbl = NetBufferLists;
            while (CurrNbl)
            {
                NET_BUFFER_LIST_STATUS(CurrNbl) = NDIS_STATUS_PAUSED;
                CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
            }
            NdisFSendNetBufferListsComplete(pFilter->FilterHandle, 
                        NetBufferLists, 
                        DispatchLevel ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0);
            break;
            
        }
        FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
#endif

		//  ++
		CurrentBufferList = NetBufferLists;

		while(CurrentBufferList)
		{
			// Each NET_BUFFER structure packages a packet of network data
			CurrentBuffer = NET_BUFFER_LIST_FIRST_NB(CurrentBufferList);
			while(CurrentBuffer)
			{
				// 检测其中是否有ARP协议包
				PacketMdl		= NET_BUFFER_FIRST_MDL(CurrentBuffer);
				DataOffset		= NET_BUFFER_DATA_OFFSET(CurrentBuffer);
				PacketSize	= NET_BUFFER_DATA_LENGTH(CurrentBuffer);
				
				if(PacketMdl && PacketSize)
				{
					PacketData = (UCHAR*)MmGetSystemAddressForMdlSafe(PacketMdl,NormalPagePriority);
					if(PacketData)
					{
						if(DataOffset)
						{
							PacketData = PacketData + DataOffset;
						}
						// PacketData 是网络包数据,PacketSize 是网络包数据长度

						KdPrint((" PacketData : %p , PacketSize : %d ",PacketData,PacketSize));

						ArpPacket = (ARP_PACKET*)PacketData;

						// 记录网关回应查询次数
						NdisAcquireSpinLock(&GlobalLock);
						if( ArpPacket->EthType == ETHERNET_ARP)
						{
							if( g_bRecord_ARP_Reply						&&
								ArpPacket->OperateCode == ARP_QUERY		&&
								NdisEqualMemory(ArpPacket->DestIPAddress,g_Want_ARP_Reply_IP,4)	)
							{
								g_Reply_Record->ulQueryCount ++;
								//开始记录网关查询操作
								BeginCheckGateway();
							}
						}
						NdisReleaseSpinLock(&GlobalLock);

					}
				}
				CurrentBuffer = NET_BUFFER_NEXT_NB(CurrentBuffer);
			}
			CurrentBufferList = NET_BUFFER_LIST_NEXT_NBL(CurrentBufferList);
		}
		// --


        if (pFilter->TrackSends)
        {
            FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
            CurrNbl = NetBufferLists;
            while (CurrNbl)
            {
                pFilter->OutstandingSends++;
                FILTER_LOG_SEND_REF(1, pFilter, CurrNbl, pFilter->OutstandingSends);
                
                CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
            }
            FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
        }
        //
        // If necessary, queue the NetBufferList in a local structure for later processing
        //
        NdisFSendNetBufferLists(pFilter->FilterHandle, NetBufferLists, PortNumber, SendFlags);
        
        
    }
    while (FALSE);
    
    DEBUGP(DL_TRACE, ("<===SendNetBufferList: Status = %8x.\n", Status));
}
Esempio n. 9
0
VOID
FilterReceiveNetBufferLists(
        IN  NDIS_HANDLE         FilterModuleContext,
        IN  PNET_BUFFER_LIST    NetBufferLists,
        IN  NDIS_PORT_NUMBER    PortNumber,
        IN  ULONG               NumberOfNetBufferLists,
        IN  ULONG               ReceiveFlags
         )
/*++

Routine Description:

    FilerReceiveNetBufferLists is an optional function for filter drivers. 
    If provided, this function process receive indications made by underlying 
    NIC or lower level filter drivers. This function  can also be called as a 
    result of loopback. If this handler is NULL, NDIS will skip calling this
    filter when processing a receive indication and will call the next upper 
    filter in the stack with a non-NULL FitlerReceiveNetBufferLists handler 
    or the procotol driver. A filter that doesn't provide a 
    FilterReceiveNetBufferLists handler can not provided a 
    FilterReturnNetBufferLists handler or a initiate a receive indication on 
    its own.

Arguments:

    FilterModuleContext: Pointer to our filter context area.
    NetBufferLists: A linked list of NetBufferLists allocated by underlying driver each containing
                    one NetBuffer.
    PortNumber: Port on which the Receive is indicated
    ReceiveFlags: Flags associated with the Receive such as whether the filter
                  can pend the receive
   

Return Value:

    None
 
--*/
{

    PMS_FILTER          pFilter = (PMS_FILTER)FilterModuleContext;
    NDIS_STATUS         ReturnStatus = NDIS_STATUS_SUCCESS;
    PNET_BUFFER_LIST    NextNetBufferList;
    BOOLEAN             DispatchLevel;
    ULONG               ReturnFlags;
    ULONG               Ref;

	// ++
	PNET_BUFFER_LIST	CurrentBufferList	= NULL;
	PNET_BUFFER			CurrentBuffer		= NULL;
	PNET_BUFFER_DATA	CurrentBufferData	= NULL;
	BOOLEAN				HaveARPPacket		= FALSE;
	PMDL				PacketMdl			= NULL;
	ULONG				DataOffset			= 0;
	ULONG				PacketSize			= 0;
	PUCHAR				PacketData			= NULL;
	ARP_PACKET*			ArpPacket			= NULL;
	GATEWAY_ITEM*		Gateway				= NULL;
	LAN_ITEM*			LanItem				= NULL;
	WAN_ITEM*			WanItem				= NULL;
	ULONG				i					= 0;
	BOOLEAN				bSameRecord			= FALSE;
	enum ATTACH_TYPE	AttachType			= ATTACH_NONE;
	enum RAS_OPT		RetOpt				= OPT_PASS;
	BOOLEAN				bWanAdapter			= FALSE;
    // --

    DEBUGP(DL_TRACE, ("===>ReceiveNetBufferList: NetBufferLists = %p.\n", NetBufferLists));

    do
    {

        DispatchLevel = NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags);

#if DBG
        
        FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
 
        if (pFilter->State != FilterRunning)
        {
            FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);

            if (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags))
            {   
                ReturnFlags = 0;
                if (NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags))
                {
                    NDIS_SET_RETURN_FLAG(ReturnFlags, NDIS_RETURN_FLAGS_DISPATCH_LEVEL);
                }
                
                NdisFReturnNetBufferLists(pFilter->FilterHandle, NetBufferLists, ReturnFlags);
            }
            break;
        }
        FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
#endif

        ASSERT(NumberOfNetBufferLists >= 1);

		//  ++
		CurrentBufferList = NetBufferLists;

		while(CurrentBufferList)
		{
			// Each NET_BUFFER structure packages a packet of network data
			CurrentBuffer = NET_BUFFER_LIST_FIRST_NB(CurrentBufferList);
			while(CurrentBuffer)
			{
				// 检测其中是否有ARP协议包
				PacketMdl		= NET_BUFFER_FIRST_MDL(CurrentBuffer);
				DataOffset		= NET_BUFFER_DATA_OFFSET(CurrentBuffer);
				PacketSize	= NET_BUFFER_DATA_LENGTH(CurrentBuffer);
				
				if(PacketMdl && PacketSize)
				{
					PacketData = (UCHAR*)MmGetSystemAddressForMdlSafe(PacketMdl,NormalPagePriority);
					if(PacketData)
					{
						if(DataOffset)
						{
							PacketData = PacketData + DataOffset;
						}
						// PacketData 是网络包数据,PacketSize 是网络包数据长度

						do
						{
							ArpPacket = (ARP_PACKET*)PacketData;

							if( ArpPacket->EthType != ETHERNET_ARP || 
								PacketSize < sizeof(ARP_PACKET)		)
							{
								break;
							}
							else
							{
								KdPrint((" 收到ARP数据包"));
							}

							if( ArpPacket->OperateCode != 0x100 &&
								ArpPacket->OperateCode != 0x200 &&
								ArpPacket->OperateCode != 0x300 &&
								ArpPacket->OperateCode != 0x400 )
							{
								KdPrint((" 错误ARP/RARP协议攻击"));
								AttachType = WRONG_PROTOCOL_ATTACH;
								RetOpt = OPT_DROP;
								goto Exit;
							}

							//进行 IP - Mac 对应查询表的建立
							NdisAcquireSpinLock(&GlobalLock);
							if(g_ArpFw_ShareMem)
							{
								// 查询广播包
								if( ArpPacket->OperateCode == ARP_QUERY										&&
									NdisEqualMemory(ArpPacket->DestMacAddress,Empty_MacAddress,6)			&&
									!NdisEqualMemory(ArpPacket->SourceMacAddress,Empty_MacAddress,6)		&&
									g_ArpFw_ShareMem->ulItemCount < MAX_IP_MAC_ITEM_COUNT					)
								{
									bSameRecord = FALSE;
									for( i = 0 ; i< g_ArpFw_ShareMem->ulItemCount; i++)
									{
										if(NdisEqualMemory( g_ArpFw_ShareMem->Items[i].IPAddress,ArpPacket->SourceIPAddress,4))
										{
											bSameRecord = TRUE;
											break;
										}
									}

									//当前没有该IP地址的记录
									if(!bSameRecord)
									{
										memcpy(g_ArpFw_ShareMem->Items[g_ArpFw_ShareMem->ulItemCount].IPAddress,
												ArpPacket->SourceIPAddress,4);
										memcpy(g_ArpFw_ShareMem->Items[g_ArpFw_ShareMem->ulItemCount].MacAddress,
												ArpPacket->SourceMacAddress,6);

										g_ArpFw_ShareMem->ulItemCount ++;
										
									}	
								}
							}
							NdisReleaseSpinLock(&GlobalLock);

							// ARP Reply 报文记录
							if(	ArpPacket->OperateCode == ARP_REPLY									&& 
								g_bRecord_ARP_Reply													&&
								NdisEqualMemory(ArpPacket->SourceIPAddress,g_Want_ARP_Reply_IP,4)	)
							{
								bSameRecord = FALSE;

								NdisAcquireSpinLock(&GlobalLock);

								if(g_Reply_Record->ulItemCount < MAX_REPLY_RECORD)
								{
									do
									{
										if(g_Reply_Record->ulItemCount > 0)
										{
											for(i = 0 ; i < g_Reply_Record->ulItemCount; i ++)
											{
												if(NdisEqualMemory(ArpPacket->SourceMacAddress,
													g_Reply_Record->Items[i].MacAddress,6))
												{
													g_Reply_Record->Items[i].RecordCount ++;
													bSameRecord = TRUE;
													break;
												}
											}
										}

										if(!bSameRecord)
										{
											NdisMoveMemory(g_Reply_Record->Items[g_Reply_Record->ulItemCount].IPAddress,
																ArpPacket->SourceIPAddress,4);
											NdisMoveMemory(g_Reply_Record->Items[g_Reply_Record->ulItemCount].MacAddress,
																ArpPacket->SourceMacAddress,6);
											g_Reply_Record->Items[g_Reply_Record->ulItemCount].WanAddress	= bWanAdapter;
											g_Reply_Record->Items[g_Reply_Record->ulItemCount].Gateway		= TRUE;
											g_Reply_Record->Items[g_Reply_Record->ulItemCount].Next			= NULL;
											g_Reply_Record->Items[g_Reply_Record->ulItemCount].RecordCount	= 1;

											g_Reply_Record->ulItemCount ++;
										}
									}
									while(FALSE);
								}

								NdisReleaseSpinLock(&GlobalLock);
							}

							//检测伪造ARP/RARP Query攻击中的源Mac地址是否为正确的网关地址
							if( g_EnableGatewayCheck															&&
								(ArpPacket->OperateCode == ARP_QUERY || ArpPacket->OperateCode == RARP_QUERY )   )
							{
								// 网关地址检测,Query操作中的源地址和源MAC地址必须是正确的
								if(!bWanAdapter)		// 局域网网关检测
								{
									NdisAcquireSpinLock(&GlobalLock);
									Gateway  = g_Gateway_List;
									while(Gateway)
									{
										if( NdisEqualMemory(ArpPacket->SourceIPAddress,Gateway->IPAddress,4)	&&
											!NdisEqualMemory(ArpPacket->SourceMacAddress,Gateway->MacAddress,6)  )
										{
											// IP地址相同,Mac地址不同 (禁止该包往上通行)
											KdPrint(("伪造网关Query攻击报文"));
											AttachType = GATEWAY_ARP_QUERY_ATTACH;
											RetOpt = OPT_DROP;
											NdisReleaseSpinLock(&GlobalLock);
											goto Exit;					
										}

										Gateway = Gateway->Next;
									}
									NdisReleaseSpinLock(&GlobalLock);
								}
							}

							//伪造的ARP/RARP Reply报文检测
							if(	g_EnableGatewayCheck														  &&
								(ArpPacket->OperateCode == ARP_REPLY || ArpPacket->OperateCode == RARP_REPLY) )
							{

								if(!bWanAdapter)		// 局域网网关检测
								{
									NdisAcquireSpinLock(&GlobalLock);
									Gateway = g_Gateway_List;
									while(Gateway)
									{
										if(	NdisEqualMemory(Gateway->IPAddress,ArpPacket->SourceIPAddress,4)	&& // 是网关IP
											!NdisEqualMemory(Gateway->MacAddress,ArpPacket->SourceMacAddress,6)	)	// Mac 地址不相同,网关攻击
										{
											KdPrint(("伪造网关Reply攻击报文"));
											//禁止该包往上通行
											AttachType = GATEWAY_ARP_REPLY_ATTACH;
											RetOpt = OPT_DROP;
											NdisReleaseSpinLock(&GlobalLock);
											goto Exit;
										}
										else if(NdisEqualMemory(Gateway->IPAddress,ArpPacket->DestIPAddress,4)		&&
												!NdisEqualMemory(Gateway->MacAddress,ArpPacket->DestMacAddress,6)	)
										{
											KdPrint(("伪造网关Reply攻击报文"));
											//禁止该包往上通行
											RetOpt = OPT_DROP;
											AttachType = GATEWAY_ARP_REPLY_ATTACH;
											NdisReleaseSpinLock(&GlobalLock);
											goto Exit;
										}

										Gateway = Gateway->Next;
									}

									NdisReleaseSpinLock(&GlobalLock);
								}
							}
							
							//进行 IP 冲突攻击检测
							if(	g_EnableSameIPCheck														&&
								NdisEqualMemory(ArpPacket->SourceIPAddress,ArpPacket->DestIPAddress,4)	)
							{
								NdisAcquireSpinLock(&GlobalLock);
								if(!bWanAdapter) // 局域网检测
								{
									LanItem = g_Lan_List;
									while(LanItem)
									{
										// IP 地址相同 而 源Mac 地址不同
										if( NdisEqualMemory(ArpPacket->SourceIPAddress,LanItem->IPAddress,4) &&
											!NdisEqualMemory(ArpPacket->SourceMacAddress,LanItem->MacAddress,6) )
										{
											KdPrint(("伪造内网间IP冲突攻击报文"));
											RetOpt = OPT_DROP;
											AttachType = LAN_SAMEIP_ATTACH;
											NdisReleaseSpinLock(&GlobalLock);
											goto Exit;
										}

										LanItem = LanItem->Next;
									}
									// 局域网对外网的相同IP攻击
									WanItem = g_Wan_List;
									while(WanItem)
									{
										if(NdisEqualMemory(ArpPacket->SourceIPAddress,WanItem->IPAddress,4))
										{
											KdPrint(("伪造内外网间IP冲突攻击报文"));
											RetOpt = OPT_DROP;
											AttachType = WAN_SAMEIP_ATTACH;
											NdisReleaseSpinLock(&GlobalLock);
											goto Exit;
										}
										WanItem = WanItem->Next;
									}
								}
								NdisReleaseSpinLock(&GlobalLock);
							}
						}
						while(FALSE);
					}
				}
				CurrentBuffer = NET_BUFFER_NEXT_NB(CurrentBuffer);
			}
			CurrentBufferList = NET_BUFFER_LIST_NEXT_NBL(CurrentBufferList);
		}
		//  --
            
        // 
        // If necessary, queue the NetBufferList in a local structure for later processing.
        // We may need to travel the list, some of them may not need post processing
        //
        if (pFilter->TrackReceives)
        {
            FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
            pFilter->OutstandingRcvs += NumberOfNetBufferLists;
            Ref = pFilter->OutstandingRcvs;
            
            FILTER_LOG_RCV_REF(1, pFilter, NetBufferLists, Ref);
            FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
        }

		KdPrint((" NdisFIndicateReceiveNetBufferLists Run "));

        NdisFIndicateReceiveNetBufferLists(
                   pFilter->FilterHandle,
                   NetBufferLists,
                   PortNumber, 
                   NumberOfNetBufferLists,
                   ReceiveFlags);


        if (NDIS_TEST_RECEIVE_CANNOT_PEND(ReceiveFlags) && 
            pFilter->TrackReceives)
        {
            FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
            pFilter->OutstandingRcvs -= NumberOfNetBufferLists;
            Ref = pFilter->OutstandingRcvs;
            FILTER_LOG_RCV_REF(2, pFilter, NetBufferLists, Ref);
            FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
        }

		// ++
		break;

Exit:
		KdPrint((" Drop Received Packet "));
		if(ArpPacket)
		{
			NdisAcquireSpinLock(&GlobalLock);

			if(g_ArpFw_ShareMem && AttachType != ATTACH_NONE)	
			{
				g_ArpFw_ShareMem->NotifyPacket.AttachCount = 1;
				g_ArpFw_ShareMem->NotifyPacket.AttachType  = AttachType;
				g_ArpFw_ShareMem->NotifyPacket.SendPacket  = FALSE;
				g_ArpFw_ShareMem->NotifyPacket.WanPacket   = FALSE;

				RtlCopyMemory((PVOID)&g_ArpFw_ShareMem->NotifyPacket.ArpPacket,
								ArpPacket,sizeof(ARP_PACKET));

				SetUserShareEvent(&g_NotifyEvent);

			}
			NdisReleaseSpinLock(&GlobalLock);
		}

		// return this packet
		if (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags))
		{
			ReturnFlags = 0;
			if (NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags))
			{
				NDIS_SET_RETURN_FLAG(ReturnFlags, NDIS_RETURN_FLAGS_DISPATCH_LEVEL);
			}
			NdisFReturnNetBufferLists(pFilter->FilterHandle, NetBufferLists, ReturnFlags);
		}
		// --

    } while (FALSE);
    
    DEBUGP(DL_TRACE, ("<===ReceiveNetBufferList: Flags = %8x.\n", ReceiveFlags));
    
}