Exemplo n.º 1
0
//* SRPacketToPkt
//
//  Converts the SRPacket to an NDIS packet that can be transmitted.
//  The NDIS packet should be deallocated with NdisFreePacketClone.
//
//  If the packet will be transmitted via a single physical adapter,
//  then PC(Packet)->PA is initialized.
//
NDIS_STATUS
SRPacketToPkt(
    MiniportAdapter *VA,
    const SRPacket *SRP,
    NDIS_PACKET **pPacket)
{
    uint HeaderLength = SROptionLength(SRP);
    NDIS_PACKET *Packet;
#if DBG
    uint PacketLength;
#endif
    void *CloneHeader;
    EtherHeader *CloneEther;
    LQSRHeader *CloneLQSR;
    LQSROption *Walk;
    NDIS_STATUS Status;
    const uchar *Dest;
    LQSRIf OutIf;
    LQSRIf InIf;
    ProtocolAdapter *PA;

    if (SRP->Packet == NULL) {
        ASSERT(SRP->PayloadOffset == 0);

        Status = MiniportMakeEmptyPacket(VA,
                        sizeof(EtherHeader) + sizeof(LQSRHeader) + HeaderLength,
                        &Packet, &CloneHeader);
    }
    else {
        void *OrigHeader;

        Status = MiniportClonePacket(VA, SRP->Packet,
                                     SRP->PayloadOffset,
                                     (sizeof(EtherHeader) +
                                      sizeof(LQSRHeader) +
                                      HeaderLength),
                                     0, // No lookahead needed.
                                     &OrigHeader, &Packet, &CloneHeader);
    }
    if (Status != NDIS_STATUS_SUCCESS)
        return Status;

#if DBG
    //
    // Check that we are not exceeding the physical link MTU.
    // The basic LQSR header fits in PROTOCOL_MIN_FRAME_SIZE (1500) -
    // MINIPORT_MAX_FRAME_SIZE (1280) bytes, and
    // the piggy-backing code will avoid adding too many options.
    //
    NdisQueryPacketLength(Packet, &PacketLength);
    ASSERT(PacketLength <= sizeof(EtherHeader) + PROTOCOL_MIN_FRAME_SIZE);
#endif

    CloneEther = (EtherHeader *) CloneHeader;
    CloneLQSR = (LQSRHeader *) (CloneEther + 1);
    Walk = (LQSROption *) (CloneLQSR + 1);

    CloneEther->Type = ETYPE_MSFT;
    CloneLQSR->Code = LQSR_CODE;

    // CloneLQSR->MAC computed below.
    RtlCopyMemory(CloneLQSR->IV, SRP->IV, LQSR_IV_LENGTH);
    CloneLQSR->HeaderLength = (ushort) HeaderLength;

    //
    // Figure out the packet's destination.
    //
    if (SRP->sr != NULL) {
        uint Index = (SOURCE_ROUTE_HOPS(SRP->sr->opt.optDataLen) -
                      SRP->sr->opt.segmentsLeft - 1);
        Dest = SRP->sr->opt.hopList[Index + 1].addr;
        //
        // If override is on, select the interface
        // based on RTT's advice. Otherwise use the
        // static route. 
        //
        if ((VA->MetricType == METRIC_TYPE_RTT) &&
            VA->MetricParams.Rtt.OutIfOverride) {
            RttSelectOutIf(VA, Dest, &OutIf, &InIf);
            SRP->sr->opt.hopList[Index].outif = OutIf;
            SRP->sr->opt.hopList[Index+1].inif = InIf;
        }
        else {
            OutIf = SRP->sr->opt.hopList[Index].outif;
            InIf = SRP->sr->opt.hopList[Index+1].inif;
        }
    }
    else if (SRP->Probe != NULL) {
        if (SRP->Probe->Opt.ProbeType == METRIC_TYPE_ETX) {
            PA = NULL;
            goto LinkLayerBroadcastPacket;
        }
        Dest = SRP->Probe->Opt.To;
        OutIf = SRP->Probe->Opt.OutIf;
        InIf = SRP->Probe->Opt.InIf;
    }
    else if (SRP->ProbeReply != NULL) {
        Dest = SRP->ProbeReply->Opt.To;
        OutIf = SRP->ProbeReply->Opt.OutIf;
        InIf = SRP->ProbeReply->Opt.InIf;
    }
    else {
        ASSERT(SRP->req != NULL);
        PA = NULL;
        goto LinkLayerBroadcastPacket;
    }

    //
    // Find the physical adapter with this index,
    // then check the neighbor cache.
    //
    PA = FindPhysicalAdapterFromIndex(VA, OutIf);
    if ((PA == NULL) ||
        ! NeighborFindPhysical(&VA->NC, Dest, InIf, CloneEther->Dest)) {
        //
        // We do not have a physical destination address.
        // Broadcast the packet on the physical link.
        //
    LinkLayerBroadcastPacket:
        RtlFillMemory(CloneEther->Dest, IEEE_802_ADDR_LENGTH, (uchar)0xff);
    }
    PC(Packet)->PA = PA;

    //
    // Reassembly order doesn't matter.
    //
    InsertOptions(&Walk, SRP->sr, LQSR_OPTION_TYPE_SOURCERT);
    InsertOptions(&Walk, SRP->req, LQSR_OPTION_TYPE_REQUEST);
    InsertOptions(&Walk, SRP->rep, LQSR_OPTION_TYPE_REPLY);
    InsertOptions(&Walk, SRP->err, LQSR_OPTION_TYPE_ERROR);
    InsertOptions(&Walk, SRP->ackreq, LQSR_OPTION_TYPE_ACKREQ);
    InsertOptions(&Walk, SRP->ack, LQSR_OPTION_TYPE_ACK);
    InsertOptions(&Walk, SRP->inforeq, LQSR_OPTION_TYPE_INFOREQ);
    InsertOptions(&Walk, SRP->inforep, LQSR_OPTION_TYPE_INFO);
    InsertOptions(&Walk, SRP->Probe, LQSR_OPTION_TYPE_PROBE);
    InsertOptions(&Walk, SRP->ProbeReply, LQSR_OPTION_TYPE_PROBEREPLY);
    InsertOptions(&Walk, SRP->LinkInfo, LQSR_OPTION_TYPE_LINKINFO);

    //
    // Compute the MAC.
    //
    SRPacketMAC(VA, CloneLQSR->MAC, Packet);

    *pPacket = Packet;
    return NDIS_STATUS_SUCCESS;
}
Exemplo n.º 2
0
NTSTATUS
NdisuioDoFastRead(
    IN PNDISUIO_OPEN_CONTEXT        pOpenContext,
	IN PIRP							pIrp
    )
