Пример #1
0
VOID FreeNdisPacket
( PNDIS_PACKET Packet )
/*
 * FUNCTION: Frees an NDIS packet
 * ARGUMENTS:
 *     Packet = Pointer to NDIS packet to be freed
 */
{
    PNDIS_BUFFER Buffer, NextBuffer;

    TI_DbgPrint(DEBUG_PBUFFER, ("Packet (0x%X)\n", Packet));

    /* Free all the buffers in the packet first */
    NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL);
    for (; Buffer != NULL; Buffer = NextBuffer) {
        PVOID Data;
        UINT Length;

        NdisGetNextBuffer(Buffer, &NextBuffer);
        NdisQueryBuffer(Buffer, &Data, &Length);
	TI_DbgPrint(DEBUG_PBUFFER, ("Freeing ndis buffer (0x%X)\n", Buffer));
        NdisFreeBuffer(Buffer);
	TI_DbgPrint(DEBUG_PBUFFER, ("Freeing exal buffer (0x%X)\n", Data));
        ExFreePoolWithTag(Data, PACKET_BUFFER_TAG);
    }

    /* Finally free the NDIS packet discriptor */
    NdisFreePacket(Packet);
}
Пример #2
0
VOID FreeNdisPacketX
( PNDIS_PACKET Packet,
  PCHAR File,
  UINT Line )
/*
 * FUNCTION: Frees an NDIS packet
 * ARGUMENTS:
 *     Packet = Pointer to NDIS packet to be freed
 */
{
    PNDIS_BUFFER Buffer, NextBuffer;

    TI_DbgPrint(DEBUG_PBUFFER, ("Packet (0x%X)\n", Packet));

    /* Free all the buffers in the packet first */
    NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL);
    for (; Buffer != NULL; Buffer = NextBuffer) {
        PVOID Data;
        UINT Length;

        NdisGetNextBuffer(Buffer, &NextBuffer);
        XNdisQueryBuffer(Buffer, &Data, &Length);
	UntrackFL(File,Line,Buffer);
        NdisFreeBuffer(Buffer);
        exFreePool(Data);
    }

    /* Finally free the NDIS packet descriptor */
    UntrackFL(File,Line,Packet);
    NdisFreePacket(Packet);
}
Пример #3
0
BOOLEAN
FilterPacket_ReceiveHandler (
	PVOID pHeadBuffer,
	ULONG ulHeadSize,
	PNDIS_PACKET pPacket
	)
/*++

Routine Description:

	Filters network packets for NDISReceiveHandler.


Arguments:

	...


Return Value:

	TRUE: This packet should be blocked.

	FALSE: This packet should pass through.


Author:

	xiaonie

	2012/07/12


--*/
{
	ULONG ulPacketSize;
	PUCHAR pBuffer = NULL;
	NDIS_STATUS status;
	PNDIS_BUFFER pFirstBuffer, pNextBuffer;
	BOOLEAN bRet = FALSE;

	NdisQueryPacket(pPacket, NULL, NULL, NULL, &ulPacketSize);
	if (ulPacketSize == 0)
		return FALSE;

	DbgPrint("ulHeadSize == %d, ulPacketSize == %d in FilterPacket_ReceiveHandler!\r\n", ulHeadSize, ulPacketSize);

	status = NdisAllocateMemoryWithTag(&pBuffer, ulPacketSize + ulHeadSize, '!nmN');
	if (status != NDIS_STATUS_SUCCESS/* || pBuffer == NULL */)
		return FALSE;

	//obtain content from the packet
	NdisMoveMemory(pBuffer, pHeadBuffer, ulHeadSize);
	ReadPacket(pPacket, pBuffer + ulHeadSize, ulPacketSize);

	bRet = RabbitHole(pBuffer, ulPacketSize + ulHeadSize);

	NdisFreeMemory(pBuffer, ulPacketSize + ulHeadSize, 0);

	return bRet;
}
Пример #4
0
PVOID AdjustPacket(
    PNDIS_PACKET Packet,
    UINT Available,
    UINT Needed)
/*
 * FUNCTION: Adjusts the amount of unused space at the beginning of the packet
 * ARGUMENTS:
 *     Packet    = Pointer to packet
 *     Available = Number of bytes available at start of first buffer
 *     Needed    = Number of bytes needed for the header
 * RETURNS:
 *     Pointer to start of packet
 */
{
    PNDIS_BUFFER NdisBuffer;
    INT Adjust;

    TI_DbgPrint(DEBUG_PBUFFER, ("Available = %d, Needed = %d.\n", Available, Needed));

    Adjust = Available - Needed;

    NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);

    /* If Adjust is zero there is no need to adjust this packet as
       there is no additional space at start the of first buffer */
    if (Adjust != 0) {
        NdisBuffer->MappedSystemVa  = (PVOID) ((ULONG_PTR)(NdisBuffer->MappedSystemVa) + Adjust);
        NdisBuffer->ByteOffset     += Adjust;
        NdisBuffer->ByteCount      -= Adjust;
    }

    return NdisBuffer->MappedSystemVa;
}
Пример #5
0
/* Maps to ReceiverReleaseNetBufferList() in xennet6 */
static void
ReceiverReleasePacket(PRECEIVER Receiver, PNDIS_PACKET Packet)
{
    PMDL headMdl;

    NdisQueryPacket(Packet, NULL, NULL, &headMdl, NULL);
    ReceiverCommonReleaseMdlChain(&Receiver->Common, headMdl);
    NdisDprFreePacketNonInterlocked(Packet);
}
Пример #6
0
void GetDataPtr( PNDIS_PACKET Packet,
		 UINT Offset,
		 PCHAR *DataOut,
		 PUINT Size ) {
    PNDIS_BUFFER Buffer;

    NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL);
    if( !Buffer ) return;
    SkipToOffset( Buffer, Offset, DataOut, Size );
}
Пример #7
0
Boolean
ssh_wan_send_to_adapter(SshNdisIMAdapter adapter, 
                        SshNdisPacket packet,
                        SshInterceptorProtocol protocol)
{
  UINT pkt_len;
  SshUInt32 ppp_protocol;
  PUCHAR pos;
  ULONG len;
  PNDIS_WAN_PACKET wan_pkt;

  switch (protocol)
    {
    case SSH_PROTOCOL_IP4:
      ppp_protocol = SSH_PPP_PROTOCOL_IP4;
      break;
    case SSH_PROTOCOL_IP6:
      ppp_protocol = SSH_PPP_PROTOCOL_IP6;
      break;
    default:
      SSH_DEBUG(SSH_D_ERROR, ("Cannot PPP-encapsulate non-IP protocol"));
      return FALSE;
    }

  NdisQueryPacket(packet->np, NULL, NULL, NULL, &pkt_len);

  /* Allocate a buffer large enough a PPP header and the packet. */
  if (!(wan_pkt = ssh_wan_alloc_buffer_send(adapter, 4 + pkt_len)))
    goto fail;

  pos = wan_pkt->CurrentBuffer;
  len = 4 + pkt_len;

  /* Create PPP header. */
  if (!ssh_wan_encode_ppp_header(&pos, &len, ppp_protocol,
                                 adapter->ppp_send_flags))
    goto fail;

  /* Add the packet itself. */
  ssh_interceptor_packet_copyout(&packet->ip, 0, pos, pkt_len);
  pos += pkt_len;
  len -= pkt_len;

  wan_pkt->CurrentLength = pos - wan_pkt->CurrentBuffer;

  /* Send WAN packet to adapter. */
  ssh_wan_send_buffer(adapter, wan_pkt);
  return TRUE;

 fail:
  if (wan_pkt)
    ssh_wan_free_buffer_send(wan_pkt);
  return FALSE;
}
Пример #8
0
BOOLEAN
FilterPacket_ProtocolReceiveHandler (
	PNDIS_PACKET pPacket
	)
/*++

Routine Description:

	Filters network packets for NDISProtocolReceiveHandler.


Arguments:

	pPacket - Pointer to the packet buffer descriptor.


Return Value:

	TRUE: This packet should be blocked.

	FALSE: This packet should pass through.


Author:

	xiaonie

	2012/07/12


--*/
{
	ULONG ulTotalPacketLength;
	PUCHAR pBuffer = NULL;
	BOOLEAN bRet = FALSE;
	NDIS_STATUS status;

	NdisQueryPacket(pPacket, NULL, NULL, NULL, &ulTotalPacketLength);
	if (ulTotalPacketLength == 0)
		return FALSE;

	status = NdisAllocateMemoryWithTag(&pBuffer, ulTotalPacketLength, '!nmN');
	if (status != NDIS_STATUS_SUCCESS/* || pBuffer == NULL*/)
		return FALSE;

	ReadPacket(pPacket, pBuffer, ulTotalPacketLength);

	// filter it!
	bRet = RabbitHole(pBuffer, ulTotalPacketLength);

	NdisFreeMemory(pBuffer, ulTotalPacketLength, 0);

	return bRet;
}
Пример #9
0
Boolean
ssh_wan_send_to_protocol(SshNdisIMAdapter adapter, 
                         SshNdisPacket packet,
                         SshInterceptorProtocol protocol)
{
  UINT pkt_len;
  SshUInt32 ppp_protocol;
  PUCHAR buffer, pos;
  ULONG len;

  switch (protocol)
    {
    case SSH_PROTOCOL_IP4:
      ppp_protocol = SSH_PPP_PROTOCOL_IP4;
      break;
    case SSH_PROTOCOL_IP6:
      ppp_protocol = SSH_PPP_PROTOCOL_IP6;
      break;
    default:
      SSH_DEBUG(SSH_D_ERROR, ("Cannot PPP-encapsulate non-IP protocol"));
      return FALSE;
    }

  NdisQueryPacket(packet->np, NULL, NULL, NULL, &pkt_len);

  /* Allocate a buffer large enough a PPP header and the packet. */
  buffer = ssh_wan_alloc_buffer_receive(adapter, 4 + pkt_len);
  if (buffer == NULL)
    goto fail;

  pos = buffer;
  len = 4 + pkt_len;

  /* Create PPP header. */
  if (!ssh_wan_encode_ppp_header(&pos, &len, ppp_protocol,
                                adapter->ppp_receive_flags))
    goto fail;

  /* Add the packet itself. */
  ssh_interceptor_packet_copyout(&packet->ip, 0, pos, pkt_len);
  pos += pkt_len;
  len -= pkt_len;

  /* Indicate WAN packet to protocol. */
  ssh_wan_receive_buffer(adapter, buffer, pos - buffer);
  return TRUE;

 fail:
  if (buffer)
    ssh_wan_free_buffer_receive(buffer);
  return FALSE;
}
Пример #10
0
VOID
ArcFreeNdisPacket(
    IN PARC_PACKET Packet
    )
