Example #1
0
UINT CopyPacketToBuffer(
    PCHAR DstData,
    PNDIS_PACKET SrcPacket,
    UINT SrcOffset,
    UINT Length)
/*
 * FUNCTION: Copies data from an NDIS packet to a buffer
 * ARGUMENTS:
 *     DstData   = Pointer to destination buffer
 *     SrcPacket = Pointer to source NDIS packet
 *     SrcOffset = Source start offset
 *     Length    = Number of bytes to copy
 * RETURNS:
 *     Number of bytes copied to destination buffer
 * NOTES:
 *     The number of bytes copied may be limited by the source
 *     buffer size
 */
{
    PNDIS_BUFFER FirstBuffer;
    PVOID Address;
    UINT FirstLength;
    UINT TotalLength;

    TI_DbgPrint(DEBUG_PBUFFER, ("DstData (0x%X)  SrcPacket (0x%X)  SrcOffset (0x%X)  Length (%d)\n", DstData, SrcPacket, SrcOffset, Length));

    NdisGetFirstBufferFromPacket(SrcPacket,
                                 &FirstBuffer,
                                 &Address,
                                 &FirstLength,
                                 &TotalLength);

    return CopyBufferChainToBuffer(DstData, FirstBuffer, SrcOffset, Length);
}
Example #2
0
void netgSendToMiniportComplete(IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET pNdisPacket, IN NDIS_STATUS Status) {
	PIRP                        pIrp;
    PIO_STACK_LOCATION          pIrpSp;
	PADAPT						pAdapt;
    POPEN_CONTEXT				pOpenContext;
	PNDIS_BUFFER                pNdisBuffer;
	PVOID                       VirtualAddr;
	UINT                        BufferLength;
	UINT                        TotalLength;

	DBGPRINT(("==> netgSendToMiniportComplete\n"));

	pAdapt = (PADAPT)ProtocolBindingContext;
	pOpenContext = pAdapt->pOpenContext;
	pIrp = (((PNPROT_SEND_PACKET_RSVD)&((pNdisPacket)->ProtocolReserved[0]))->pIrp);

	// Free buffer
	NdisGetFirstBufferFromPacket(pNdisPacket, &pNdisBuffer, &VirtualAddr, &BufferLength, &TotalLength);
	NdisFreeBuffer(pNdisBuffer);

	// Free packet
	if (NdisInterlockedDecrement((PLONG)&((PNPROT_SEND_PACKET_RSVD)&((pNdisPacket)->ProtocolReserved[0]))->RefCount) == 0) {                                                                           \
		NdisFreePacket(pNdisPacket);
	}   

CompleteTheIRP:
	// Complete the Write IRP with the right status.
	pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
    if (Status == NDIS_STATUS_SUCCESS) {
		pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length;
        pIrp->IoStatus.Status = STATUS_SUCCESS;
    } else {
        pIrp->IoStatus.Information = 0;
        pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
    }
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	DBGPRINT(("<== netgSendToMiniportComplete\n"));
}
Example #3
0
INT
LpxProtocolReceivePacket(
	IN NDIS_HANDLE	ProtocolBindingContext,
	IN PNDIS_PACKET	Packet
){
	PDEVICE_CONTEXT	deviceContext;
	PNDIS_BUFFER	ndisFirstBuffer;
	PVOID			firstBuffer;
	UINT		    firstBufferSize;
	UINT			totalBufferSize;
	USHORT		    protocol;
	PNDIS_PACKET	packet = NULL;
	NDIS_STATUS		status;
	INT				pktReferenceCount = 0;
	UINT		    addiLlcHeaderSize = 0;
	PLPX_HEADER		lpxHeader;
	USHORT			lpxHeaderSize;
	UINT			lpxPayload;
	UINT			rawDataOffset;


	DebugPrint( 4, ("ProtocolReceivePacket: Entered\n") );
	
	deviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext;

	//
	//	Check to see if the device context is initialized.
	//
	ASSERT( deviceContext->NdisBindingHandle );

	if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) ||
		FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) {

			DebugPrint( 4,("Device is not initialized. Drop packet\n") );

			return 0;
	}

	//
	//	validation
	//
	NdisGetFirstBufferFromPacket(
				Packet,
				&ndisFirstBuffer,
				&firstBuffer,
				&firstBufferSize,
				&totalBufferSize);

	if (firstBufferSize < ETHERNET_HEADER_LENGTH) {

		DebugPrint( 1, ("ProtocolReceivePacket: FirstBufferSize = %x\n", firstBufferSize) );
		return 0;
	}

	protocol = ((PETHERNET_HEADER)firstBuffer)->Type;

	//
	//	Discard 802.2 LLC SNAP field.
	//
	// if Ether Type less than 0x0600 ( 1536 )
	//

	if (NTOHS(protocol) < 0x0600  && 
	    NTOHS(protocol) != 0x0060 && // LOOP: Ethernet Loopback
		NTOHS(protocol) != 0x0200 && // PUP : Xerox PUP packet
		NTOHS(protocol) != 0x0201) { // PUPAP: Xerox PUP address trans packet 

		protocol = *(PUSHORT)((PUCHAR)firstBuffer + ETHERNET_HEADER_LENGTH + LENGTH_8022LLCSNAP - 2);
		if(firstBufferSize >= LENGTH_8022LLCSNAP)
			firstBufferSize -= LENGTH_8022LLCSNAP;
		else {
			DebugPrint( 1, ("ProtocolReceivePacket: Too small first buffer\n") );
			return 0;
		}

		if(totalBufferSize >= LENGTH_8022LLCSNAP)
			totalBufferSize -= LENGTH_8022LLCSNAP;
		else {
			DebugPrint( 1, ("ProtocolReceivePacket: Too small total buffer\n") );
			return 0;
		}
		addiLlcHeaderSize = LENGTH_8022LLCSNAP;
	}

	if (protocol != HTONS(ETH_P_LPX)) {
	
		DebugPrint( 4, ("ProtocolReceivePacket: Type = %x\n", protocol) );
		return 0;
	}
	if(totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + sizeof(LPX_HEADER)) {
		DebugPrint( 1, ("ProtocolReceivePacket: too small packet(1).\n"));
		return 0;
	}

	//
	// Extract LPX header information
	//
	//

	lpxHeader = (PLPX_HEADER)((PBYTE)firstBuffer + ETHERNET_HEADER_LENGTH + addiLlcHeaderSize);
	lpxHeaderSize = sizeof(LPX_HEADER);
	lpxPayload = NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize;