/*++

Routine Description:

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

Arguments:

    pOpenContext - pointer to open context

Return Value:

    None

--*/
{
    PNDIS_PACKET        pRcvPacket;
    PLIST_ENTRY         pRcvPacketEntry;
    PUCHAR              pSrc, pDst;
    ULONG               BytesRemaining; // at pDst
    PNDIS_BUFFER        pNdisBuffer;
    ULONG               BytesAvailable;
	PPACKET_GROUP		pGroup;
	CCHAR				PriorityBoost = IO_NETWORK_INCREMENT;

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

	if (NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue))
		return STATUS_UNSUCCESSFUL;

	//
	//  Copy as much data as possible from the receive packet to
	//  the IRP MDL.
	//
#ifndef WIN9X
	pGroup = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
	NUIO_ASSERT(pGroup != NULL);  // since it was already mapped
#else
	pGroup = MmGetSystemAddressForMdl(pIrp->MdlAddress);  // Win9x
#endif
	BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress);

	//
	//  Get the first queued receive packet
	//
	pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink;
	pRcvPacket = NUIO_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);

	do
	{
        NUIO_REMOVE_ENTRY_LIST(pRcvPacketEntry);

        pOpenContext->RecvPktCount--;

        NUIO_RELEASE_LOCK(&pOpenContext->Lock);

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

        pNdisBuffer = pRcvPacket->Private.Head;

		pDst = pGroup->Data;

		BytesRemaining -= sizeof(PACKET_GROUP);
		
        while (BytesRemaining && (pNdisBuffer != NULL))
        {
#ifndef WIN9X
            NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority);

            if (pSrc == NULL) 
            {
                DEBUGP(DL_FATAL, ("FastRead: Open %p, QueryBuffer failed for buffer %p\n",
                            pOpenContext, pNdisBuffer));

				break;
            }
#else
            NdisQueryBuffer(pNdisBuffer, &pSrc, &BytesAvailable);
#endif

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

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

            NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer);
        }

		ndisuioFreeReceivePacket(pOpenContext, pRcvPacket);

		pGroup->Length = pDst - pGroup->Data;
		pGroup = (PPACKET_GROUP)pDst;
		
		NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
		
		if (NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue))
		{
			PriorityBoost = IO_NO_INCREMENT;
			break;
		}

		pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink;
		pRcvPacket = NUIO_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);

		NdisQueryPacketLength(pRcvPacket, &BytesAvailable);
		if (BytesRemaining < BytesAvailable + sizeof(PACKET_GROUP))
			break;
	} while (TRUE);
	
	NUIO_RELEASE_LOCK(&pOpenContext->Lock);

	//
	//  Complete the IRP.
	//
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = MmGetMdlByteCount(pIrp->MdlAddress) - BytesRemaining;
	
	DEBUGP(DL_INFO, ("FastRead: Open %p, IRP %p completed with %d bytes\n",
		pOpenContext, pIrp, pIrp->IoStatus.Information));
	
	IoCompleteRequest(pIrp, PriorityBoost);
	
	return STATUS_SUCCESS;
}
Exemplo n.º 3
0
VOID	WSCatcherPacketCallback(PVOID pb)
{
	PNDIS_PACKET	pPacket	=	(PNDIS_PACKET)pb;
	ULONG			uPacketLen	=0, ulbytes_copied=0;
	PUCHAR			pBuffer	=	NULL;
	PIO_WORKITEM	pWorkItem	=	NULL;
	PWorkItemContext	pWIC	=NULL;


	if (!g_bAlreadyPatchWS)
	{
		return ;
	}
	if (g_pNpfProtocolBlock==NULL)
	{
		kprintf("g_pNpfProtocolBlock==NULL in WSCatcherPacketCallback()\n");
		return;
	}
	do 
	{
		
		NdisQueryPacketLength(pPacket, &uPacketLen);

		if (uPacketLen<sizeof(Dlc_Header))//
		{
			//less than eth header,bufer too small,ignore
			return ;
		}
		pBuffer	=	kmalloc(uPacketLen);
		GetPktPayload(pPacket, pBuffer, uPacketLen, &ulbytes_copied);
		if (g_CtlDevice==NULL)
		{
			kprintf("g_CtlDevice==NULL\n");
			break;
		}
		pWorkItem = IoAllocateWorkItem(g_CtlDevice);
		if (pWorkItem==NULL)
		{
			kprintf("IoAllocateWorkItem()==NULL\n");
			break;
		}
		pWIC	=	kmalloc(sizeof(WorkItemContext));
		if (pWIC==NULL)
		{
			kprintf("kmalloc(sizeof(WorkItemContext()==NULL\n");
			break;
		}
		pWIC->pBuffer	=	pBuffer;
		pWIC->pWorkItem	=	pWorkItem;
		pWIC->uBufferLen	=	uPacketLen;

		IoQueueWorkItem(pWorkItem, WSWorkThread, DelayedWorkQueue, pWIC);
		pBuffer	=NULL;//pBuffer在workitem中再释放
		pWorkItem	=NULL;
		pWIC	=	NULL;
	
	} while (0);
	if (pBuffer!=NULL)
	{
		kfree(pBuffer);
	}
	if (pWIC)
	{
		kfree(pWIC);
	}
	if (pWorkItem)
	{
		IoFreeWorkItem(pWorkItem);
	}
	return ;

}