/*++

Routine description:

    This routine takes an arcnet packet and frees up the corresponding
    Ndis packet built for it.

Arguments:

    Packet - The packet to free up.

Return values:

    None

--*/
{
    PNDIS_BUFFER NdisBuffer, NextNdisBuffer;

    NdisQueryPacket(
        &(Packet->TmpNdisPacket),
        NULL,
        NULL,
        &NdisBuffer,
        NULL
        );

    while (NdisBuffer != NULL) {

        NdisGetNextBuffer(
            NdisBuffer,
            &NextNdisBuffer
            );

        NdisFreeBuffer(
            NdisBuffer
            );

        NdisBuffer = NextNdisBuffer;
    }

    NdisReinitializePacket(&(Packet->TmpNdisPacket));

}
/*----------------------------------------------------------------------------*/
VOID kalCopyFrame(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, OUT PUINT_8 pucDestBuffer)
{
	PNDIS_PACKET prNdisPacket;
	PNDIS_BUFFER prNdisBuffer, prNextNdisBuffer;
	UINT u4PacketLen;
	UINT u4BytesToCopy;
	PVOID pvMbuf;
	UINT u4MbufLength;
	UINT u4BytesCopied;

	ASSERT(pvPacket);

	prNdisPacket = (PNDIS_PACKET) pvPacket;
	NdisQueryPacket(prNdisPacket, NULL, NULL, &prNdisBuffer, &u4PacketLen);

	u4BytesToCopy = u4PacketLen;
	u4BytesCopied = 0;

	while (u4BytesToCopy != 0) {

#ifdef NDIS51_MINIPORT
		NdisQueryBufferSafe(prNdisBuffer, &pvMbuf, &u4MbufLength, HighPagePriority);
#else
		NdisQueryBuffer(prNdisBuffer, &pvMbuf, &u4MbufLength);
#endif				/* NDIS51_MINIPORT */

		if (pvMbuf == (PVOID) NULL) {
			ASSERT(pvMbuf);
			break;
		}

		NdisMoveMemory((PVOID) pucDestBuffer, pvMbuf, u4MbufLength);

		u4BytesToCopy -= u4MbufLength;
		u4BytesCopied += u4MbufLength;
		pucDestBuffer += u4MbufLength;

		NdisGetNextBuffer(prNdisBuffer, &prNextNdisBuffer);
		prNdisBuffer = prNextNdisBuffer;
	}

	ASSERT(u4BytesCopied == u4PacketLen);

	return;
}
Пример #12
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 */
}
Пример #13
0
UINT ResizePacket(
    PNDIS_PACKET Packet,
    UINT Size)
/*
 * FUNCTION: Resizes an NDIS packet
 * ARGUMENTS:
 *     Packet = Pointer to packet
 *     Size   = Number of bytes in first buffer
 * RETURNS:
 *     Previous size of first buffer
 */
{
    PNDIS_BUFFER NdisBuffer;
    UINT OldSize;

    NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);

    OldSize = NdisBuffer->ByteCount;

    if (Size != OldSize)
        NdisBuffer->ByteCount = Size;

    return OldSize;
}
Пример #14
0
NTSTATUS IPSendDatagram(PIP_PACKET IPPacket, PNEIGHBOR_CACHE_ENTRY NCE,
			PIP_TRANSMIT_COMPLETE Complete, PVOID Context)
/*
 * FUNCTION: Sends an IP datagram to a remote address
 * ARGUMENTS:
 *     IPPacket = Pointer to an IP packet
 *     RCN      = Pointer to route cache node
 * RETURNS:
 *     Status of operation
 * NOTES:
 *     This is the highest level IP send routine. It possibly breaks the packet
 *     into two or more fragments before passing it on to the next lower level
 *     send routine (IPSendFragment)
 */
{
    UINT PacketSize;

    TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X)  NCE (0x%X)\n", IPPacket, NCE));

    DISPLAY_IP_PACKET(IPPacket);
    /*OskitDumpBuffer( IPPacket->Header, IPPacket->TotalSize );*/

    /* Fetch path MTU now, because it may change */
    TI_DbgPrint(MID_TRACE,("PathMTU: %d\n", NCE->Interface->MTU));

    NdisQueryPacket(IPPacket->NdisPacket,
                    NULL,
                    NULL,
                    NULL,
                    &PacketSize);

    NCE->Interface->Stats.OutBytes += PacketSize;

    return SendFragments(IPPacket, NCE, NCE->Interface->MTU,
			 Complete, Context);
}
Пример #15
0
extern
VOID
Pc586CopyFromPacketToPacket(
    IN PNDIS_PACKET Destination,
    IN UINT DestinationOffset,
    IN UINT BytesToCopy,
    IN PNDIS_PACKET Source,
    IN UINT SourceOffset,
    OUT PUINT BytesCopied
    )

/*++

Routine Description:

    Copy from an ndis packet to an ndis packet.

Arguments:

    Destination - The packet should be copied in to.

    DestinationOffset - The offset from the beginning of the packet
    into which the data should start being placed.

    BytesToCopy - The number of bytes to copy from the source packet.

    Source - The ndis packet from which to copy data.

    SourceOffset - The offset from the start of the packet from which
    to start copying data.

    BytesCopied - The number of bytes actually copied from the source
    packet.  This can be less than BytesToCopy if the source or destination
    packet is too short.

Return Value:

    None

--*/

{

    //
    // Holds the count of the number of ndis buffers comprising the
    // destination packet.
    //
    UINT DestinationBufferCount;

    //
    // Holds the count of the number of ndis buffers comprising the
    // source packet.
    //
    UINT SourceBufferCount;

    //
    // Points to the buffer into which we are putting data.
    //
    PNDIS_BUFFER DestinationCurrentBuffer;

    //
    // Points to the buffer from which we are extracting data.
    //
    PNDIS_BUFFER SourceCurrentBuffer;

    //
    // Holds the virtual address of the current destination buffer.
    //
    PVOID DestinationVirtualAddress;

    //
    // Holds the virtual address of the current source buffer.
    //
    PVOID SourceVirtualAddress;

    //
    // Holds the length of the current destination buffer.
    //
    UINT DestinationCurrentLength;

    //
    // Holds the length of the current source buffer.
    //
    UINT SourceCurrentLength;

    //
    // Keep a local variable of BytesCopied so we aren't referencing
    // through a pointer.
    //
    UINT LocalBytesCopied = 0;

    //
    // Take care of boundary condition of zero length copy.
    //

    *BytesCopied = 0;
    if (!BytesToCopy) return;

    //
    // Get the first buffer of the destination.
    //

    NdisQueryPacket(
        Destination,
        NULL,
        &DestinationBufferCount,
        &DestinationCurrentBuffer,
        NULL
        );

    //
    // Could have a null packet.
    //

    if (!DestinationBufferCount) return;

    NdisQueryBuffer(
        DestinationCurrentBuffer,
        NULL,
        &DestinationVirtualAddress,
        &DestinationCurrentLength
        );

    //
    // Get the first buffer of the source.
    //

    NdisQueryPacket(
        Source,
        NULL,
        &SourceBufferCount,
        &SourceCurrentBuffer,
        NULL
        );

    //
    // Could have a null packet.
    //

    if (!SourceBufferCount) return;

    NdisQueryBuffer(
        SourceCurrentBuffer,
        NULL,
        &SourceVirtualAddress,
        &SourceCurrentLength
        );

    while (LocalBytesCopied < BytesToCopy) {

        //
        // Check to see whether we've exhausted the current destination
        // buffer.  If so, move onto the next one.
        //

        if (!DestinationCurrentLength) {

            NdisGetNextBuffer(
                DestinationCurrentBuffer,
                &DestinationCurrentBuffer
                );

            if (!DestinationCurrentBuffer) {

                //
                // We've reached the end of the packet.  We return
                // with what we've done so far. (Which must be shorter
                // than requested.)
                //

                break;

            }

            NdisQueryBuffer(
                DestinationCurrentBuffer,
                NULL,
                &DestinationVirtualAddress,
                &DestinationCurrentLength
                );
            continue;

        }


        //
        // Check to see whether we've exhausted the current source
        // buffer.  If so, move onto the next one.
        //

        if (!SourceCurrentLength) {

            NdisGetNextBuffer(
                SourceCurrentBuffer,
                &SourceCurrentBuffer
                );

            if (!SourceCurrentBuffer) {

                //
                // We've reached the end of the packet.  We return
                // with what we've done so far. (Which must be shorter
                // than requested.)
                //

                break;

            }

            NdisQueryBuffer(
                SourceCurrentBuffer,
                NULL,
                &SourceVirtualAddress,
                &SourceCurrentLength
                );
            continue;

        }

        //
        // Try to get us up to the point to start the copy.
        //

        if (DestinationOffset) {

            if (DestinationOffset > DestinationCurrentLength) {

                //
                // What we want isn't in this buffer.
                //

                DestinationOffset -= DestinationCurrentLength;
                DestinationCurrentLength = 0;
                continue;

            } else {

                DestinationVirtualAddress = (PCHAR)DestinationVirtualAddress
                                            + DestinationOffset;
                DestinationCurrentLength -= DestinationOffset;
                DestinationOffset = 0;

            }

        }

        //
        // Try to get us up to the point to start the copy.
        //

        if (SourceOffset) {

            if (SourceOffset > SourceCurrentLength) {

                //
                // What we want isn't in this buffer.
                //

                SourceOffset -= SourceCurrentLength;
                SourceCurrentLength = 0;
                continue;

            } else {

                SourceVirtualAddress = (PCHAR)SourceVirtualAddress
                                            + SourceOffset;
                SourceCurrentLength -= SourceOffset;
                SourceOffset = 0;

            }

        }

        //
        // Copy the data.
        //

        {

            //
            // Holds the amount of data to move.
            //
            UINT AmountToMove;

            //
            // Holds the amount desired remaining.
            //
            UINT Remaining = BytesToCopy - LocalBytesCopied;

            AmountToMove =
                       ((SourceCurrentLength <= DestinationCurrentLength)?
                        (SourceCurrentLength):(DestinationCurrentLength));

            AmountToMove = ((Remaining < AmountToMove)?
                            (Remaining):(AmountToMove));

            PC586_MOVE_MEMORY(
                DestinationVirtualAddress,
                SourceVirtualAddress,
                AmountToMove
                );

            DestinationVirtualAddress =
                (PCHAR)DestinationVirtualAddress + AmountToMove;
            SourceVirtualAddress =
                (PCHAR)SourceVirtualAddress + AmountToMove;

            LocalBytesCopied += AmountToMove;
            SourceCurrentLength -= AmountToMove;
            DestinationCurrentLength -= AmountToMove;

        }

    }

    *BytesCopied = LocalBytesCopied;

}
Пример #16
0
VOID
ReadPacket (
	PNDIS_PACKET pPacket,
	PUCHAR pBuffer,
	ULONG ulBufSize
	)