#if __LPX_OPTION_ADDRESSS__

	if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) {
		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
	}

	if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) {
		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
	}

#endif

	if(totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize + lpxPayload) {
		DebugPrint( 1, ("ProtocolReceivePacket: too small packet(2).\n"));
		return 0;
	}

	//
	// DROP PACKET for DEBUGGING!!!!
	//

#if 1 //DBG // Enabled for testing

	if (PacketRxDropRate) {

		PacketRxCountForDrop++;
				
		if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) {
			PLPX_HEADER        lpxHeader = (PLPX_HEADER)((PUCHAR)firstBuffer + addiLlcHeaderSize);
#if 0
			if ((PacketRxCountForDrop % (PacketRxDropRate*20)) == 0) 
				DebugPrint( 1, ("[Drop(%x,%x,%x))]\n", 
								 NTOHS(lpxHeader->Lsctl), NTOHS(lpxHeader->Sequence), NTOHS(lpxHeader->AckSequence)) );
#endif			
			DebugPrint( 1, ("D\n") );

			return 0;
		}
	}

#endif

	ASSERT( addiLlcHeaderSize == 0 );

	DebugPrint( 4, ("ProtocolReceivePacket: TotalBuffSz = %d, FirstBuffSz = %d, LPX_HEADER size = %d\n",
					 totalBufferSize, firstBufferSize, sizeof(LPX_HEADER)) );
	//
	//  If the miniport is out of resources, we can't queue
	//  this packet - make a copy if this is so.
	//
	if (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES) {

		UINT			bytesCopied;

		DebugPrint( 1, ("ProtocolReceivePacket: Miniport reported low packet resources.\n"));

		status = RcvPacketAlloc( deviceContext,
								 lpxPayload,
								 &packet );

		if (status == STATUS_SUCCESS) {
			ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS );
			//
			// Copy lpx payload. payload contains only data.
			//
			NdisCopyFromPacketToPacket(
						packet, 0,
						lpxPayload,
						Packet, ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize,
						&bytesCopied);
			ASSERT(lpxPayload == bytesCopied);
		}

		rawDataOffset = 0;
		pktReferenceCount = 0;
	} else {
		PLPX_RESERVED	externalReserved;
		//
		// No need to allocate new NDIS packet and copy data to the new NDIS packet.
		// But, NDIS miniport allocates only 4 * sizeof(PVOID) for protocol reserved context.
		// We should allocate our own.
		//
		packet = Packet;

		status = NdisAllocateMemoryWithTag(&externalReserved, sizeof(LPX_RESERVED), LPX_MEM_TAG_EXTERNAL_RESERVED);
		if(status == NDIS_STATUS_SUCCESS) {

			RtlZeroMemory(externalReserved, sizeof(LPX_RESERVED));

			// By setting the external reserved field, RESERVED() uses external reserved context automatically.
			((PLPX_RESERVED)packet->ProtocolReserved)->ExternalReserved = externalReserved;

			// Initialize LPX reserved context instead of RcvPacketAlloc().
			RESERVED(packet)->Cloned = 0;
			RESERVED(packet)->Type = LPX_PACKET_TYPE_RECEIVE;
			RESERVED(packet)->RecvFlags |= LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT;

			// set data offset
			// Because NDIS miniport allocated the packet, the NDIS packet contains whole raw packet data.
			rawDataOffset = ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize;
			lpxPayload += rawDataOffset;

			// return one reference count indicating LPX will call NdisReturnPackets() once.
			pktReferenceCount = 1;

		}
	}

	if (status != NDIS_STATUS_SUCCESS) {

		return 0;
	}

	//
	// Init LPX reserved context
	//

	LpxCopyEthLpxHeadersToLpxReserved(packet, firstBuffer, protocol, lpxHeader, lpxHeaderSize);
	RESERVED(Packet)->Packet = packet;
	RESERVED(Packet)->RecvTime = CurrentTime();
	RESERVED(Packet)->PacketRawDataLength = lpxPayload;
	RESERVED(Packet)->PacketRawDataOffset = rawDataOffset;

	//
	// Queue to the device context.
	//

	ExInterlockedInsertTailList( &deviceContext->PacketInProgressList,
								 &(RESERVED(Packet)->ListEntry),
								 &deviceContext->PacketInProgressQSpinLock );


	return pktReferenceCount;
}
Example #4
0
VOID
NdisProtSendComplete(
    IN NDIS_HANDLE                  ProtocolBindingContext,
    IN PNDIS_PACKET                 pNdisPacket,
    IN NDIS_STATUS                  Status
)
/*++

Routine Description:

    NDIS entry point called to signify completion of a packet send.
    We pick up and complete the Write IRP corresponding to this packet.

    NDIS 5.1:

Arguments:

    ProtocolBindingContext - pointer to open context
    pNdisPacket - packet that completed send
    Status - status of send

Return Value:

    None

--*/
{
    PIRP                        pIrp;
    PIO_STACK_LOCATION          pIrpSp;
    PNDISPROT_OPEN_CONTEXT       pOpenContext;

    pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext;
    NPROT_STRUCT_ASSERT(pOpenContext, oc);

    pIrp = NPROT_IRP_FROM_SEND_PKT(pNdisPacket);

    if (pOpenContext->bRunningOnWin9x)
    {
        //
        //  We would have attached our own NDIS_BUFFER. Take it out
        //  and free it.
        //
#ifndef NDIS51
        PNDIS_BUFFER                pNdisBuffer;
        PVOID                       VirtualAddr;
        UINT                        BufferLength;
        UINT                        TotalLength;
#endif

#ifdef NDIS51
        NPROT_ASSERT(FALSE); // NDIS 5.1 not on Win9X!
#else
        NdisGetFirstBufferFromPacket(
            pNdisPacket,
            &pNdisBuffer,
            &VirtualAddr,
            &BufferLength,
            &TotalLength);

        NPROT_ASSERT(pNdisBuffer != NULL);
        NdisFreeBuffer(pNdisBuffer);
#endif
    }


#ifdef NDIS51
    IoSetCancelRoutine(pIrp, NULL);

    NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);

    NPROT_REMOVE_ENTRY_LIST(&pIrp->Tail.Overlay.ListEntry);

    NPROT_RELEASE_LOCK(&pOpenContext->Lock);
