mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
610 lines
12 KiB
610 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ltutils.c
|
|
|
|
Abstract:
|
|
|
|
This module contains utility routines.
|
|
|
|
Author:
|
|
|
|
Nikhil Kamkolkar ([email protected])
|
|
Stephen Hou ([email protected])
|
|
|
|
Revision History:
|
|
19 Jun 1992 Initial Version ([email protected])
|
|
|
|
Notes: Tab stop: 4
|
|
--*/
|
|
|
|
#include "ltmain.h"
|
|
#include "ltutils.h"
|
|
|
|
|
|
// Define file id for errorlogging
|
|
#define FILENUM LTUTILS
|
|
|
|
|
|
USHORT
|
|
LtUtilsPacketType(
|
|
IN PNDIS_PACKET Packet
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Calculates the packet type for this packet. It also determines
|
|
if this packet should go out on the wire.
|
|
|
|
Arguments:
|
|
|
|
Packet - Packet whose source and destination addresses are tested.
|
|
|
|
Return Value:
|
|
|
|
Returns FALSE if the source is equal to the destination.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
// Holds the destination and source address from the packet.
|
|
UCHAR PacketAddresses[2];
|
|
|
|
// Junk variable to hold the length of the addresses
|
|
UINT AddressLength;
|
|
|
|
LtUtilsCopyFromPacketToBuffer(
|
|
Packet,
|
|
0,
|
|
2,
|
|
PacketAddresses,
|
|
&AddressLength);
|
|
|
|
return(LtUtilsUcharPacketType(PacketAddresses[0], PacketAddresses[1]));
|
|
}
|
|
|
|
|
|
USHORT
|
|
LtUtilsUcharPacketType(
|
|
IN UCHAR DestinationAddress,
|
|
IN UCHAR SourceAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Calculates the packet type for this packet. It also determines
|
|
if this packet should go out on the wire.
|
|
|
|
Arguments:
|
|
|
|
Packet - Packet whose source and destination addresses are tested.
|
|
|
|
Return Value:
|
|
|
|
Returns FALSE if the source is equal to the destination.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
int PacketType = LT_DIRECTED;
|
|
|
|
if (DestinationAddress == LT_BROADCAST_NODE_ID)
|
|
{
|
|
PacketType = LT_BROADCAST;
|
|
}
|
|
else
|
|
{
|
|
if (DestinationAddress == SourceAddress)
|
|
{
|
|
PacketType = LT_LOOPBACK;
|
|
}
|
|
}
|
|
|
|
return(PacketType);
|
|
}
|
|
|
|
|
|
VOID
|
|
LtUtilsCopyFromPacketToBuffer(
|
|
IN PNDIS_PACKET SrcPacket,
|
|
IN UINT SrcOffset,
|
|
IN UINT BytesToCopy,
|
|
OUT PUCHAR DestBuffer,
|
|
OUT PUINT BytesCopied
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copy from an ndis packet into a buffer.
|
|
|
|
Arguments:
|
|
|
|
SrcPacket - The packet to copy from.
|
|
|
|
SrcOffset - The offset within the packet from which to start the copy.
|
|
|
|
BytesToCopy - The number of bytes to copy from the packet.
|
|
|
|
DestBuffer - 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
|
|
|
|
--*/
|
|
{
|
|
|
|
UINT SrcBufferCount; // number of buffers in the current buffer
|
|
PNDIS_BUFFER SrcCurrentBuffer; // current buffer
|
|
UINT SrcCurrentBufferLen; // length of the current buffer
|
|
PVOID SrcVirtualAddress; // virtual address of the current buffer
|
|
UINT AmountToCopy; // bytes to copy
|
|
|
|
UINT LocalBytesCopied = 0; // total bytes copied
|
|
|
|
*BytesCopied = 0;
|
|
|
|
// Take care of boundary condition of zero length copy.
|
|
if (!BytesToCopy)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Get the first buffer.
|
|
//
|
|
|
|
NdisQueryPacket(
|
|
SrcPacket,
|
|
NULL,
|
|
&SrcBufferCount,
|
|
&SrcCurrentBuffer,
|
|
NULL);
|
|
|
|
// Could have a null packet.
|
|
if (!SrcBufferCount)
|
|
{
|
|
return;
|
|
}
|
|
|
|
NdisQueryBuffer(
|
|
SrcCurrentBuffer,
|
|
&SrcVirtualAddress,
|
|
&SrcCurrentBufferLen);
|
|
|
|
// advance to the start point for the copy.
|
|
while (SrcOffset)
|
|
{
|
|
if (SrcOffset > SrcCurrentBufferLen)
|
|
{
|
|
//
|
|
// What we want isn't in this buffer.
|
|
//
|
|
|
|
SrcOffset -= SrcCurrentBufferLen;
|
|
SrcCurrentBufferLen = 0;
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
SrcVirtualAddress = (PCHAR)SrcVirtualAddress + SrcOffset;
|
|
SrcCurrentBufferLen -= SrcOffset;
|
|
SrcOffset = 0;
|
|
break;
|
|
|
|
}
|
|
|
|
NdisGetNextBuffer(
|
|
SrcCurrentBuffer,
|
|
&SrcCurrentBuffer);
|
|
|
|
// We hit the end of the packet
|
|
if (!SrcCurrentBuffer)
|
|
{
|
|
return;
|
|
}
|
|
|
|
NdisQueryBuffer(
|
|
SrcCurrentBuffer,
|
|
&SrcVirtualAddress,
|
|
&SrcCurrentBufferLen);
|
|
}
|
|
|
|
// Copy the data.
|
|
while (LocalBytesCopied < BytesToCopy)
|
|
{
|
|
AmountToCopy = ((SrcCurrentBufferLen <= (BytesToCopy - LocalBytesCopied))?
|
|
(SrcCurrentBufferLen):(BytesToCopy - LocalBytesCopied));
|
|
|
|
NdisMoveMemory(
|
|
DestBuffer,
|
|
SrcVirtualAddress,
|
|
AmountToCopy);
|
|
|
|
DestBuffer = (PCHAR)DestBuffer + AmountToCopy;
|
|
SrcVirtualAddress = (PCHAR)SrcVirtualAddress + AmountToCopy;
|
|
|
|
LocalBytesCopied += AmountToCopy;
|
|
SrcCurrentBufferLen -= AmountToCopy;
|
|
|
|
// read the entire buffer, read in the next one
|
|
if (!SrcCurrentBufferLen)
|
|
{
|
|
NdisGetNextBuffer(
|
|
SrcCurrentBuffer,
|
|
&SrcCurrentBuffer);
|
|
|
|
//
|
|
// We've reached the end of the packet. We return
|
|
// with what we've done so far. (Which must be shorter
|
|
// than requested.
|
|
//
|
|
|
|
if (!SrcCurrentBuffer)
|
|
break;
|
|
|
|
NdisQueryBuffer(
|
|
SrcCurrentBuffer,
|
|
&SrcVirtualAddress,
|
|
&SrcCurrentBufferLen);
|
|
|
|
}
|
|
}
|
|
|
|
*BytesCopied = LocalBytesCopied;
|
|
}
|
|
|
|
|
|
VOID
|
|
LtUtilsCopyFromBufferToPacket(
|
|
IN PUCHAR SrcBuffer,
|
|
IN UINT SrcOffset,
|
|
IN UINT BytesToCopy,
|
|
IN PNDIS_PACKET DestPacket,
|
|
OUT PUINT BytesCopied
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copy from a buffer into an ndis packet.
|
|
|
|
Arguments:
|
|
|
|
SrcBuffer - The buffer to copy from.
|
|
|
|
SrcOffset - The offset within SrcBuffer from which to start the copy.
|
|
|
|
DestPacket - The destination of the copy.
|
|
|
|
BytesToCopy - The number of bytes to copy from the buffer.
|
|
|
|
BytesCopied - The number of bytes actually copied. Will be less
|
|
than BytesToCopy if the packet is not large enough.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
|
|
UINT DestBufferCount; // number of buffers in the packet
|
|
PNDIS_BUFFER DestCurrentBuffer; // current buffer
|
|
UINT DestCurrentBufferLen; // length of the current buffer
|
|
PVOID DestVirtualAddress; // virtual addr of the current dest buffer
|
|
PUCHAR SrcCurrentAddress; // ptr to current location in src buffer
|
|
UINT AmountToCopy; // bytes to copy
|
|
UINT BytesRemaining; // bytes left to copy
|
|
|
|
UINT LocalBytesCopied = 0; // bytes copied
|
|
|
|
*BytesCopied = 0;
|
|
|
|
// Take care of boundary condition of zero length copy.
|
|
if (!BytesToCopy)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Get the first buffer of the destination.
|
|
NdisQueryPacket(
|
|
DestPacket,
|
|
NULL,
|
|
&DestBufferCount,
|
|
&DestCurrentBuffer,
|
|
NULL);
|
|
|
|
// Could have a null packet.
|
|
if (!DestBufferCount)
|
|
{
|
|
return;
|
|
}
|
|
|
|
NdisQueryBuffer(
|
|
DestCurrentBuffer,
|
|
&DestVirtualAddress,
|
|
&DestCurrentBufferLen);
|
|
|
|
// Set up the source address.
|
|
SrcCurrentAddress = SrcBuffer + SrcOffset;
|
|
|
|
while (LocalBytesCopied < BytesToCopy)
|
|
{
|
|
//
|
|
// Check to see whether we've exhausted the current destination
|
|
// buffer. If so, move onto the next one.
|
|
//
|
|
|
|
if (!DestCurrentBufferLen)
|
|
{
|
|
NdisGetNextBuffer(
|
|
DestCurrentBuffer,
|
|
&DestCurrentBuffer);
|
|
|
|
if (!DestCurrentBuffer)
|
|
{
|
|
//
|
|
// 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(
|
|
DestCurrentBuffer,
|
|
&DestVirtualAddress,
|
|
&DestCurrentBufferLen);
|
|
|
|
// go back to the start of the loop and repeat buffer size check
|
|
continue;
|
|
|
|
}
|
|
|
|
//
|
|
// Copy the data.
|
|
//
|
|
|
|
BytesRemaining = BytesToCopy - LocalBytesCopied;
|
|
|
|
AmountToCopy = ((BytesRemaining < DestCurrentBufferLen)?
|
|
(BytesRemaining):(DestCurrentBufferLen));
|
|
|
|
NdisMoveMemory(
|
|
DestVirtualAddress,
|
|
SrcCurrentAddress,
|
|
AmountToCopy);
|
|
|
|
SrcCurrentAddress += AmountToCopy;
|
|
LocalBytesCopied += AmountToCopy;
|
|
DestCurrentBufferLen -= AmountToCopy;
|
|
|
|
}
|
|
|
|
*BytesCopied = LocalBytesCopied;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
LtRefAdapter(
|
|
IN OUT PLT_ADAPTER Adapter,
|
|
OUT PNDIS_STATUS Status
|
|
)
|
|
{
|
|
*Status = NDIS_STATUS_SUCCESS;
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
if ((Adapter->Flags & ADAPTER_CLOSING) == 0)
|
|
{
|
|
Adapter->RefCount++;
|
|
}
|
|
else
|
|
{
|
|
*Status = NDIS_STATUS_ADAPTER_REMOVED;
|
|
}
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
LtRefAdapterNonInterlock(
|
|
IN OUT PLT_ADAPTER Adapter,
|
|
OUT PNDIS_STATUS Status
|
|
)
|
|
{
|
|
*Status = NDIS_STATUS_SUCCESS;
|
|
|
|
if ((Adapter->Flags & ADAPTER_CLOSING) == 0)
|
|
{
|
|
Adapter->RefCount++;
|
|
}
|
|
else
|
|
{
|
|
*Status = NDIS_STATUS_ADAPTER_REMOVED;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
LtDeRefAdapter(
|
|
IN OUT PLT_ADAPTER Adapter
|
|
)
|
|
{
|
|
BOOLEAN Close = FALSE;
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
if (--Adapter->RefCount == 0)
|
|
Close = TRUE;
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
if (Close)
|
|
{
|
|
// Last reference on adapter is gone.
|
|
ASSERTMSG("LtDeRefAdapter: Closing flag not set!\n",
|
|
(Adapter->Flags & ADAPTER_CLOSING));
|
|
|
|
ASSERTMSG("LtDeRefAdapter: Open count is not zero!\n",
|
|
(Adapter->OpenCount == 0));
|
|
|
|
// Release the adapter
|
|
NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
|
|
NdisFreeSpinLock(&Adapter->Lock);
|
|
|
|
NdisFreeMemory(
|
|
Adapter,
|
|
sizeof(LT_ADAPTER),
|
|
(UINT)0);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
LtRefBinding(
|
|
IN OUT PLT_OPEN Binding,
|
|
OUT PNDIS_STATUS Status
|
|
)
|
|
{
|
|
*Status = NDIS_STATUS_SUCCESS;
|
|
|
|
NdisAcquireSpinLock(&Binding->LtAdapter->Lock);
|
|
if ((Binding->Flags & BINDING_CLOSING) == 0)
|
|
{
|
|
Binding->RefCount++;
|
|
}
|
|
else
|
|
{
|
|
*Status = NDIS_STATUS_CLOSING;
|
|
}
|
|
NdisReleaseSpinLock(&Binding->LtAdapter->Lock);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
LtRefBindingNextNcNonInterlock(
|
|
IN PLIST_ENTRY PList,
|
|
IN PLIST_ENTRY PEnd,
|
|
OUT PLT_OPEN * Binding,
|
|
OUT PNDIS_STATUS Status
|
|
)
|
|
{
|
|
PLT_OPEN ChkBinding;
|
|
*Status = NDIS_STATUS_FAILURE;
|
|
|
|
*Binding = NULL;
|
|
while (PList != PEnd)
|
|
{
|
|
ChkBinding = CONTAINING_RECORD(PList, LT_OPEN, Linkage);
|
|
|
|
DBGPRINT(DBG_COMP_UTILS, DBG_LEVEL_INFO,
|
|
("LtRefBindingNextNcNonInterlock: ChkBind %lx\n", ChkBinding));
|
|
|
|
LtRefBindingNonInterlock(ChkBinding, Status);
|
|
if (*Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
*Binding = ChkBinding;
|
|
break;
|
|
}
|
|
|
|
PList = PList->Flink;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
LtRefBindingNonInterlock(
|
|
IN OUT PLT_OPEN Binding,
|
|
OUT PNDIS_STATUS Status
|
|
)
|
|
{
|
|
*Status = NDIS_STATUS_SUCCESS;
|
|
|
|
if ((Binding->Flags & BINDING_CLOSING) == 0)
|
|
{
|
|
Binding->RefCount++;
|
|
}
|
|
else
|
|
{
|
|
*Status = NDIS_STATUS_CLOSING;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
LtDeRefBinding(
|
|
IN OUT PLT_OPEN Binding
|
|
)
|
|
{
|
|
BOOLEAN Close = FALSE;
|
|
|
|
NdisAcquireSpinLock(&Binding->LtAdapter->Lock);
|
|
if (--Binding->RefCount == 0)
|
|
{
|
|
Close = TRUE;
|
|
RemoveEntryList(&Binding->Linkage);
|
|
(Binding->LtAdapter->OpenCount)--;
|
|
}
|
|
NdisReleaseSpinLock(&Binding->LtAdapter->Lock);
|
|
|
|
if (Close)
|
|
{
|
|
NDIS_HANDLE OpenBindingContext = Binding->NdisBindingContext;
|
|
|
|
// Last reference on binding is gone.
|
|
ASSERTMSG("LtDeRefBinding: Closing flag not set!\n",
|
|
(Binding->Flags & BINDING_CLOSING));
|
|
|
|
// Release the binding and remove its reference on the
|
|
// adapter.
|
|
NdisCompleteCloseAdapter(OpenBindingContext, NDIS_STATUS_SUCCESS);
|
|
LtDeReferenceAdapter(Binding->LtAdapter);
|
|
|
|
// Free up the binding structure
|
|
NdisFreeMemory(Binding, sizeof(LT_OPEN), (UINT)0);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|