/*++

Routine Description:

	Retrieves the buffer from a buffer descriptor.


Arguments:

	Packet - Pointer to the buffer descriptor.

	pBuffer - Pointer to the buffer.

	ulBufSize - Size of the buffer.

Return Value:

	None.


Author:

	xiaonie

	2012/07/12


--*/
{
	PVOID			pVA;
	PNDIS_BUFFER	pFirstBuffer, pNextBuffer;
	ULONG			ulTotalLength;
	ULONG			ulLen;
	PVOID			pBuf = NULL;
	ULONG			ulCount = 0;

	NdisQueryPacket(pPacket, NULL, NULL, &pFirstBuffer, NULL);
	while (pFirstBuffer != NULL)
	{
		NdisQueryBufferSafe(pFirstBuffer, &pVA, &ulLen, NormalPagePriority);

		if(!pVA)
		{
			// memory not enough
			DbgPrint("pVA == NULL, insufficient memory!\r\n");
			break;
		}
		if (ulCount + ulLen > ulBufSize) {
			DbgPrint("ulCount + ulLen(%d) > ulBufSize(%d)\r\n", ulCount + ulLen, ulBufSize);
			break;
		}

		NdisMoveMemory(pBuffer + ulCount, pVA, ulLen);
		ulCount += ulLen;
		NdisGetNextBuffer(pFirstBuffer,  &pNextBuffer);
		pFirstBuffer = pNextBuffer;
	}

	DbgPrint("ReadPacket: ulBufSize == %d, ulCount == %d\n", ulBufSize, ulCount);

	return;
}
Пример #17
0
extern
NDIS_STATUS
SonicTransferData(
    OUT PNDIS_PACKET Packet,
    OUT PUINT BytesTransferred,
    IN NDIS_HANDLE MiniportAdapterContext,
    IN NDIS_HANDLE MiniportReceiveContext,
    IN UINT ByteOffset,
    IN UINT BytesToTransfer
    )

/*++

Routine Description:

    A protocol calls the SonicTransferData request (indirectly via
    NdisTransferData) from within its Receive event handler
    to instruct the driver to copy the contents of the received packet
    a specified paqcket buffer.

Arguments:

    MiniportAdapterContext - Context registered with the wrapper, really
        a pointer to the adapter.

    MiniportReceiveContext - The context value passed by the driver on its call
    to NdisMEthIndicateReceive.  The driver can use this value to determine
    which packet, on which adapter, is being received.

    ByteOffset - An unsigned integer specifying the offset within the
    received packet at which the copy is to begin.  If the entire packet
    is to be copied, ByteOffset must be zero.

    BytesToTransfer - An unsigned integer specifying the number of bytes
    to copy.  It is legal to transfer zero bytes; this has no effect.  If
    the sum of ByteOffset and BytesToTransfer is greater than the size
    of the received packet, then the remainder of the packet (starting from
    ByteOffset) is transferred, and the trailing portion of the receive
    buffer is not modified.

    Packet - A pointer to a descriptor for the packet storage into which
    the MAC is to copy the received packet.

    BytesTransfered - A pointer to an unsigned integer.  The MAC writes
    the actual number of bytes transferred into this location.  This value
    is not valid if the return status is STATUS_PENDING.

Return Value:

    The function value is the status of the operation.


--*/

{
    //
    // Buffer is the buffer to copy from.
    //
    PCHAR Buffer = (PCHAR)MiniportReceiveContext + ByteOffset;

    //
    // Holds the count of the number of ndis buffers comprising the
    // destination packet.
    //
    UINT DestinationBufferCount;

    //
    // Points to the buffer into which we are putting data.
    //
    PNDIS_BUFFER DestinationCurrentBuffer;

    //
    // Points to the location in Buffer from which we are extracting data.
    //
    PUCHAR SourceCurrentAddress;

    //
    // Holds the virtual address of the current destination buffer.
    //
    PVOID DestinationVirtualAddress;

    //
    // Holds the length of the current destination buffer.
    //
    UINT DestinationCurrentLength;

    //
    // Keep a local variable of BytesTransferred so we aren't referencing
    // through a pointer.
    //
    UINT LocalBytesTransferred = 0;

    //
    // MiniportAdapterContext is not referenced.
    //
    MiniportAdapterContext;

    //
    // Take care of boundary condition of zero length copy.
    //

    if (BytesToTransfer == 0) {
        *BytesTransferred = 0;
        return NDIS_STATUS_SUCCESS;
    }

    //
    // Get the first buffer of the destination.
    //

    NdisQueryPacket(
        Packet,
        NULL,
        &DestinationBufferCount,
        &DestinationCurrentBuffer,
        NULL
        );

    //
    // Could have a null packet.
    //

    if (DestinationBufferCount == 0) {
        *BytesTransferred = 0;
        return NDIS_STATUS_SUCCESS;
    }

    NdisQueryBuffer(
        DestinationCurrentBuffer,
        &DestinationVirtualAddress,
        &DestinationCurrentLength
        );

    //
    // Set up the source address.
    //

    SourceCurrentAddress = Buffer;


    while (LocalBytesTransferred < BytesToTransfer) {

        //
        // Check to see whether we've exhausted the current destination
        // buffer.  If so, move onto the next one.
        //

        if (DestinationCurrentLength == 0) {

            NdisGetNextBuffer(
                DestinationCurrentBuffer,
                &DestinationCurrentBuffer
                );

            if (DestinationCurrentBuffer == NULL) {

                //
                // We've reached the end of the packet.  We return
                // with what we've done so far. (Which must be shorter
                // than requested.)
                //

                break;

            }

            NdisQueryBuffer(
                DestinationCurrentBuffer,
                &DestinationVirtualAddress,
                &DestinationCurrentLength
                );

            continue;

        }

        //
        // Copy the data.
        //

        {

            //
            // Holds the amount of data to move.
            //
            UINT AmountToMove;

            //
            // Holds the amount desired remaining.
            //
            UINT Remaining = BytesToTransfer - LocalBytesTransferred;


            AmountToMove = DestinationCurrentLength;

            AmountToMove = ((Remaining < AmountToMove)?
                            (Remaining):(AmountToMove));

            SONIC_MOVE_MEMORY(
                DestinationVirtualAddress,
                SourceCurrentAddress,
                AmountToMove
                );

            SourceCurrentAddress += AmountToMove;
            LocalBytesTransferred += AmountToMove;
            DestinationCurrentLength -= AmountToMove;

        }

    }

    *BytesTransferred = LocalBytesTransferred;
    return NDIS_STATUS_SUCCESS;
}
Пример #18
0
NDIS_STATUS
ProIndicatePacket(
    PLOGICAL_ADAPTER Adapter,
    PNDIS_PACKET Packet)
/*
 * FUNCTION: Indicates a packet to bound protocols
 * ARGUMENTS:
 *     Adapter = Pointer to logical adapter
 *     Packet  = Pointer to packet to indicate
 * RETURNS:
 *     STATUS_SUCCESS in all cases
 * NOTES:
 *     - XXX ATM, this only handles loopback packets - is that its designed function?
 */
{
  UINT BufferedLength;
  UINT PacketLength;
  KIRQL OldIrql;
  PUCHAR LookaheadBuffer;

  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));