#endif

    //
    //  We are done with the NDIS_PACKET:
    //
    NPROT_DEREF_SEND_PKT(pNdisPacket);

    //
    //  Complete the Write IRP with the right status.
    //
    pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
    if (Status == NDIS_STATUS_SUCCESS)
    {
        pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length;
        pIrp->IoStatus.Status = STATUS_SUCCESS;
    }
    else
    {
        pIrp->IoStatus.Information = 0;
        pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
    }

    DEBUGP(DL_INFO, ("SendComplete: packet %p/IRP %p/Length %d "
                     "completed with status %x\n",
                     pNdisPacket, pIrp, pIrp->IoStatus.Information, pIrp->IoStatus.Status));

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    NdisInterlockedDecrement((PLONG)&pOpenContext->PendedSendCount);

    NPROT_DEREF_OPEN(pOpenContext); // send complete - dequeued send IRP
}
Example #5
0
UINT CopyPacketToBufferChain(
    PNDIS_BUFFER DstBuffer,
    UINT DstOffset,
    PNDIS_PACKET SrcPacket,
    UINT SrcOffset,
    UINT Length)
/*
 * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain
 * ARGUMENTS:
 *     DstBuffer = Pointer to destination NDIS buffer
 *     DstOffset = Destination start offset
 *     SrcPacket = Pointer to source NDIS packet
 *     SrcOffset = Source start offset
 *     Length    = Number of bytes to copy
 * RETURNS:
 *     Number of bytes copied to destination buffer
 * NOTES:
 *     The number of bytes copied may be limited by the source and
 *     destination buffer sizes
 */
{
    PNDIS_BUFFER SrcBuffer;
    PCHAR DstData, SrcData;
    UINT DstSize, SrcSize;
    UINT Count, Total;

    TI_DbgPrint(DEBUG_PBUFFER, ("DstBuffer (0x%X)  DstOffset (0x%X)  SrcPacket (0x%X)  SrcOffset (0x%X)  Length (%d)\n", DstBuffer, DstOffset, SrcPacket, SrcOffset, Length));

    /* Skip DstOffset bytes in the destination buffer chain */
    NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
    if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1)
        return 0;

    /* Skip SrcOffset bytes in the source packet */
    NdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, (PVOID)&SrcData, &SrcSize, &Total);
    if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1)
        return 0;

    /* Copy the data */
    for (Total = 0;;) {
        /* Find out how many bytes we can copy at one time */
        if (Length < SrcSize)
            Count = Length;
        else
            Count = SrcSize;
        if (DstSize < Count)
            Count = DstSize;

        RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count);

        Total  += Count;
        Length -= Count;
        if (Length == 0)
            break;

        DstSize -= Count;
        if (DstSize == 0) {
            /* No more bytes in destination buffer. Proceed to
               the next buffer in the destination buffer chain */
            NdisGetNextBuffer(DstBuffer, &DstBuffer);
            if (!DstBuffer)
                break;

            NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
        }

        SrcSize -= Count;
        if (SrcSize == 0) {
            /* No more bytes in source buffer. Proceed to
               the next buffer in the source buffer chain */
            NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
            if (!SrcBuffer)
                break;

            NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
        }
    }

    return Total;
}
Example #6
0
//* SRPacketFromPkt
//
//  Parses an LQSR packet into an SRPacket.
//
NDIS_STATUS
SRPacketFromPkt(
    MiniportAdapter *VA,
    NDIS_PACKET *Packet,
    SRPacket **pSRP)
{
    uchar MAC[LQSR_MAC_LENGTH];
    SRPacket *SRP;
    void *OrigHeader;
    EtherHeader *OrigEther;
    LQSRHeader *OrigLQSR;
    NDIS_BUFFER *OrigBuffer;
    uint OrigBufferLength;
    uint HeaderLength;
    uint OrigPacketLength;
    InternalRouteRequest *Req;
    InternalRouteReply *Rep;
    InternalRouteError *Err;
    InternalAcknowledgementRequest *AckReq;
    InternalAcknowledgement *Ack;
    InternalSourceRoute *SR;
    InternalInfoRequest *InfoReq;
    InternalInfoReply *InfoRep;
    InternalProbe *Pro;
    InternalProbeReply *ProRep;
    InternalLinkInfo *LI;

    //
    // NB: Below code assumes the entire LQSR header is contiguous.
    //

    NdisGetFirstBufferFromPacket(Packet, &OrigBuffer, &OrigHeader,
                                 &OrigBufferLength, &OrigPacketLength);
    ASSERT(OrigBufferLength <= OrigPacketLength);
    if (OrigBufferLength < sizeof(EtherHeader) + sizeof(LQSRHeader))
        return NDIS_STATUS_BUFFER_TOO_SHORT;

    OrigEther = (EtherHeader *) OrigHeader;
    OrigLQSR = (LQSRHeader *) (OrigEther + 1);

    HeaderLength = (sizeof(EtherHeader) +
                    sizeof(LQSRHeader) +
                    OrigLQSR->HeaderLength);

    if (OrigBufferLength < HeaderLength)
        return NDIS_STATUS_BUFFER_TOO_SHORT;

    //
    // Verify the MAC.
    //
    SRPacketMAC(VA, MAC, Packet);
    if (! RtlEqualMemory(MAC, OrigLQSR->MAC, LQSR_MAC_LENGTH)) {
        InterlockedIncrement((PLONG)&VA->CountRecvBadMAC); 
        return NDIS_STATUS_INVALID_PACKET; 
    }

    SRP = ExAllocatePool(NonPagedPool, sizeof *SRP);
    if (SRP == NULL)
        return NDIS_STATUS_RESOURCES;
    RtlZeroMemory(SRP, sizeof *SRP);

    //
    // Parse the LQSR header options.
    //
    SRP = FillSRPacket(SRP, OrigLQSR);
    if (SRP == NULL) {
        //
        // Illegal packet format. FillSRPacket freed SRP.
        //
        return NDIS_STATUS_INVALID_PACKET;
    }

    //
    // Extract virtual source/destination addresses from the LQSR header.
    //
    if (SRP->sr != NULL) {
        uint Hops = SOURCE_ROUTE_HOPS(SRP->sr->opt.optDataLen);
        RtlCopyMemory(SRP->Source, SRP->sr->opt.hopList[0].addr, SR_ADDR_LEN);
        RtlCopyMemory(SRP->Dest, SRP->sr->opt.hopList[Hops - 1].addr,
                      SR_ADDR_LEN);
    }
    else if (SRP->req != NULL) {
        RtlCopyMemory(SRP->Source, SRP->req->opt.hopList[0].addr, SR_ADDR_LEN);
        RtlCopyMemory(SRP->Dest, SRP->req->opt.targetAddress, SR_ADDR_LEN);
    }
    else if ((SRP->ack != NULL) || (SRP->Probe != NULL) ||
             (SRP->ProbeReply != NULL)) {
        //
        // We don't have virtual source/destination addresses.
        //
        RtlZeroMemory(SRP->Source, SR_ADDR_LEN);
        RtlZeroMemory(SRP->Dest, SR_ADDR_LEN);
    }
    else {
        KdPrint(("MCL!Packet missing RR/SR/Ack!\n"));
        SRPacketFree(SRP);
        return NDIS_STATUS_INVALID_PACKET;
    }

    //
    // Acknowledgement Requests need a Source Route.
    //
    if ((SRP->ackreq != NULL) && (SRP->sr == NULL)) {
        KdPrint(("MCL!Packet with AckReq missing SR!\n"));
        SRPacketFree(SRP);
        return NDIS_STATUS_INVALID_PACKET;
    }

    //
    // Save information about the original packet.
    // NB: Calling SRPacketFree after doing this
    // and before our caller initializes SRP->FreePacket
    // will cause a bugcheck.
    //
    SRP->Packet = Packet;
    SRP->PacketLength = OrigPacketLength;
    SRP->PayloadOffset = HeaderLength;

    //
    // Save some info for later.
    //
    RtlCopyMemory(SRP->EtherDest, OrigEther->Dest, SR_ADDR_LEN);
    RtlCopyMemory(SRP->EtherSource, OrigEther->Source, SR_ADDR_LEN);
    RtlCopyMemory(SRP->IV, OrigLQSR->IV, LQSR_IV_LENGTH);

    //
    // Increment our counters.
    //
    for (Req = SRP->req; Req != NULL; Req = Req->next)
        InterlockedIncrement((PLONG)&VA->CountRecvRouteRequest);
    for (Rep = SRP->rep; Rep != NULL; Rep = Rep->next)
        InterlockedIncrement((PLONG)&VA->CountRecvRouteReply);
    for (Err = SRP->err; Err != NULL; Err = Err->next)
        InterlockedIncrement((PLONG)&VA->CountRecvRouteError);
    for (AckReq = SRP->ackreq; AckReq != NULL; AckReq = AckReq->next)
        InterlockedIncrement((PLONG)&VA->CountRecvAckRequest);
    for (Ack = SRP->ack; Ack != NULL; Ack = Ack->next)
        InterlockedIncrement((PLONG)&VA->CountRecvAck);
    for (SR = SRP->sr; SR != NULL; SR = SR->next)
        InterlockedIncrement((PLONG)&VA->CountRecvSourceRoute);
    for (InfoReq = SRP->inforeq; InfoReq != NULL; InfoReq = InfoReq->next)
        InterlockedIncrement((PLONG)&VA->CountRecvInfoRequest);
    for (InfoRep = SRP->inforep; InfoRep != NULL; InfoRep = InfoRep->next)
        InterlockedIncrement((PLONG)&VA->CountRecvInfoReply);
    for (Pro = SRP->Probe; Pro != NULL; Pro = Pro->Next)
        InterlockedIncrement((PLONG)&VA->CountRecvProbe);
    for (ProRep = SRP->ProbeReply; ProRep != NULL; ProRep = ProRep->Next)
        InterlockedIncrement((PLONG)&VA->CountRecvProbeReply);
    for (LI = SRP->LinkInfo; LI != NULL; LI = LI->Next)
        InterlockedIncrement((PLONG)&VA->CountRecvLinkInfo);

    *pSRP = SRP;
    return NDIS_STATUS_SUCCESS;
}
Example #7
0
//* CheckPacket
//
//  This is a combination of SRPacketFromPkt and FillSRPacket
//  that just sanity-checks the packet, for debugging purposes.
//
NDIS_STATUS
CheckPacket(
    MiniportAdapter *VA,
    NDIS_PACKET *Packet)
{
    uchar MAC[LQSR_MAC_LENGTH];
    void *OrigHeader;
    EtherHeader *OrigEther;
    LQSRHeader *OrigLQSR;
    NDIS_BUFFER *OrigBuffer;
    uint OrigBufferLength;
    uint HeaderLength;
    uint OrigPacketLength;

    LQSROption *Walk;
    uint Left;

    //
    // NB: Below code assumes the entire LQSR header is contiguous.
    //

    NdisGetFirstBufferFromPacket(Packet, &OrigBuffer, &OrigHeader,
                                 &OrigBufferLength, &OrigPacketLength);
    ASSERT(OrigBufferLength <= OrigPacketLength);
    if (OrigBufferLength < sizeof(EtherHeader) + sizeof(LQSRHeader)) {
        KdPrint(("MCL!CheckPacket: header truncated\n"));
        return NDIS_STATUS_BUFFER_TOO_SHORT;
    }

    OrigEther = (EtherHeader *) OrigHeader;
    OrigLQSR = (LQSRHeader *) (OrigEther + 1);

    HeaderLength = (sizeof(EtherHeader) +
                    sizeof(LQSRHeader) +
                    OrigLQSR->HeaderLength);

    if (OrigBufferLength < HeaderLength) {
        KdPrint(("MCL!CheckPacket: options truncated\n"));
        return NDIS_STATUS_BUFFER_TOO_SHORT;
    }

    //
    // Verify the MAC.
    //
    SRPacketMAC(VA, MAC, Packet);
    if (! RtlEqualMemory(MAC, OrigLQSR->MAC, LQSR_MAC_LENGTH)) {
        KdPrint(("MCL!CheckPacket: bad MAC\n"));
        return NDIS_STATUS_INVALID_PACKET;
    }

    //
    // Walk the options and verify them.
    //

    Walk = (LQSROption *)(OrigLQSR + 1);
    Left = OrigLQSR->HeaderLength;

    while (Left != 0) {
        //
        // Verify that we have enough data to match what the option
        // itself claims is present.
        //
        if ((Left < sizeof *Walk) ||
            (Left < sizeof *Walk + Walk->optDataLen)) {
            KdPrint(("MCL!CheckPacket: bad option length\n"));
            return NDIS_STATUS_INVALID_PACKET;
        }

        switch (Walk->optionType) {

        case LQSR_OPTION_TYPE_REQUEST:
            //
            // Route Request options must have at least one hop,
            // because the sending node includes itself.
            //
            if (Walk->optDataLen < ROUTE_REQUEST_LEN(1)) {
                KdPrint(("MCL!CheckPacket: bad request\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case LQSR_OPTION_TYPE_REPLY:
            //
            // Route Replies must have at least two hops.
            //
            if (Walk->optDataLen < ROUTE_REPLY_LEN(2)) {
                KdPrint(("MCL!CheckPacket: bad reply\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case LQSR_OPTION_TYPE_ERROR:
            if (Walk->optDataLen != ROUTE_ERROR_LENGTH) {
                KdPrint(("MCL!CheckPacket: bad error\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case LQSR_OPTION_TYPE_SOURCERT:
            //
            // Source Routes must have at least two hops.
            //
            if (Walk->optDataLen < SOURCE_ROUTE_LEN(2)) {
                KdPrint(("MCL!CheckPacket: bad SR\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }

            //
            // Sanity-check segmentsLeft.
            //
            if ((((SourceRoute *)Walk)->segmentsLeft == 0) ||
                (((SourceRoute *)Walk)->segmentsLeft >=
                 SOURCE_ROUTE_HOPS(Walk->optDataLen))) {
                KdPrint(("MCL!CheckPacket: bad segmentsLeft\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case LQSR_OPTION_TYPE_ACKREQ:
            if (Walk->optDataLen != ACK_REQUEST_LEN) {
                KdPrint(("MCL!CheckPacket: bad ack req\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case LQSR_OPTION_TYPE_ACK:
            if (Walk->optDataLen != ACKNOWLEDGEMENT_LEN) {
                KdPrint(("MCL!CheckPacket: bad ack\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case LQSR_OPTION_TYPE_INFOREQ:
            if (Walk->optDataLen != INFO_REQUEST_LEN) {
                KdPrint(("MCL!CheckPacket: bad info req\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case LQSR_OPTION_TYPE_INFO:
            if (Walk->optDataLen != INFO_REPLY_LEN) {
                KdPrint(("MCL!CheckPacket: bad info reply\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case LQSR_OPTION_TYPE_PROBE:
            //
            // First, make sure that we have enough
            // data left to read ProbeType correctly. 
            //
            if (Walk->optDataLen < PROBE_LEN) {
                KdPrint(("MCL!CheckPacket: bad probe\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }

            switch (((Probe *)Walk)->ProbeType) {
            case METRIC_TYPE_RTT:
                if (Walk->optDataLen != PROBE_LEN) {
                    KdPrint(("MCL!CheckPacket: bad rtt\n"));
                    return NDIS_STATUS_INVALID_PACKET;
                }
                break;
            case METRIC_TYPE_PKTPAIR:
                if (Walk->optDataLen != PROBE_LEN) {
                    KdPrint(("MCL!CheckPacket: bad pktpair\n"));
                    return NDIS_STATUS_INVALID_PACKET;
                }
                break;
            case METRIC_TYPE_ETX:
                if (Walk->optDataLen != PROBE_LEN + sizeof(EtxProbe)) {
                    KdPrint(("MCL!CheckPacket: bad etx\n"));
                    return NDIS_STATUS_INVALID_PACKET;
                }
                break;
            default:
                KdPrint(("MCL!CheckPacket: bad probe type\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case LQSR_OPTION_TYPE_PROBEREPLY:
            //
            // First, make sure that we have enough
            // data left to read ProbeType correctly. 
            //
            if (Walk->optDataLen < PROBE_REPLY_LEN) {
                KdPrint(("MCL!CheckPacket: bad probe reply\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }

            switch (((Probe *)Walk)->ProbeType) {
            case METRIC_TYPE_RTT:
                if (Walk->optDataLen != PROBE_REPLY_LEN) {
                    KdPrint(("MCL!CheckPacket: bad rtt reply\n"));
                    return NDIS_STATUS_INVALID_PACKET;
                }
            case METRIC_TYPE_PKTPAIR:
                if (Walk->optDataLen != PROBE_REPLY_LEN + sizeof(PRPktPair)) {
                    KdPrint(("MCL!CheckPacket: bad pktpair reply\n"));
                    return NDIS_STATUS_INVALID_PACKET;
                }
                break;
            default:
                KdPrint(("MCL!CheckPacket: bad probe reply type\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case LQSR_OPTION_TYPE_LINKINFO:
            //
            // LinkInfo options must contain at least one entry.
            //
            if (Walk->optDataLen < LINKINFO_LEN(1)) {
                KdPrint(("MCL!CheckPacket: bad linkinfo\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        default:
            KdPrint(("MCL!CheckPacket: bad option type\n"));
            return NDIS_STATUS_INVALID_PACKET;
        }

        //
        // Move on to the next option (if any).
        //
        Left -= sizeof(LQSROption) + Walk->optDataLen;
        (uchar *)Walk += sizeof(LQSROption) + Walk->optDataLen;
    }

    return NDIS_STATUS_SUCCESS;
}
Example #8
0
INT
LpxProtocolReceivePacket (
	IN NDIS_HANDLE	ProtocolBindingContext,
	IN PNDIS_PACKET	Packet
	)
{
	PDEVICE_CONTEXT	deviceContext;

	PLPX_RESERVED	reserved = NULL;	

	PNDIS_BUFFER	ndisFirstBuffer;
	PVOID			firstBuffer;
	UINT		    firstBufferSize;
	UINT			totalBufferSize;
	PNDIS_PACKET	packet = NULL;
	NDIS_STATUS		status;
	INT				pktReferenceCount = 0;
	UINT		    addiLlcHeaderSize = 0;
	PLPX_HEADER		lpxHeader;
	USHORT			lpxHeaderSize;
	UINT			lpxPayload;
	UINT			rawDataOffset;
	ETHERNET_HEADER	ethernetHeader;

	DebugPrint( 4, ("ProtocolReceivePacket: Entered\n") );
	
	deviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext;

	//	Check to see if the device context is initialized.

	if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) || FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) {

		DebugPrint( 1, ("Device is not initialized. Drop packet\n") );

		return NDIS_STATUS_NOT_RECOGNIZED;
	}

	NDAS_ASSERT( deviceContext->NdisBindingHandle );

	//	validation

#ifndef NTDDI_VERSION

	NdisGetFirstBufferFromPacket( Packet,
								  &ndisFirstBuffer,
								  &firstBuffer,
								  &firstBufferSize,
								  &totalBufferSize );
#else

	firstBufferSize = 0;
	
	NdisGetFirstBufferFromPacketSafe( Packet,
									  &ndisFirstBuffer,
									  &firstBuffer,
									  &firstBufferSize,
									  &totalBufferSize,
									  HighPagePriority );
#endif

	if (firstBufferSize < ETHERNET_HEADER_LENGTH) {

		NDAS_ASSERT(FALSE);

		DebugPrint( 2, ("ProtocolReceivePacket: FirstBufferSize = %x\n", firstBufferSize) );
		return 0;
	}

	RtlCopyMemory( &ethernetHeader, firstBuffer, ETHERNET_HEADER_LENGTH );

	if (ethernetHeader.DestinationAddress[5] != 0xFF) {

		DebugPrint( 3, ("LpxProtocolReceivePacket: Type = %X\n", ethernetHeader.Type) );	
	}

	//	Discard 802.2 LLC SNAP field.
	//
	// if Ether Type less than 0x0600 ( 1536 )

	if (NTOHS(ethernetHeader.Type)  < 0x0600 && 
		NTOHS(ethernetHeader.Type) != 0x0060 && // LOOP:  Ethernet Loopback
		NTOHS(ethernetHeader.Type) != 0x0200 && // PUP :  Xerox PUP packet
		NTOHS(ethernetHeader.Type) != 0x0201) { // PUPAP: Xerox PUP address trans packet 

		RtlCopyMemory( &ethernetHeader, 
					   (PUCHAR)firstBuffer + ETHERNET_HEADER_LENGTH + LENGTH_8022LLCSNAP - 2, 
					   ETHERNET_HEADER_LENGTH );

		if (firstBufferSize >= LENGTH_8022LLCSNAP) {

			firstBufferSize -= LENGTH_8022LLCSNAP;
		
		} else {

			DebugPrint( 2, ("ProtocolReceivePacket: Too small first buffer\n") );
			return 0;
		}

		if (totalBufferSize >= LENGTH_8022LLCSNAP) {

			totalBufferSize -= LENGTH_8022LLCSNAP;
		
		} else {

			DebugPrint( 2, ("ProtocolReceivePacket: Too small total buffer\n") );
			return 0;
		}

		addiLlcHeaderSize = LENGTH_8022LLCSNAP;

		NDAS_ASSERT( ethernetHeader.Type != HTONS(ETH_P_LPX) );
	}

	if (ethernetHeader.Type != HTONS(ETH_P_LPX)) {
	
		DebugPrint( 4, ("ProtocolReceivePacket: Type = %x\n", ethernetHeader.Type) );
		return 0;
	}

	if (totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + sizeof(LPX_HEADER)) {

		DebugPrint( 2, ("ProtocolReceivePacket: too small packet(1).\n"));
		return 0;
	}

	// DROP PACKET for DEBUGGING!!!!

	if (PacketRxDropRate) {

		PacketRxCountForDrop++;
				
		if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) {

			PLPX_HEADER        lpxHeader = (PLPX_HEADER)((PUCHAR)firstBuffer + addiLlcHeaderSize);

			if ((PacketRxCountForDrop % (PacketRxDropRate*20)) == 0) {

				DebugPrint( 6, ("[Drop(%x,%x,%x))]\n", 
								 NTOHS(lpxHeader->Lsctl), NTOHS(lpxHeader->Sequence), NTOHS(lpxHeader->AckSequence)) );
			}

			DebugPrint( 2, ("D\n") );

			return 0;
		}
	}

	if (!(RtlEqualMemory(ethernetHeader.DestinationAddress, deviceContext->LocalAddress.Address, ETHERNET_ADDRESS_LENGTH) ||
		  RtlEqualMemory(ethernetHeader.DestinationAddress, LpxBroadcastAddress, ETHERNET_ADDRESS_LENGTH))) {

		DebugPrint( 4, ("LpxProtocolReceivePacket, %02x%02x%02x%02x%02x%02x\n",
						 deviceContext->LocalAddress.Address[0], deviceContext->LocalAddress.Address[1], 
						 deviceContext->LocalAddress.Address[2], deviceContext->LocalAddress.Address[3], 
						 deviceContext->LocalAddress.Address[4], deviceContext->LocalAddress.Address[5]) );

		DebugPrint( 4, ("LpxProtocolReceivePacket, %02x%02x%02x%02x%02x%02x\n",
						 ethernetHeader.DestinationAddress[0], ethernetHeader.DestinationAddress[1], 
						 ethernetHeader.DestinationAddress[2], ethernetHeader.DestinationAddress[3], 
						 ethernetHeader.DestinationAddress[4], ethernetHeader.DestinationAddress[5]) );

		return 0;
	}

	// Extract LPX header information

	lpxHeader = (PLPX_HEADER)((PBYTE)firstBuffer + ETHERNET_HEADER_LENGTH + addiLlcHeaderSize);
	lpxHeaderSize = sizeof(LPX_HEADER);
	lpxPayload = NTOHS((UINT16)(lpxHeader->PacketSize & ~LPX_TYPE_MASK)) - lpxHeaderSize;

	if (lpxHeader->DestinationPort == NTOHS(LPXRP_HIX_PORT)) {

		DebugPrint( 1, ("[LPX] LpxProtocolReceivePacket: DataGram packet arrived.\n") );
	}

#if __LPX_OPTION_ADDRESSS__

	if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) {

		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
	}

	if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) {

		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
	}

#endif

	if (totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize + lpxPayload) {

		DebugPrint( 2, ("ProtocolReceivePacket: too small packet(2).\n") );

		return 0;
	}

	NDAS_ASSERT( addiLlcHeaderSize == 0 );

	DebugPrint( 4, ("ProtocolReceivePacket: TotalBuffSz = %d, FirstBuffSz = %d, LPX_HEADER size = %d\n",
					 totalBufferSize, firstBufferSize, sizeof(LPX_HEADER)) );

	//  If the miniport is out of resources, we can't queue
	//  this packet - make a copy if this is so.

	NDAS_ASSERT( sizeof(ZeroProtocolReserved) == PROTOCOL_RESERVED_OFFSET );

	if (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES ||
		!RtlEqualMemory(&Packet->ProtocolReserved[PROTOCOL_RESERVED_OFFSET], ZeroProtocolReserved, sizeof(ZeroProtocolReserved))) {

		UINT bytesCopied;
		INT  i;

		for (i=0; i<16; i++) {

			DebugPrint( 1, ("Packet->ProtocolReserved[%d] = %d\n", i, Packet->ProtocolReserved[i]) );
		}

		NDAS_ASSERT(FALSE);

		DebugPrint( 2, ("ProtocolReceivePacket: Miniport reported low packet resources.\n") );

		status = RcvPacketAlloc( deviceContext, lpxPayload, &packet );

		if (status == STATUS_SUCCESS) {

			NDAS_ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS );

			// Copy lpx payload. payload contains only data.

			NdisCopyFromPacketToPacket( packet, 
										0,
										lpxPayload,
										Packet, 
										ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize,
										&bytesCopied
										);

			NDAS_ASSERT( lpxPayload == bytesCopied );
		}

		rawDataOffset = 0;
		pktReferenceCount = 0;
	
	} else {
	
		PLPX_RESERVED externalReserved;

		// No need to allocate new NDIS packet and copy data to the new NDIS packet.
		// But, NDIS miniport allocates only 4 * sizeof(PVOID) for protocol reserved context.
		// We should allocate our own.

		packet = Packet;

		status = NdisAllocateMemoryWithTag( &externalReserved, sizeof(LPX_RESERVED), LPX_MEM_TAG_EXTERNAL_RESERVED );

		if (status == NDIS_STATUS_SUCCESS) {

			RtlZeroMemory( externalReserved, sizeof(LPX_RESERVED) );

			// By setting the external reserved field, LpxGetReserved() uses external reserved context automatically.

			((PLPX_RESERVED)(&packet->ProtocolReserved[PROTOCOL_RESERVED_OFFSET]))->ExternalReserved = externalReserved;

			reserved = LpxGetReserved(packet);

			// Initialize LPX reserved context instead of RcvPacketAlloc().

			reserved->Cloned = 0;
			reserved->Type = LPX_PACKET_TYPE_RECEIVE;
			reserved->RecvFlags |= LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT;

			// set data offset
			// Because NDIS miniport allocated the packet, the NDIS packet contains whole raw packet data.

			rawDataOffset = ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize;
			lpxPayload += rawDataOffset;

			// return one reference count indicating LPX will call NdisReturnPackets() once.

			pktReferenceCount = 1;
		}
	}

	if (status != NDIS_STATUS_SUCCESS) {

		DebugPrint( 2, ("ProtocolReceivePacket: status != NDIS_STATUS_SUCCESS\n") );
		return 0;
	}

	// Init LPX reserved context

	LpxCopyEthLpxHeadersToLpxReserved( packet, firstBuffer, ethernetHeader.Type, lpxHeader, lpxHeaderSize );

	reserved = LpxGetReserved(packet);

	reserved->Packet = packet;
	reserved->RecvTime = NdasCurrentTime();
	reserved->PacketRawDataLength = lpxPayload;
	reserved->PacketRawDataOffset = rawDataOffset;

	// Queue to the device context.

	ExInterlockedInsertTailList( &deviceContext->PacketInProgressList,
								 &(reserved->ListEntry),
								 &deviceContext->PacketInProgressQSpinLock );

	return pktReferenceCount;
}
VOID
SecLabFreeReceivePacket(
	PADAPT                          pAdapt,
    IN PNDIS_PACKET                 pNdisPacket
    )
/*++

Routine Description:

    释放所有与接收包相关的资源。如果这是一个本地拷贝,将此包释放到接收包池
	。否则释放到miniport.

Arguments:
    pNdisPacket - 指向要释放的包的指针

Return Value:

    None

--*/
{
    PNDIS_BUFFER        pNdisBuffer;
    UINT                TotalLength;
    UINT                BufferLength;
    PUCHAR              pCopyData;

    if (NdisGetPoolFromPacket(pNdisPacket) ==pAdapt->RecvPacketPoolHandle)
    {
        //
        //  This is a local copy.
        //
		
#ifdef NDIS51
		    NdisGetFirstBufferFromPacketSafe(
            pNdisPacket,
            &pNdisBuffer,
            (PVOID *)&pCopyData,
            &BufferLength,
            &TotalLength,
            NormalPagePriority);
#else
            NdisGetFirstBufferFromPacket(
            pNdisPacket,
            &pNdisBuffer,
            (PVOID *)&pCopyData,
            &BufferLength,
            &TotalLength);
#endif

        if(BufferLength != TotalLength || pNdisBuffer==NULL || pCopyData==NULL)
		{
			DbgPrint("Error! Failed in Free a Packet");
			DbgBreakPoint();
		}

        NdisFreePacket(pNdisPacket);

        NdisFreeBuffer(pNdisBuffer);

        NdisFreeMemory(pCopyData,0,0);

    }
    else
    {
        NdisReturnPackets(&pNdisPacket, 1);
    }
}