#if DBG
  MiniDisplayPacket(Packet);
#endif

  NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength);

  LookaheadBuffer = ExAllocatePool(NonPagedPool, PacketLength);
  if (!LookaheadBuffer) {
      NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
      return NDIS_STATUS_RESOURCES;
  }

  NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
  KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
    {
      BufferedLength = CopyPacketToBuffer(LookaheadBuffer, Packet, 0, PacketLength);
      Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = Packet;
    }
  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);

  if (BufferedLength > Adapter->MediumHeaderSize)
    {
      /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
      MiniIndicateData(Adapter, NULL, LookaheadBuffer, Adapter->MediumHeaderSize,
          &LookaheadBuffer[Adapter->MediumHeaderSize], BufferedLength - Adapter->MediumHeaderSize,
          PacketLength - Adapter->MediumHeaderSize);
    }
  else
    {
      MiniIndicateData(Adapter, NULL, LookaheadBuffer, Adapter->MediumHeaderSize, NULL, 0, 0);
    }

  ExFreePool(LookaheadBuffer);

  KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
    {
      Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = NULL;
    }
  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);

  return NDIS_STATUS_SUCCESS;
}
Пример #19
0
NDIS_STATUS NTAPI
ProSend(
    IN  NDIS_HANDLE     MacBindingHandle,
    IN  PNDIS_PACKET    Packet)
/*
 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
 * ARGUMENTS:
 *     MacBindingHandle = Adapter binding handle
 *     Packet           = Pointer to NDIS packet descriptor
 * RETURNS:
 *     NDIS_STATUS_SUCCESS if the packet was successfully sent
 *     NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
 */
{
  PADAPTER_BINDING AdapterBinding;
  PLOGICAL_ADAPTER Adapter;
  PNDIS_BUFFER NdisBuffer;
  PDMA_CONTEXT Context;
  NDIS_STATUS NdisStatus;
  UINT PacketLength;
  KIRQL OldIrql;

  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));

  ASSERT(MacBindingHandle);
  AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);

  ASSERT(AdapterBinding);
  Adapter = AdapterBinding->Adapter;

  ASSERT(Adapter);

  /* if the following is not true, KeRaiseIrql() below will break */
  ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

  /* XXX what is this crazy black magic? */
  Packet->Reserved[1] = (ULONG_PTR)MacBindingHandle;

  /*
   * Test the packet to see if it is a MAC loopback.
   *
   * We may have to loop this packet if miniport cannot.
   * If dest MAC address of packet == MAC address of adapter,
   * this is a loopback frame.
   */

  if ((Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) &&
      MiniAdapterHasAddress(Adapter, Packet))
    {
#if WORKER_TEST
        MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, Packet, FALSE);
        return NDIS_STATUS_PENDING;
#else
        return ProIndicatePacket(Adapter, Packet);
#endif
    } else {
        if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
        {
            NDIS_DbgPrint(MID_TRACE, ("Using Scatter/Gather DMA\n"));

            NdisQueryPacket(Packet,
                            NULL,
                            NULL,
                            &NdisBuffer,
                            &PacketLength);

            Context = ExAllocatePool(NonPagedPool, sizeof(DMA_CONTEXT));
            if (!Context) {
                NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
                return NDIS_STATUS_RESOURCES;
            }

            Context->Adapter = Adapter;
            Context->Packet = Packet;

            KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);

            KeFlushIoBuffers(NdisBuffer, FALSE, TRUE);

            NdisStatus = Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->GetScatterGatherList(
                          Adapter->NdisMiniportBlock.SystemAdapterObject,
                          Adapter->NdisMiniportBlock.PhysicalDeviceObject,
                          NdisBuffer,
                          MmGetMdlVirtualAddress(NdisBuffer),
                          PacketLength,
                          ScatterGatherSendPacket,
                          Context,
                          TRUE);

            KeLowerIrql(OldIrql);

            if (!NT_SUCCESS(NdisStatus)) {
                NDIS_DbgPrint(MIN_TRACE, ("GetScatterGatherList failed! (%x)\n", NdisStatus));
                return NdisStatus;
            }

            return NDIS_STATUS_PENDING;
        }


        return proSendPacketToMiniport(Adapter, Packet);
    }
}
Пример #20
0
extern
VOID
Pc586ProcessLoopback(
    IN PPC586_ADAPTER Adapter
    )

/*++

Routine Description:

    This routine is responsible for indicating *one* packet on
    the loopback queue either completing it or moving on to the
    finish send queue.

Arguments:

    Adapter - The adapter whose loopback queue we are processing.

Return Value:

    None.

--*/

{



    NdisAcquireSpinLock(&Adapter->Lock);

    if (Adapter->FirstLoopBack) {

        //
        // Packet at the head of the loopback list.
        //
        PNDIS_PACKET PacketToMove;

        //
        // The reserved portion of the above packet.
        //
        PPC586_RESERVED Reserved;

        //
        // Buffer for loopback.
        //
        CHAR Loopback[PC586_SIZE_OF_RECEIVE_BUFFERS];

        //
        // The first buffer in the ndis packet to be loopbacked.
        //
        PNDIS_BUFFER FirstBuffer;

        //
        // The total amount of user data in the packet to be
        // loopbacked.
        //
        UINT TotalPacketLength;

        //
        // Eventually the address of the data to be indicated
        // to the transport.
        //
        PVOID BufferAddress;

        //
        // Eventually the length of the data to be indicated
        // to the transport.
        //
        UINT BufferLength;

        PacketToMove = Adapter->FirstLoopBack;
        Pc586RemovePacketFromLoopBack(Adapter);
        NdisReleaseSpinLock(&Adapter->Lock);

        Reserved = PPC586_RESERVED_FROM_PACKET(PacketToMove);

        //
        // See if we need to copy the data from the packet
        // into the loopback buffer.
        //
        // We need to copy to the local loopback buffer if
        // the first buffer of the packet is less than the
        // minimum loopback size AND the first buffer isn't
        // the total packet.
        //

        NdisQueryPacket(
            PacketToMove,
            NULL,
            NULL,
            &FirstBuffer,
            &TotalPacketLength
            );

        NdisQueryBuffer(
            FirstBuffer,
            NULL,
            &BufferAddress,
            &BufferLength
            );

        if ((BufferLength < PC586_SIZE_OF_RECEIVE_BUFFERS) &&
            (BufferLength != TotalPacketLength)) {

            Pc586CopyFromPacketToBuffer(
                PacketToMove,
                0,
                PC586_SIZE_OF_RECEIVE_BUFFERS,
                Loopback,
                &BufferLength
                );

            BufferAddress = Loopback;

        }

        //
        // Indicate the packet to every open binding
        // that could want it.
        //

        MacFilterIndicateReceive(
            Adapter->FilterDB,
            PacketToMove,
            ((PCHAR)BufferAddress),
            BufferAddress,
            BufferLength,
            TotalPacketLength
            );

        //
        // Remove the packet from the loopback queue and
        // either indicate that it is finished or put
        // it on the finishing up queue for the real transmits.
        //

        NdisAcquireSpinLock(&Adapter->Lock);

        if (!Reserved->STAGE.STAGE4.ReadyToComplete) {

            //
            // We can decrement the reference count on the open by one since
            // it is no longer being "referenced" by the packet on the
            // loopback queue.
            //

            PPC586_OPEN_FROM_BINDING_HANDLE(
                Reserved->MacBindingHandle
                )->References--;
            Pc586PutPacketOnFinishTrans(
                Adapter,
                PacketToMove
                );

        } else {

            PPC586_OPEN Open;
            //
            // Increment the reference count on the open so that
            // it will not be deleted out from under us while
            // where indicating it.
            //

            Open = PPC586_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
            Open->References++;
            NdisReleaseSpinLock(&Adapter->Lock);

            NdisCompleteSend(
                Open->NdisBindingContext,
                Reserved->RequestHandle,
                ((Reserved->STAGE.STAGE4.SuccessfulTransmit)?
                 (NDIS_STATUS_SUCCESS):(NDIS_STATUS_FAILURE))
                );

            NdisAcquireSpinLock(&Adapter->Lock);

            //
            // We can decrement the reference count by two since it is
            // no longer being referenced to indicate and it is no longer
            // being "referenced" by the packet on the loopback queue.
            //

            Open->References -= 2;

        }

        //
        // If there is nothing else on the loopback queue
        // then indicate that reception is "done".
        //

        if (!Adapter->FirstLoopBack) {

            //
            // We need to signal every open binding that the
            // "receives" are complete.  We increment the reference
            // count on the open binding while we're doing indications
            // so that the open can't be deleted out from under
            // us while we're indicating (recall that we can't own
            // the lock during the indication).
            //

            PPC586_OPEN Open;
            PLIST_ENTRY CurrentLink;

            CurrentLink = Adapter->OpenBindings.Flink;

            while (CurrentLink != &Adapter->OpenBindings) {

                Open = CONTAINING_RECORD(
                         CurrentLink,
                         PC586_OPEN,
                         OpenList
                         );

                Open->References++;
                NdisReleaseSpinLock(&Adapter->Lock);

                NdisIndicateReceiveComplete(Open->NdisBindingContext);

                NdisAcquireSpinLock(&Adapter->Lock);
                Open->References--;

                CurrentLink = CurrentLink->Flink;

            }

        }

    }

    NdisReleaseSpinLock(&Adapter->Lock);

}
Пример #21
0
NDIS_STATUS
TOK162Send(
    IN NDIS_HANDLE MiniportAdapterContext,
    IN PNDIS_PACKET Packet,
    IN UINT Flags
    )

/*++

Routine Description:

    The TOK162Send request instructs a Miniport to transmit a packet through
    the adapter onto the medium.

Arguments:

    MiniportAdapterContext - The context value returned by the Miniport when
                             the adapter was initialized.  In reality, it is
                             a pointer to TOK162_ADAPTER.

    Packet                 - A pointer to a descriptor for the packet that is
                             to be transmitted.

Return Value:

    The function value is the status of the operation.

--*/

{
    //
    // Pointer to the adapter.
    //
    PTOK162_ADAPTER Adapter =
        PTOK162_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);

    //
    // Pointer to transmit block
    //
    PTOK162_SUPER_TRANSMIT_LIST    temp;

    //
    // The number of NDIS buffers in the entire packet.
    //
    UINT NdisBufferCount;

    //
    // The total amount of data in the ndis packet.
    //
    UINT TotalDataLength;

    //
    // Points to the current ndis buffer being walked.
    //
    PNDIS_BUFFER CurrentBuffer;

    //
    // Aux pointer to number of available transmit blocks
    //
    PUINT   AvailBlocks;

    //
    // log send called
    //
    IF_LOG('h');

    //
    // Get original count
    //
    AvailBlocks = &Adapter->NumberOfAvailableTransmitBlocks;

    //
    // See if we have any transmits available
    //
    if (*AvailBlocks > 0) {

        (*AvailBlocks)--;

        temp = Adapter->AvailableTransmit;

        Adapter->AvailableTransmit = temp->NextEntry;

        temp->NextActive = NULL;

        //
        // Timestamp the transmit block
        //
        temp->Timeout = FALSE;

        //
        // If the adapter is currently executing a transmit, add this to the
        // end of the waiting list. Otherwise, download it.
        //
        if (Adapter->ActiveTransmitHead != NULL) {

            Adapter->ActiveTransmitTail->NextActive = temp;
            Adapter->ActiveTransmitTail = temp;

        } else {

            Adapter->ActiveTransmitHead = temp;
            Adapter->ActiveTransmitTail = temp;

        }

        //
        // Another transmit is being queued
        //
        Adapter->TransmitsQueued++;

        //
        // Number of sends since last reset increments by one
        //
        Adapter->TotalSends++;

        //
        // Assign the packet to the block
        //
        temp->Packet = Packet;

        //
        // Figure out if we need to constrain the packet.
        //
        NdisQueryPacket(
            Packet,
            &temp->NumberOfBuffers,
            &NdisBufferCount,
            &CurrentBuffer,
            &TotalDataLength
            );

        //
        // See if the packet exceeds MAX_BUFFERS_PER_TRANSMIT or is too short.
        // We will have to constrain in either event.
        //
        if ( (temp->NumberOfBuffers <= MAX_BUFFERS_PER_TRANSMIT) &&
             (TotalDataLength >= MINIMUM_TOKENRING_PACKET_SIZE) ) {

            //
            // Need to constrain the packet, increment the counter
            //
            TOK162DownLoadPacket(Adapter,temp,CurrentBuffer);

            //
            // log leaving send
            //
            IF_LOG('H');

            //
            // We are pending.
            //
            return(NDIS_STATUS_PENDING);

        } else {

            //
            // Need to constrain the packet, increment the counter
            //
            TOK162ConstrainPacket(Adapter,
                temp,
                CurrentBuffer,
                NdisBufferCount,
                TotalDataLength
                );

            //
            // log leaving send
            //
            IF_LOG('H');

            //
            // We are pending.
            //
            return(NDIS_STATUS_PENDING);

        }

    //
    // If no transmit block was available, return RESOURCE error
    //
    } else {

        //
        // log resource error
        //
        IF_LOG('*');

        //
        // Restart the transmits
        //
        WRITE_ADAPTER_USHORT(Adapter,
            PORT_OFFSET_COMMAND,
            ENABLE_TRANSMIT_VALID
            );

        return NDIS_STATUS_RESOURCES;

    }

}
Пример #22
0
int
filter_packet(int direction, int iface, PNDIS_PACKET packet)
{
	PNDIS_BUFFER buffer;
	UINT packet_len, buffer_len, hdr_len;
	int result;
	void *pointer;
	struct ether_hdr *ether_hdr;
	struct ip_hdr *ip_hdr;

	//lint -e506 -e613 -e774 -e831 -e550 
	NdisQueryPacket(packet, NULL, NULL, &buffer, &packet_len);

	if (packet_len < sizeof(struct ether_hdr)) {
		DBGOUT(("filter_packet: too small packet for ether_hdr! (%u)\n", packet_len));
		return FILTER_UNKNOWN;
	}

	/* process ether_hdr */

	NdisQueryBufferSafe(buffer, &ether_hdr, &buffer_len, LowPagePriority);

	if (buffer_len < sizeof(struct ether_hdr)) {
		DBGOUT(("filter_packet: too small buffer for ether_hdr! (%u)\n", buffer_len));
		return FILTER_UNKNOWN;
	}
	
	// go to the next header
	if (buffer_len > sizeof(struct ether_hdr)) {

		pointer = (char *)ether_hdr + sizeof(struct ether_hdr);

		buffer_len -= sizeof(struct ether_hdr);

	} else {
		// use next buffer in chain
		NdisGetNextBuffer(buffer, &buffer);
		NdisQueryBufferSafe(buffer, &pointer, &buffer_len, LowPagePriority);
	}

	if (ether_hdr->ether_type == ETHERNET_TYPE_IP) {
		/* process ip_hdr */

		if (buffer_len < sizeof(struct ip_hdr)) {
			DBGOUT(("filter_packet: too small buffer for ip_hdr! (%u)\n",	buffer_len));
			return FILTER_UNKNOWN;
		}

		ip_hdr = (struct ip_hdr *)pointer;
		hdr_len = ip_hdr->ip_hl * 4;

		if (buffer_len < hdr_len) {
			DBGOUT(("filter_packet: too small buffer for ip_hdr! (%u vs. %u)\n", buffer_len, hdr_len));
			return FILTER_UNKNOWN;
		}

		// go to the next header
		if (buffer_len > hdr_len) {

			pointer = (char *)ip_hdr + hdr_len;
					
			buffer_len -= hdr_len;
			
		} else {
			// use next buffer in chain
			NdisGetNextBuffer(buffer, &buffer);
			NdisQueryBufferSafe(buffer, &pointer, &buffer_len, LowPagePriority);
		}

		result = process_transp(direction, iface, ip_hdr->ip_p, ip_hdr, pointer, buffer_len);
		if (result != FILTER_ALLOW)
			return result;
	}

	// default behavior
	return FILTER_ALLOW;
}
Пример #23
0
int divert_filter_send(PADAPT pAdapt, PNDIS_PACKET Packet, int in)
{
#define HDR_SIZE 54
	int len, cnt;
	PNDIS_BUFFER buf;
	char crap[HDR_SIZE];
	int rc = 0, rd;
	struct ether_header  *pEthHdr;      // See ../B2Winet/ethernet.h
	struct ip            *pIPHeader;
	struct tcphdr	     *tcp;
	struct divert_packet *dp;
	int off = 0; // 14;
        NDISPROT_ETH_HEADER UNALIGNED *pEthHeader;

	NdisAcquireSpinLock(&pAdapt->Lock);

	NdisQueryPacket(Packet, NULL, &cnt, &buf, &len);

	if (len < HDR_SIZE)
		goto Out;

	FltReadOnPacket(Packet, crap, HDR_SIZE, 0, &rd);
	if (rd < HDR_SIZE)
		goto Out;

	pEthHdr = (struct ether_header*) crap;
	pEthHeader = pEthHdr;

	if (ntohs( pEthHdr->ether_type ) != ETHERTYPE_IP)
		goto Out;

	if (in && get_pa(pEthHeader->SrcAddr))
		goto Out;

	pIPHeader = (struct ip * ) (pEthHdr + 1);

	if (pIPHeader->ip_p != IPPROTO_TCP)
		goto Out;

	tcp	  = (struct tcphr*) (pIPHeader + 1);

#if 0
	if (ntohs(tcp->th_dport) == 666)
		rc = 1;
#endif

	lock();

	if (!_open)
		goto F**k;

	dp = get_packet();
	if (!dp) {
		DbgPrint("divert_packet() - outta space dude\n");
		goto F**k;
	}

	dp->dp_len = len - off;
	FltReadOnPacket(Packet, dp->dp_packet, dp->dp_len, off, &rd);
//	rd = dp->dp_len;
	if (rd != dp->dp_len)
		goto F**k;

	dp->dp_flags = 1;

	kick_pending();

	rc = 1;

F**k:
	unlock();
Out:
	NdisReleaseSpinLock(&pAdapt->Lock);

	return rc;
#undef HDR_SIZE
}
Пример #24
0
NDIS_STATUS NIC_DRIVER_OBJECT::DriverSend(
    IN PNDIS_PACKET pPacket,
    IN UINT uFlags)
{

    PCQUEUE_GEN_HEADER pobj;
    
    if (!(pobj = m_TQueue.Dequeue()))
    {
        m_bOutofResources = 1;
        DEBUG_PRINT((TEXT("[DM9ISA_d]: m_bOutofResources\n")));
        return NDIS_STATUS_RESOURCES;
    }
    
    PNDIS_BUFFER pndisFirstBuffer;
    
    UINT uPhysicalBufferCount;
    UINT uBufferCount;
    UINT uTotalPacketLength;
    
    PNDIS_BUFFER pndisCurrBuffer;
    PU8 pcurr = (PU8)CQueueGetUserPointer(pobj);
    
    PVOID ptrBuffer;
    UINT nBuffer;
    U32 idx, check;
    
    NdisQueryPacket(
        pPacket,
        &uPhysicalBufferCount,
        &uBufferCount,
        &pndisFirstBuffer,
        &uTotalPacketLength);
        
    if (uTotalPacketLength > ETH_MAX_FRAME_SIZE)
    {
        return NDIS_STATUS_FAILURE;
    }
    
    uPhysicalBufferCount &= 0xFFFF;
    
    for (idx = 0, check = 0, pndisCurrBuffer = pndisFirstBuffer;
            idx < uBufferCount;
            idx++, pndisCurrBuffer = pndisCurrBuffer->Next)
    {
        NdisQueryBuffer(pndisCurrBuffer, &ptrBuffer, &nBuffer);
            
        if (!nBuffer)
            continue;
            
        NdisMoveMemory(pcurr, ptrBuffer, nBuffer);
        
        pcurr += nBuffer;
        
        check += nBuffer;
        
    } // of for gathering buffer
    
    if (uTotalPacketLength != check)
        return NDIS_STATUS_FAILURE;
        
    pobj->pPacket = (PVOID)pPacket;
    
    pobj->uFlags = uFlags;
    
    pobj->nLength = uTotalPacketLength;
    
    m_pLower->DeviceSend(pobj);
    
#ifdef IMPL_SEND_INDICATION
    return NDIS_STATUS_PENDING;
    
#else
    return NDIS_STATUS_SUCCESS;
    
#endif
}
Пример #25
0
NDIS_STATUS
ElnkSend(
    IN NDIS_HANDLE MacBindingHandle,
    IN PNDIS_PACKET Packet
    )

/*++

Routine Description:

    The ElnkSend request instructs a MAC to transmit a packet through
    the adapter onto the medium.

Arguments:

    MacBindingHandle - The context value returned by the MAC  when the
    adapter was opened.  In reality, it is a pointer to ELNK_OPEN.

    Packet - A pointer to a descriptor for the packet that is to be
    transmitted.

Return Value:
    The function value is the status of the operation.
--*/

{

    //
    // Holds the status that should be returned to the caller.
    //
    NDIS_STATUS StatusToReturn = NDIS_STATUS_PENDING;

    //
    // Pointer to the adapter.
    //
    PELNK_ADAPTER Adapter;

    if ELNKDEBUG DPrint2("ElnkSend Packet = %x\n",Packet);

    Adapter = PELNK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
    NdisAcquireSpinLock(&Adapter->Lock);
    Adapter->References++;

    if (!Adapter->ResetInProgress) {

        PELNK_OPEN Open;

        Open = PELNK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);

        if (!Open->BindingShuttingDown) {

            UINT TotalPacketSize;

            //
            // Increment the references on the open while we are
            // accessing it in the interface.
            //

            Open->References++;

            NdisReleaseSpinLock(&Adapter->Lock);

            //
            // It is reasonable to do a quick check and fail if the packet
            // is larger than the maximum an ethernet can handle.
            //

            NdisQueryPacket(
                Packet,
                NULL,
                NULL,
                NULL,
                &TotalPacketSize
                );

            NdisAcquireSpinLock(&Adapter->Lock);

            if ((!TotalPacketSize) ||
                (TotalPacketSize > MAXIMUM_ETHERNET_PACKET_SIZE)) {
                Open->References--;
                StatusToReturn = NDIS_STATUS_RESOURCES;

            } else {

                PELNK_RESERVED Reserved = PELNK_RESERVED_FROM_PACKET(Packet);
                PNDIS_BUFFER FirstBuffer;
                PUCHAR BufferVA;
                UINT Length;

                //
                // Set Reserved->Loopback.
                //

                NdisQueryPacket(Packet, NULL, NULL, &FirstBuffer, NULL);

                //
                // Get VA of first buffer
                //

                NdisQueryBuffer(
                    FirstBuffer,
                    (PVOID *)&BufferVA,
                    &Length
                    );

                if (Open->ProtOptionFlags & NDIS_PROT_OPTION_NO_LOOPBACK){
                    Reserved->Loopback = FALSE;
                } else {
                    Reserved->Loopback = EthShouldAddressLoopBack(Adapter->FilterDB, BufferVA);
                }

                Reserved->MacBindingHandle = MacBindingHandle;

                //
                // Put on the stage queue.
                //

                if (!Adapter->LastStagePacket) {

                    Adapter->FirstStagePacket = Packet;

                } else {

                    PELNK_RESERVED_FROM_PACKET(Adapter->LastStagePacket)->Next = Packet;

                }

                Adapter->LastStagePacket = Packet;

                Reserved->Next = NULL;

                Adapter->TransmitsQueued++;

                //
                // Only try to push it through the stage queues
                // if somebody else isn't already doing it and
                // there is some hope of moving some packets
                // ahead.
                //

                while (!Adapter->AlreadyProcessingStage &&
                       Adapter->FirstStagePacket &&
                       Adapter->StageOpen
                      ) {

                    ElnkStagedAllocation(Adapter);

                }

            }

            //
            // We leave the reference for the pending send.
            //

        } else {

            StatusToReturn = NDIS_STATUS_CLOSING;

        }

    } else {

        StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;

    }

    ELNK_DO_DEFERRED(Adapter);
    return StatusToReturn;
}
Пример #26
0
extern
VOID
Pc586CopyFromPacketToBuffer(
    IN PNDIS_PACKET Packet,
    IN UINT Offset,
    IN UINT BytesToCopy,
    OUT PCHAR Buffer,
    OUT PUINT BytesCopied
    )

/*++

Routine Description:

    Copy from an ndis packet into a buffer.

Arguments:

    Packet - The packet to copy from.

    Offset - The offset from which to start the copy.

    BytesToCopy - The number of bytes to copy from the packet.

    Buffer - The destination of the copy.

    BytesCopied - The number of bytes actually copied.  Can be less then
    BytesToCopy if the packet is shorter than BytesToCopy.

Return Value:

    None

--*/

{

    //
    // Holds the number of ndis buffers comprising the packet.
    //
    UINT NdisBufferCount;

    //
    // Points to the buffer from which we are extracting data.
    //
    PNDIS_BUFFER CurrentBuffer;

    //
    // Holds the virtual address of the current buffer.
    //
    PVOID VirtualAddress;

    //
    // Holds the length of the current buffer of the packet.
    //
    UINT CurrentLength;

    //
    // Keep a local variable of BytesCopied so we aren't referencing
    // through a pointer.
    //
    UINT LocalBytesCopied = 0;

    //
    // Take care of boundary condition of zero length copy.
    //

    *BytesCopied = 0;
    if (!BytesToCopy) return;

    //
    // Get the first buffer.
    //

    NdisQueryPacket(
        Packet,
        NULL,
        &NdisBufferCount,
        &CurrentBuffer,
        NULL
        );

    //
    // Could have a null packet.
    //

    if (!NdisBufferCount) return;

    NdisQueryBuffer(
        CurrentBuffer,
        NULL,
        &VirtualAddress,
        &CurrentLength
        );

    while (LocalBytesCopied < BytesToCopy) {

        if (!CurrentLength) {

            NdisGetNextBuffer(
                CurrentBuffer,
                &CurrentBuffer
                );

            //
            // We've reached the end of the packet.  We return
            // with what we've done so far. (Which must be shorter
            // than requested.
            //

            if (!CurrentBuffer) break;

            NdisQueryBuffer(
                CurrentBuffer,
                NULL,
                &VirtualAddress,
                &CurrentLength
                );
            continue;

        }

        //
        // Try to get us up to the point to start the copy.
        //

        if (Offset) {

            if (Offset > CurrentLength) {

                //
                // What we want isn't in this buffer.
                //

                Offset -= CurrentLength;
                CurrentLength = 0;
                continue;

            } else {

                VirtualAddress = (PCHAR)VirtualAddress + Offset;
                CurrentLength -= Offset;
                Offset = 0;

            }

        }

        //
        // Copy the data.
        //


        {

            //
            // Holds the amount of data to move.
            //
            UINT AmountToMove;

            AmountToMove =
                       ((CurrentLength <= (BytesToCopy - LocalBytesCopied))?
                        (CurrentLength):(BytesToCopy - LocalBytesCopied));

            PC586_MOVE_MEMORY(
                Buffer,
                VirtualAddress,
                AmountToMove
                );

            Buffer = (PCHAR)Buffer + AmountToMove;
            VirtualAddress = (PCHAR)VirtualAddress + AmountToMove;

            LocalBytesCopied += AmountToMove;
            CurrentLength -= AmountToMove;

        }

    }

    *BytesCopied = LocalBytesCopied;

}
Пример #27
0
INT
PacketReceivePacket(
	IN    NDIS_HANDLE         ProtocolBindingContext,
	IN    PNDIS_PACKET        Packet
)
{
	UINT                bytesTransfered = 0;
	POPEN_INSTANCE      open;
	PIRP                irp;
	PNDIS_PACKET        myPacket;
	PLIST_ENTRY         packetListEntry;
	ULONG               bufferLength;
	PPACKET_RESERVED    reserved;
	PIO_STACK_LOCATION  irpSp;
	PMDL                mdl;
	PVOID               startAddress;
	NTSTATUS           status;

	// DebugPrint(("PacketReceivePacket\n"));

	open = (POPEN_INSTANCE)ProtocolBindingContext;

	packetListEntry = ExInterlockedRemoveHeadList(
											&open->RcvList,
											&open->RcvQSpinLock
											);

	if (packetListEntry == NULL) {
		// DebugPrint(("No pending read, dropping packets\n"));
		return 0;
	}

	reserved = CONTAINING_RECORD(packetListEntry,PACKET_RESERVED,ListElement);
	myPacket = CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved);

	irp = RESERVED(myPacket)->Irp;
	irpSp = IoGetCurrentIrpStackLocation(irp);

	// We don't have to worry about the situation where the IRP is cancelled
	// after we remove it from the queue and before we reset the cancel
	// routine because the cancel routine has been coded to cancel an IRP
	// only if it's in the queue.

	IoSetCancelRoutine(irp, NULL);

	// Following block of code locks the destination packet
	// MDLs in a safe manner. This is a temporary workaround
	// for NdisCopyFromPacketToPacket that currently doesn't use
	// safe functions to lock pages of MDL. This is required to
	// prevent system from bugchecking under low memory resources.
	//
	{
		PVOID           virtualAddress;
		PNDIS_BUFFER    firstBuffer, nextBuffer;
		ULONG           totalLength;

		NdisQueryPacket(Packet, NULL, NULL, &firstBuffer, &totalLength);
		while( firstBuffer ) {
			NdisQueryBufferSafe( firstBuffer, &virtualAddress, &totalLength, NormalPagePriority );
			if(!virtualAddress) {
				status = STATUS_INSUFFICIENT_RESOURCES;
				goto CleanExit;
			}
			NdisGetNextBuffer(firstBuffer,  &nextBuffer);
			firstBuffer = nextBuffer;
		}
	}

	NdisChainBufferAtFront( myPacket, irp->MdlAddress );
	bufferLength=irpSp->Parameters.Read.Length;
	NdisCopyFromPacketToPacket( myPacket, 0, bufferLength, Packet, 0,  &bytesTransfered );

CleanExit:
	NdisFreePacket(myPacket);
	irp->IoStatus.Status = status;
	irp->IoStatus.Information = bytesTransfered;
	IoCompleteRequest(irp, IO_NO_INCREMENT);
	// DebugPrint(("BytesTransfered:%d\n", bytesTransfered));
	IoDecrement(open);
	return 0;
}
Пример #28
0
NDIS_STATUS
LpxReceiveIndication (
	IN NDIS_HANDLE	ProtocolBindingContext,
	IN NDIS_HANDLE	MacReceiveContext,
	IN PVOID		HeaderBuffer,
	IN UINT		    HeaderBufferSize,
	IN PVOID		LookAheadBuffer,
	IN UINT		    LookAheadBufferSize,
	IN UINT		    PacketSize
	)
/*++

Routine Description:

	This routine receives control from the physical provider as an
	indication that a frame has been received on the physical link.
	This routine is time critical, so we only allocate a
	buffer and copy the packet into it. We also perform minimal
	validation on this packet. It gets queued to the device context
	to allow for processing later.

Arguments:

	BindingContext - The Adapter Binding specified at initialization time.

	ReceiveContext - A magic cookie for the MAC.

	HeaderBuffer - pointer to a buffer containing the packet header.

	HeaderBufferSize - the size of the header.

	LookaheadBuffer - pointer to a buffer containing the negotiated minimum
		amount of buffer I get to look at (not including header).

	LookaheadBufferSize - the size of the above. May be less than asked
		for, if that's all there is.

	PacketSize - Overall size of the packet (not including header).

Return Value:

	NDIS_STATUS - status of operation, one of:

			     NDIS_STATUS_SUCCESS if packet accepted,
			     NDIS_STATUS_NOT_RECOGNIZED if not recognized by protocol,
			     NDIS_any_other_thing if I understand, but can't handle.

--*/
{
	PDEVICE_CONTEXT	deviceContext;
	USHORT		    protocol;
	PNDIS_PACKET	packet;
	NDIS_STATUS		status;
	UINT		    bytesTransfered = 0;
	UINT		    startOffset = 0;


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

	//
	//	validation
	//

	if (HeaderBufferSize != ETHERNET_HEADER_LENGTH) {

		DebugPrint( 4, ("HeaderBufferSize = %x\n", HeaderBufferSize) );
		return NDIS_STATUS_NOT_RECOGNIZED;
	}
	
	RtlCopyMemory( (PUCHAR)&protocol, &((PUCHAR)HeaderBuffer)[12], sizeof(USHORT) );

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

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

#if __LPX__
		NdisCopyLookaheadData( (PUCHAR)&protocol,
								&((PUCHAR)LookAheadBuffer)[LENGTH_8022LLCSNAP - 2],
								sizeof(USHORT),
								deviceContext->MacOptions );
#endif
		PacketSize -= LENGTH_8022LLCSNAP;
		LookAheadBufferSize -= LENGTH_8022LLCSNAP;
		startOffset = LENGTH_8022LLCSNAP;
	}

	if (protocol != HTONS(ETH_P_LPX)) {
	
		DebugPrint( 4, ("Type = %x\n", protocol) );
		return NDIS_STATUS_NOT_RECOGNIZED;
	}


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

	//ACQUIRE_DPC_SPIN_LOCK( &deviceContext->SpinLock );

	if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) || FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) {
	
		//RELEASE_DPC_SPIN_LOCK( &deviceContext->SpinLock );
		DebugPrint( 4,("Device is not initialized. Drop packet\n") );

		return NDIS_STATUS_NOT_RECOGNIZED;
	}

	ASSERT( deviceContext->NdisBindingHandle );

	//RELEASE_DPC_SPIN_LOCK( &deviceContext->SpinLock );

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

#if 1 //DBG // Enabled for testing

	if (PacketRxDropRate) {

		PacketRxCountForDrop++;
				
		if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) {
			PLPX_HEADER        lpxHeader = (PLPX_HEADER)LookAheadBuffer;
#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") );

			return NDIS_STATUS_NOT_RECOGNIZED;
		}
	}

#endif

	ASSERT( startOffset == 0 );

	DebugPrint( 4, ("LpxReceiveIndication, PacketSize = %d, LookAheadBufferSize = %d, LPX_HEADER size = %d\n",
					 PacketSize, LookAheadBufferSize, sizeof(LPX_HEADER)) );

	if (LookAheadBufferSize >= sizeof(LPX_HEADER)) {

		PNDIS_BUFFER	firstBuffer;    
		PUCHAR		    packetData;
		PLPX_HEADER		lpxHeader;
		USHORT			lpxHeaderSize;

		
		lpxHeader = (PLPX_HEADER)((PBYTE)LookAheadBuffer + startOffset);
		
		lpxHeaderSize = sizeof(LPX_HEADER);

#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 (NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) == lpxHeaderSize) {

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

			if (status == STATUS_SUCCESS) {

				NdisCopyLookaheadData( &RESERVED(packet)->EthernetHeader,
										HeaderBuffer,
										ETHERNET_HEADER_LENGTH,
										deviceContext->MacOptions );

				RESERVED(packet)->EthernetHeader.Type = protocol;
				RESERVED(packet)->RecvTime = CurrentTime();
			
				RtlCopyMemory( &RESERVED(packet)->LpxHeader, lpxHeader, lpxHeaderSize );
				RESERVED(packet)->HeaderCopied = TRUE;

				RESERVED(packet)->PacketRawDataLength = 0;
				RESERVED(packet)->PacketRawDataOffset = 0;

				LpxTransferDataComplete( deviceContext,
					                     packet,
					                     NDIS_STATUS_SUCCESS,
					                     LookAheadBufferSize );

				return NDIS_STATUS_SUCCESS;
			}

		} else if (LookAheadBufferSize >= NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK)) {
				
			status = RcvPacketAlloc( deviceContext,
									 NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize,
									 &packet );

			if (status == STATUS_SUCCESS) {
			
				NdisCopyLookaheadData( &RESERVED(packet)->EthernetHeader,
										HeaderBuffer,
										ETHERNET_HEADER_LENGTH,
										deviceContext->MacOptions );

				RESERVED(packet)->EthernetHeader.Type = protocol;
				RESERVED(packet)->RecvTime = CurrentTime();

				RtlCopyMemory( &RESERVED(packet)->LpxHeader, lpxHeader, lpxHeaderSize );
				RESERVED(packet)->HeaderCopied = TRUE;

				RESERVED(packet)->PacketRawDataLength = NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize;
				RESERVED(packet)->PacketRawDataOffset = 0;

				NdisQueryPacket( packet, NULL, NULL, &firstBuffer, NULL );
				packetData = MmGetMdlVirtualAddress( firstBuffer );

				NdisCopyLookaheadData( packetData,
									   (PBYTE)LookAheadBuffer + startOffset + lpxHeaderSize,
									   RESERVED(packet)->PacketRawDataLength,
									   deviceContext->MacOptions );

				LpxTransferDataComplete( deviceContext,
					                     packet,
					                     NDIS_STATUS_SUCCESS,
					                     LookAheadBufferSize );

				return NDIS_STATUS_SUCCESS;
			}

		} else {

			status = RcvPacketAlloc( deviceContext,
									 startOffset + NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK),
									 &packet );
			
			if (status == STATUS_SUCCESS) {
			
				NdisCopyLookaheadData( &RESERVED(packet)->EthernetHeader,
										HeaderBuffer,
										ETHERNET_HEADER_LENGTH,
										deviceContext->MacOptions );

				RESERVED(packet)->EthernetHeader.Type = protocol;
				RESERVED(packet)->RecvTime = CurrentTime();

				RtlCopyMemory( &RESERVED(packet)->LpxHeader, lpxHeader, lpxHeaderSize );
				RESERVED(packet)->HeaderCopied = TRUE;

				RESERVED(packet)->PacketRawDataLength = startOffset + NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK);
				RESERVED(packet)->PacketRawDataOffset = startOffset + lpxHeaderSize;
			}
		}

	} else {

		PLPX_HEADER		lpxHeader;
		PNDIS_BUFFER	firstBuffer;	
		PUCHAR			packetData;
		UINT			packetDataLength;

		ASSERT( FALSE );

		status = RcvPacketAlloc( deviceContext, PacketSize, &packet );
		
		if (status == STATUS_SUCCESS) {
		
			RtlCopyMemory( &RESERVED(packet)->EthernetHeader,
						   HeaderBuffer,
						   ETHERNET_HEADER_LENGTH );

			RESERVED(packet)->EthernetHeader.Type = protocol;
			RESERVED(packet)->RecvTime = CurrentTime();

			RESERVED(packet)->PacketRawDataLength = PacketSize;
			RESERVED(packet)->PacketRawDataOffset = startOffset;

			NdisQueryPacket( packet, NULL, NULL, &firstBuffer, NULL );
			NdisQueryBufferSafe( firstBuffer, &packetData, &packetDataLength, HighPagePriority );

			lpxHeader = (PLPX_HEADER)(packetData + RESERVED(packet)->PacketRawDataOffset);
			RtlZeroMemory( lpxHeader, sizeof(LPX_HEADER) );

			RESERVED(packet)->HeaderCopied = FALSE;
		}
	}

	if (status != NDIS_STATUS_SUCCESS) {
	
		return NDIS_STATUS_NOT_RECOGNIZED;
	}

	ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS );
			
	if (deviceContext->NdisBindingHandle) {

		//ASSERT( FALSE );

		NdisTransferData( &status,
						  deviceContext->NdisBindingHandle,
						  MacReceiveContext,
						  0, //RESERVED(packet)->PacketRawDataOffset,
						  RESERVED(packet)->PacketRawDataLength,
						  packet,
						  &bytesTransfered );

			
		if (status == NDIS_STATUS_PENDING) {

			LPX_ASSERT( FALSE );
		    status = NDIS_STATUS_SUCCESS;
		
		} else if (status == NDIS_STATUS_SUCCESS) {
		
			LpxTransferDataComplete( deviceContext,
									 packet,
									 status,
									 bytesTransfered );

		} else {
	
			LPX_ASSERT( FALSE );
			DebugPrint( 1, ("NdisTransferData() failed. STATUS=%08lx\n", status) );
		}

	} else {
			
		status = NDIS_STATUS_NOT_RECOGNIZED;
		DebugPrint( 1, ("Invalid device status. STATUS=%08lx\n", status) );
	}

	return status;
}
Пример #29
0
/* We've received a csum_blank packet, but we don't want to let
   Windows see it like.  Calculate the checksum and dump it in the
   packet.  This only works for TCP and UDP on IPv4; on anything else
   it's a no-op. */
static VOID
FixupChecksum(PNDIS_PACKET packet)
{
    PNDIS_BUFFER pbuf;
    PNDIS_BUFFER pbuf_next;
    UINT bufLength;
    UINT len;
    struct ethhdr *eh;
    struct iphdr *ih;
    uint32_t csum_accumulator;
    uint32_t *ptr;
    uint16_t *csum_field;

    NdisQueryPacket(packet, NULL, NULL, &pbuf, NULL);
    NdisQueryBufferSafe(pbuf, &eh, &bufLength, NormalPagePriority);
    if (!eh || bufLength < sizeof(*eh))
        return;
    if (eh->proto != TPID_IPV4) {
        static BOOLEAN warned;
        if (!warned) {
            TraceWarning(("Asked to perform checksum calculation on non-IP ethernet prototocol %x!\n", eh->proto));
            warned = TRUE;
        }
        return;
    }
    ih = (struct iphdr *)(eh + 1);
    bufLength -= sizeof(*eh);
    if (bufLength < sizeof(*ih) ||
        bufLength < (UINT)(ih->len_version & 0x0f) * 4)
        return;
    ptr = (uint32_t *)((ULONG_PTR)ih + (ih->len_version & 0x0f)*4);
    len = ntohs(ih->tot_len) - (ih->len_version & 0x0f) * 4;

    bufLength -= (ih->len_version & 0x0f) * 4;
    if (bufLength > len)
        bufLength = len;

    if (ih->proto == IPPROTO_UDP) {
        if (bufLength < sizeof(struct udphdr))
            return;
        csum_field = &((struct udphdr *)ptr)->checksum;
    } else if (ih->proto == IPPROTO_TCP) {
        if (bufLength < sizeof(struct tcphdr))
            return;
        csum_field = &((struct tcphdr *)ptr)->checksum;
    } else {
        static BOOLEAN warned;
        /* Uh oh: don't know what this protocol is, so can't do
           checksum calculation for it. */
        if (!warned) {
            TraceWarning(("Asked to perform checksum calculation for unknown protocol %d!\n",
                          ih->proto));
            warned = TRUE;
        }
        return;
    }

    if (ih->proto == IPPROTO_TCP) {
        struct tcp_pseudo_header tph;
        uint16_t csum;

        tph.saddr = ih->src;
        tph.daddr = ih->dest;
        tph.mbz = 0;
        tph.ptcl = IPPROTO_TCP;
        tph.length = htons((uint16_t)len);

        csum_accumulator = acc_ip_csum(&tph, sizeof(tph), 0);
        csum = fold_ip_csum(csum_accumulator);

        if (*csum_field != csum)
            TraceWarning(("invlid pseudo header checksum: expected %04x, found %04x\n", csum, *csum_field));

        *csum_field = csum;
    }

    csum_accumulator = acc_ip_csum(ptr, bufLength, 0);
    len -= bufLength;

    while (len) {
        NdisGetNextBuffer(pbuf, &pbuf_next);
        if (pbuf_next == NULL)
            break;
        pbuf = pbuf_next;
        NdisQueryBufferSafe(pbuf, &ptr, &bufLength, NormalPagePriority);

        /* The buffer is already mapped into our RX buffer pool, so we
           should always be able to get a virtual address for it. */
        XM_ASSERT(ptr != NULL);

        if (bufLength > len)
            bufLength = len;

        csum_accumulator = acc_ip_csum(ptr, bufLength, csum_accumulator);
        len -= bufLength;
    }

    *csum_field = ~fold_ip_csum(csum_accumulator);
}
Пример #30
0
VOID
LpxTransferDataComplete(
	IN NDIS_HANDLE   ProtocolBindingContext,
	IN PNDIS_PACKET  Packet,
	IN NDIS_STATUS   Status,
	IN UINT          BytesTransfered
	)
{
	PDEVICE_CONTEXT	pDeviceContext;
	PLPX_HEADER	lpxHeader;
	PNDIS_BUFFER	firstBuffer;	
	PUCHAR			packetData;
	UINT			packetDataLength;
	USHORT			lpxHeaderSize;


	UNREFERENCED_PARAMETER( BytesTransfered );

	pDeviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext;

	if (Status != NDIS_STATUS_SUCCESS) {

		ASSERT( FALSE );
		DebugPrint( 1,  ("[LPX] LpxTransferDataComplete error %x\n", Status) );
		PacketFree( pDeviceContext, Packet );
		return;
	}

	if (RESERVED(Packet)->HeaderCopied == FALSE) {
	
		NdisQueryPacket( Packet, NULL, NULL, &firstBuffer, NULL );
		NdisQueryBufferSafe( firstBuffer, &packetData, &packetDataLength, HighPagePriority );

		lpxHeader = (PLPX_HEADER)(packetData + RESERVED(Packet)->PacketRawDataOffset);

		lpxHeaderSize = sizeof(LPX_HEADER);

#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

		RtlCopyMemory( &RESERVED(Packet)->LpxHeader, lpxHeader, lpxHeaderSize );
		RESERVED(Packet)->HeaderCopied = TRUE;

		RESERVED(Packet)->PacketRawDataLength = RESERVED(Packet)->PacketRawDataOffset + NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK);
		RESERVED(Packet)->PacketRawDataOffset += lpxHeaderSize;
	}
	
	lpxHeaderSize = sizeof(LPX_HEADER);

#if __LPX_OPTION_ADDRESSS__

	if (FlagOn(RESERVED(Packet)->LpxHeader.Option, LPX_OPTION_SOURCE_ADDRESS)) {

		if (!FlagOn(RESERVED(Packet)->LpxHeader.Option, LPX_OPTION_DESTINATION_ADDRESS)) {
		
			RtlCopyMemory( RESERVED(Packet)->OptionSourceAddress,
						   RESERVED(Packet)->OptionDestinationAddress,
						   ETHERNET_ADDRESS_LENGTH );	
		}

		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;

		ASSERT( RtlEqualMemory(RESERVED(Packet)->EthernetHeader.SourceAddress,
							   RESERVED(Packet)->OptionSourceAddress,
							   ETHERNET_ADDRESS_LENGTH) );
	}

	if (FlagOn(RESERVED(Packet)->LpxHeader.Option, LPX_OPTION_DESTINATION_ADDRESS)) {

		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;

		ASSERT( RtlEqualMemory(RESERVED(Packet)->EthernetHeader.DestinationAddress,
							   RESERVED(Packet)->OptionDestinationAddress,
							   ETHERNET_ADDRESS_LENGTH) );
	}

#endif

	if (NTOHS(RESERVED(Packet)->LpxHeader.PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize != 
		RESERVED(Packet)->PacketRawDataLength - RESERVED(Packet)->PacketRawDataOffset) {

		ASSERT( FALSE );
		PacketFree( pDeviceContext, Packet );
		return;
	}		

	ExInterlockedInsertTailList( &pDeviceContext->PacketInProgressList,
								 &(RESERVED(Packet)->ListEntry),
								 &pDeviceContext->PacketInProgressQSpinLock );
	return;
}