mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:12:59 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
672
sdk/lib/drivers/ip/network/neighbor.c
Normal file
672
sdk/lib/drivers/ip/network/neighbor.c
Normal file
|
@ -0,0 +1,672 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS TCP/IP protocol driver
|
||||
* FILE: network/neighbor.c
|
||||
* PURPOSE: Neighbor address cache
|
||||
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||
* REVISIONS:
|
||||
* CSH 01/08-2000 Created
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
NEIGHBOR_CACHE_TABLE NeighborCache[NB_HASHMASK + 1];
|
||||
|
||||
VOID NBCompleteSend( PVOID Context,
|
||||
PNDIS_PACKET NdisPacket,
|
||||
NDIS_STATUS Status ) {
|
||||
PNEIGHBOR_PACKET Packet = (PNEIGHBOR_PACKET)Context;
|
||||
TI_DbgPrint(MID_TRACE, ("Called\n"));
|
||||
ASSERT_KM_POINTER(Packet);
|
||||
ASSERT_KM_POINTER(Packet->Complete);
|
||||
Packet->Complete( Packet->Context, Packet->Packet, Status );
|
||||
TI_DbgPrint(MID_TRACE, ("Completed\n"));
|
||||
ExFreePoolWithTag( Packet, NEIGHBOR_PACKET_TAG );
|
||||
TI_DbgPrint(MID_TRACE, ("Freed\n"));
|
||||
}
|
||||
|
||||
VOID NBSendPackets( PNEIGHBOR_CACHE_ENTRY NCE ) {
|
||||
PLIST_ENTRY PacketEntry;
|
||||
PNEIGHBOR_PACKET Packet;
|
||||
UINT HashValue;
|
||||
|
||||
ASSERT(!(NCE->State & NUD_INCOMPLETE));
|
||||
|
||||
HashValue = *(PULONG)(&NCE->Address.Address);
|
||||
HashValue ^= HashValue >> 16;
|
||||
HashValue ^= HashValue >> 8;
|
||||
HashValue ^= HashValue >> 4;
|
||||
HashValue &= NB_HASHMASK;
|
||||
|
||||
/* Send any waiting packets */
|
||||
while ((PacketEntry = ExInterlockedRemoveHeadList(&NCE->PacketQueue,
|
||||
&NeighborCache[HashValue].Lock)) != NULL)
|
||||
{
|
||||
Packet = CONTAINING_RECORD( PacketEntry, NEIGHBOR_PACKET, Next );
|
||||
|
||||
TI_DbgPrint
|
||||
(MID_TRACE,
|
||||
("PacketEntry: %x, NdisPacket %x\n",
|
||||
PacketEntry, Packet->Packet));
|
||||
|
||||
PC(Packet->Packet)->DLComplete = NBCompleteSend;
|
||||
PC(Packet->Packet)->Context = Packet;
|
||||
|
||||
NCE->Interface->Transmit
|
||||
( NCE->Interface->Context,
|
||||
Packet->Packet,
|
||||
0,
|
||||
NCE->LinkAddress,
|
||||
LAN_PROTO_IPv4 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Must be called with table lock acquired */
|
||||
VOID NBFlushPacketQueue( PNEIGHBOR_CACHE_ENTRY NCE,
|
||||
NTSTATUS ErrorCode ) {
|
||||
PLIST_ENTRY PacketEntry;
|
||||
PNEIGHBOR_PACKET Packet;
|
||||
|
||||
while( !IsListEmpty(&NCE->PacketQueue) ) {
|
||||
PacketEntry = RemoveHeadList(&NCE->PacketQueue);
|
||||
Packet = CONTAINING_RECORD
|
||||
( PacketEntry, NEIGHBOR_PACKET, Next );
|
||||
|
||||
ASSERT_KM_POINTER(Packet);
|
||||
|
||||
TI_DbgPrint
|
||||
(MID_TRACE,
|
||||
("PacketEntry: %x, NdisPacket %x\n",
|
||||
PacketEntry, Packet->Packet));
|
||||
|
||||
ASSERT_KM_POINTER(Packet->Complete);
|
||||
Packet->Complete( Packet->Context,
|
||||
Packet->Packet,
|
||||
ErrorCode );
|
||||
|
||||
ExFreePoolWithTag( Packet, NEIGHBOR_PACKET_TAG );
|
||||
}
|
||||
}
|
||||
|
||||
VOID NBTimeout(VOID)
|
||||
/*
|
||||
* FUNCTION: Neighbor address cache timeout handler
|
||||
* NOTES:
|
||||
* This routine is called by IPTimeout to remove outdated cache
|
||||
* entries.
|
||||
*/
|
||||
{
|
||||
UINT i;
|
||||
PNEIGHBOR_CACHE_ENTRY *PrevNCE;
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
NDIS_STATUS Status;
|
||||
|
||||
for (i = 0; i <= NB_HASHMASK; i++) {
|
||||
TcpipAcquireSpinLockAtDpcLevel(&NeighborCache[i].Lock);
|
||||
|
||||
for (PrevNCE = &NeighborCache[i].Cache;
|
||||
(NCE = *PrevNCE) != NULL;) {
|
||||
if (NCE->State & NUD_INCOMPLETE)
|
||||
{
|
||||
/* Solicit for an address */
|
||||
NBSendSolicit(NCE);
|
||||
if (NCE->EventTimer == 0)
|
||||
{
|
||||
NCE->EventCount++;
|
||||
if (NCE->EventCount == ARP_INCOMPLETE_TIMEOUT)
|
||||
{
|
||||
NBFlushPacketQueue(NCE, NDIS_STATUS_NETWORK_UNREACHABLE);
|
||||
NCE->EventCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if event timer is running */
|
||||
if (NCE->EventTimer > 0) {
|
||||
ASSERT(!(NCE->State & NUD_PERMANENT));
|
||||
NCE->EventCount++;
|
||||
|
||||
if ((NCE->EventCount > ARP_RATE &&
|
||||
NCE->EventCount % ARP_TIMEOUT_RETRANSMISSION == 0) ||
|
||||
(NCE->EventCount == ARP_RATE))
|
||||
{
|
||||
/* We haven't gotten a packet from them in
|
||||
* EventCount seconds so we mark them as stale
|
||||
* and solicit now */
|
||||
NCE->State |= NUD_STALE;
|
||||
NBSendSolicit(NCE);
|
||||
}
|
||||
if (NCE->EventTimer - NCE->EventCount == 0) {
|
||||
/* Unlink and destroy the NCE */
|
||||
*PrevNCE = NCE->Next;
|
||||
|
||||
/* Choose the proper failure status */
|
||||
if (NCE->State & NUD_INCOMPLETE)
|
||||
{
|
||||
/* We couldn't get an address to this IP at all */
|
||||
Status = NDIS_STATUS_NETWORK_UNREACHABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This guy was stale for way too long */
|
||||
Status = NDIS_STATUS_REQUEST_ABORTED;
|
||||
}
|
||||
|
||||
NBFlushPacketQueue(NCE, Status);
|
||||
|
||||
ExFreePoolWithTag(NCE, NCE_TAG);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
PrevNCE = &NCE->Next;
|
||||
}
|
||||
|
||||
TcpipReleaseSpinLockFromDpcLevel(&NeighborCache[i].Lock);
|
||||
}
|
||||
}
|
||||
|
||||
VOID NBStartup(VOID)
|
||||
/*
|
||||
* FUNCTION: Starts the neighbor cache
|
||||
*/
|
||||
{
|
||||
UINT i;
|
||||
|
||||
TI_DbgPrint(DEBUG_NCACHE, ("Called.\n"));
|
||||
|
||||
for (i = 0; i <= NB_HASHMASK; i++) {
|
||||
NeighborCache[i].Cache = NULL;
|
||||
TcpipInitializeSpinLock(&NeighborCache[i].Lock);
|
||||
}
|
||||
}
|
||||
|
||||
VOID NBShutdown(VOID)
|
||||
/*
|
||||
* FUNCTION: Shuts down the neighbor cache
|
||||
*/
|
||||
{
|
||||
PNEIGHBOR_CACHE_ENTRY NextNCE;
|
||||
PNEIGHBOR_CACHE_ENTRY CurNCE;
|
||||
KIRQL OldIrql;
|
||||
UINT i;
|
||||
|
||||
TI_DbgPrint(DEBUG_NCACHE, ("Called.\n"));
|
||||
|
||||
/* Remove possible entries from the cache */
|
||||
for (i = 0; i <= NB_HASHMASK; i++)
|
||||
{
|
||||
TcpipAcquireSpinLock(&NeighborCache[i].Lock, &OldIrql);
|
||||
|
||||
CurNCE = NeighborCache[i].Cache;
|
||||
while (CurNCE) {
|
||||
NextNCE = CurNCE->Next;
|
||||
|
||||
/* Flush wait queue */
|
||||
NBFlushPacketQueue( CurNCE, NDIS_STATUS_NOT_ACCEPTED );
|
||||
|
||||
ExFreePoolWithTag(CurNCE, NCE_TAG);
|
||||
|
||||
CurNCE = NextNCE;
|
||||
}
|
||||
|
||||
NeighborCache[i].Cache = NULL;
|
||||
|
||||
TcpipReleaseSpinLock(&NeighborCache[i].Lock, OldIrql);
|
||||
}
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
|
||||
}
|
||||
|
||||
VOID NBSendSolicit(PNEIGHBOR_CACHE_ENTRY NCE)
|
||||
/*
|
||||
* FUNCTION: Sends a neighbor solicitation message
|
||||
* ARGUMENTS:
|
||||
* NCE = Pointer to NCE of neighbor to solicit
|
||||
* NOTES:
|
||||
* May be called with lock held on NCE's table
|
||||
*/
|
||||
{
|
||||
TI_DbgPrint(DEBUG_NCACHE, ("Called. NCE (0x%X).\n", NCE));
|
||||
|
||||
ARPTransmit(&NCE->Address,
|
||||
(NCE->State & NUD_INCOMPLETE) ? NULL : NCE->LinkAddress,
|
||||
NCE->Interface);
|
||||
}
|
||||
|
||||
VOID NBDestroyNeighborsForInterface(PIP_INTERFACE Interface)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PNEIGHBOR_CACHE_ENTRY *PrevNCE;
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
ULONG i;
|
||||
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||
for (i = 0; i <= NB_HASHMASK; i++)
|
||||
{
|
||||
TcpipAcquireSpinLockAtDpcLevel(&NeighborCache[i].Lock);
|
||||
|
||||
for (PrevNCE = &NeighborCache[i].Cache;
|
||||
(NCE = *PrevNCE) != NULL;)
|
||||
{
|
||||
if (NCE->Interface == Interface)
|
||||
{
|
||||
/* Unlink and destroy the NCE */
|
||||
*PrevNCE = NCE->Next;
|
||||
|
||||
NBFlushPacketQueue(NCE, NDIS_STATUS_REQUEST_ABORTED);
|
||||
ExFreePoolWithTag(NCE, NCE_TAG);
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
PrevNCE = &NCE->Next;
|
||||
}
|
||||
}
|
||||
|
||||
TcpipReleaseSpinLockFromDpcLevel(&NeighborCache[i].Lock);
|
||||
}
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
|
||||
PNEIGHBOR_CACHE_ENTRY NBAddNeighbor(
|
||||
PIP_INTERFACE Interface,
|
||||
PIP_ADDRESS Address,
|
||||
PVOID LinkAddress,
|
||||
UINT LinkAddressLength,
|
||||
UCHAR State,
|
||||
UINT EventTimer)
|
||||
/*
|
||||
* FUNCTION: Adds a neighbor to the neighbor cache
|
||||
* ARGUMENTS:
|
||||
* Interface = Pointer to interface
|
||||
* Address = Pointer to IP address
|
||||
* LinkAddress = Pointer to link address (may be NULL)
|
||||
* LinkAddressLength = Length of link address
|
||||
* State = State of NCE
|
||||
* RETURNS:
|
||||
* Pointer to NCE, NULL there is not enough free resources
|
||||
* NOTES:
|
||||
* The NCE if referenced for the caller if created. The NCE retains
|
||||
* a reference to the IP address if it is created, the caller is
|
||||
* responsible for providing this reference
|
||||
*/
|
||||
{
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
ULONG HashValue;
|
||||
KIRQL OldIrql;
|
||||
|
||||
TI_DbgPrint
|
||||
(DEBUG_NCACHE,
|
||||
("Called. Interface (0x%X) Address (0x%X) "
|
||||
"LinkAddress (0x%X) LinkAddressLength (%d) State (0x%X)\n",
|
||||
Interface, Address, LinkAddress, LinkAddressLength, State));
|
||||
|
||||
NCE = ExAllocatePoolWithTag
|
||||
(NonPagedPool, sizeof(NEIGHBOR_CACHE_ENTRY) + LinkAddressLength,
|
||||
NCE_TAG);
|
||||
if (NCE == NULL)
|
||||
{
|
||||
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NCE->Interface = Interface;
|
||||
NCE->Address = *Address;
|
||||
NCE->LinkAddressLength = LinkAddressLength;
|
||||
NCE->LinkAddress = (PVOID)&NCE[1];
|
||||
if( LinkAddress )
|
||||
RtlCopyMemory(NCE->LinkAddress, LinkAddress, LinkAddressLength);
|
||||
else
|
||||
memset(NCE->LinkAddress, 0xff, LinkAddressLength);
|
||||
NCE->State = State;
|
||||
NCE->EventTimer = EventTimer;
|
||||
NCE->EventCount = 0;
|
||||
InitializeListHead( &NCE->PacketQueue );
|
||||
|
||||
TI_DbgPrint(MID_TRACE,("NCE: %x\n", NCE));
|
||||
|
||||
HashValue = *(PULONG)&Address->Address;
|
||||
HashValue ^= HashValue >> 16;
|
||||
HashValue ^= HashValue >> 8;
|
||||
HashValue ^= HashValue >> 4;
|
||||
HashValue &= NB_HASHMASK;
|
||||
|
||||
TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);
|
||||
|
||||
NCE->Next = NeighborCache[HashValue].Cache;
|
||||
NeighborCache[HashValue].Cache = NCE;
|
||||
|
||||
TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
|
||||
|
||||
return NCE;
|
||||
}
|
||||
|
||||
VOID NBUpdateNeighbor(
|
||||
PNEIGHBOR_CACHE_ENTRY NCE,
|
||||
PVOID LinkAddress,
|
||||
UCHAR State)
|
||||
/*
|
||||
* FUNCTION: Update link address information in NCE
|
||||
* ARGUMENTS:
|
||||
* NCE = Pointer to NCE to update
|
||||
* LinkAddress = Pointer to link address
|
||||
* State = State of NCE
|
||||
* NOTES:
|
||||
* The link address and state is updated. Any waiting packets are sent
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
UINT HashValue;
|
||||
|
||||
TI_DbgPrint(DEBUG_NCACHE, ("Called. NCE (0x%X) LinkAddress (0x%X) State (0x%X).\n", NCE, LinkAddress, State));
|
||||
|
||||
HashValue = *(PULONG)(&NCE->Address.Address);
|
||||
HashValue ^= HashValue >> 16;
|
||||
HashValue ^= HashValue >> 8;
|
||||
HashValue ^= HashValue >> 4;
|
||||
HashValue &= NB_HASHMASK;
|
||||
|
||||
TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);
|
||||
|
||||
RtlCopyMemory(NCE->LinkAddress, LinkAddress, NCE->LinkAddressLength);
|
||||
NCE->State = State;
|
||||
NCE->EventCount = 0;
|
||||
|
||||
TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
|
||||
|
||||
if( !(NCE->State & NUD_INCOMPLETE) )
|
||||
{
|
||||
if (NCE->EventTimer) NCE->EventTimer = ARP_COMPLETE_TIMEOUT;
|
||||
NBSendPackets( NCE );
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NBResetNeighborTimeout(PIP_ADDRESS Address)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
UINT HashValue;
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
|
||||
TI_DbgPrint(DEBUG_NCACHE, ("Resetting NCE timout for 0x%s\n", A2S(Address)));
|
||||
|
||||
HashValue = *(PULONG)(&Address->Address);
|
||||
HashValue ^= HashValue >> 16;
|
||||
HashValue ^= HashValue >> 8;
|
||||
HashValue ^= HashValue >> 4;
|
||||
HashValue &= NB_HASHMASK;
|
||||
|
||||
TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);
|
||||
|
||||
for (NCE = NeighborCache[HashValue].Cache;
|
||||
NCE != NULL;
|
||||
NCE = NCE->Next)
|
||||
{
|
||||
if (AddrIsEqual(Address, &NCE->Address))
|
||||
{
|
||||
NCE->EventCount = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
|
||||
}
|
||||
|
||||
PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor(
|
||||
PIP_ADDRESS Address,
|
||||
PIP_INTERFACE Interface)
|
||||
/*
|
||||
* FUNCTION: Locates a neighbor in the neighbor cache
|
||||
* ARGUMENTS:
|
||||
* Address = Pointer to IP address
|
||||
* Interface = Pointer to IP interface
|
||||
* RETURNS:
|
||||
* Pointer to NCE, NULL if not found
|
||||
* NOTES:
|
||||
* If the NCE is found, it is referenced. The caller is
|
||||
* responsible for dereferencing it again after use
|
||||
*/
|
||||
{
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
UINT HashValue;
|
||||
KIRQL OldIrql;
|
||||
PIP_INTERFACE FirstInterface;
|
||||
|
||||
TI_DbgPrint(DEBUG_NCACHE, ("Called. Address (0x%X).\n", Address));
|
||||
|
||||
HashValue = *(PULONG)&Address->Address;
|
||||
HashValue ^= HashValue >> 16;
|
||||
HashValue ^= HashValue >> 8;
|
||||
HashValue ^= HashValue >> 4;
|
||||
HashValue &= NB_HASHMASK;
|
||||
|
||||
TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);
|
||||
|
||||
/* If there's no adapter specified, we'll look for a match on
|
||||
* each one. */
|
||||
if (Interface == NULL)
|
||||
{
|
||||
FirstInterface = GetDefaultInterface();
|
||||
Interface = FirstInterface;
|
||||
}
|
||||
else
|
||||
{
|
||||
FirstInterface = NULL;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
NCE = NeighborCache[HashValue].Cache;
|
||||
while (NCE != NULL)
|
||||
{
|
||||
if (NCE->Interface == Interface &&
|
||||
AddrIsEqual(Address, &NCE->Address))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
NCE = NCE->Next;
|
||||
}
|
||||
|
||||
if (NCE != NULL)
|
||||
break;
|
||||
}
|
||||
while ((FirstInterface != NULL) &&
|
||||
((Interface = GetDefaultInterface()) != FirstInterface));
|
||||
|
||||
if ((NCE == NULL) && (FirstInterface != NULL))
|
||||
{
|
||||
/* This time we'll even match loopback NCEs */
|
||||
NCE = NeighborCache[HashValue].Cache;
|
||||
while (NCE != NULL)
|
||||
{
|
||||
if (AddrIsEqual(Address, &NCE->Address))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
NCE = NCE->Next;
|
||||
}
|
||||
}
|
||||
|
||||
TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
|
||||
|
||||
return NCE;
|
||||
}
|
||||
|
||||
PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor(
|
||||
PIP_INTERFACE Interface,
|
||||
PIP_ADDRESS Address,
|
||||
BOOLEAN NoTimeout)
|
||||
/*
|
||||
* FUNCTION: Tries to find a neighbor and if unsuccesful, creates a new NCE
|
||||
* ARGUMENTS:
|
||||
* Interface = Pointer to interface to use (in case NCE is not found)
|
||||
* Address = Pointer to IP address
|
||||
* RETURNS:
|
||||
* Pointer to NCE, NULL if there is not enough free resources
|
||||
* NOTES:
|
||||
* The NCE is referenced if found or created. The caller is
|
||||
* responsible for dereferencing it again after use
|
||||
*/
|
||||
{
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
|
||||
TI_DbgPrint(DEBUG_NCACHE, ("Called. Interface (0x%X) Address (0x%X).\n", Interface, Address));
|
||||
|
||||
NCE = NBLocateNeighbor(Address, Interface);
|
||||
if (NCE == NULL)
|
||||
{
|
||||
TI_DbgPrint(MID_TRACE,("BCAST: %s\n", A2S(&Interface->Broadcast)));
|
||||
if( AddrIsEqual(Address, &Interface->Broadcast) ||
|
||||
AddrIsUnspecified(Address) ) {
|
||||
TI_DbgPrint(MID_TRACE,("Packet targeted at broadcast addr\n"));
|
||||
NCE = NBAddNeighbor(Interface, Address, NULL,
|
||||
Interface->AddressLength, NUD_PERMANENT, 0);
|
||||
} else {
|
||||
NCE = NBAddNeighbor(Interface, Address, NULL,
|
||||
Interface->AddressLength, NUD_INCOMPLETE, NoTimeout ? 0 : ARP_INCOMPLETE_TIMEOUT);
|
||||
if (!NCE) return NULL;
|
||||
NBSendSolicit(NCE);
|
||||
}
|
||||
}
|
||||
|
||||
return NCE;
|
||||
}
|
||||
|
||||
BOOLEAN NBQueuePacket(
|
||||
PNEIGHBOR_CACHE_ENTRY NCE,
|
||||
PNDIS_PACKET NdisPacket,
|
||||
PNEIGHBOR_PACKET_COMPLETE PacketComplete,
|
||||
PVOID PacketContext)
|
||||
/*
|
||||
* FUNCTION: Queues a packet on an NCE for later transmission
|
||||
* ARGUMENTS:
|
||||
* NCE = Pointer to NCE to queue packet on
|
||||
* NdisPacket = Pointer to NDIS packet to queue
|
||||
* RETURNS:
|
||||
* TRUE if the packet was successfully queued, FALSE if not
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PNEIGHBOR_PACKET Packet;
|
||||
UINT HashValue;
|
||||
|
||||
TI_DbgPrint
|
||||
(DEBUG_NCACHE,
|
||||
("Called. NCE (0x%X) NdisPacket (0x%X).\n", NCE, NdisPacket));
|
||||
|
||||
Packet = ExAllocatePoolWithTag( NonPagedPool, sizeof(NEIGHBOR_PACKET),
|
||||
NEIGHBOR_PACKET_TAG );
|
||||
if( !Packet ) return FALSE;
|
||||
|
||||
/* FIXME: Should we limit the number of queued packets? */
|
||||
|
||||
HashValue = *(PULONG)(&NCE->Address.Address);
|
||||
HashValue ^= HashValue >> 16;
|
||||
HashValue ^= HashValue >> 8;
|
||||
HashValue ^= HashValue >> 4;
|
||||
HashValue &= NB_HASHMASK;
|
||||
|
||||
TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);
|
||||
|
||||
Packet->Complete = PacketComplete;
|
||||
Packet->Context = PacketContext;
|
||||
Packet->Packet = NdisPacket;
|
||||
InsertTailList( &NCE->PacketQueue, &Packet->Next );
|
||||
|
||||
TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
|
||||
|
||||
if( !(NCE->State & NUD_INCOMPLETE) )
|
||||
NBSendPackets( NCE );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID NBRemoveNeighbor(
|
||||
PNEIGHBOR_CACHE_ENTRY NCE)
|
||||
/*
|
||||
* FUNCTION: Removes a neighbor from the neighbor cache
|
||||
* ARGUMENTS:
|
||||
* NCE = Pointer to NCE to remove from cache
|
||||
* NOTES:
|
||||
* The NCE must be in a safe state
|
||||
*/
|
||||
{
|
||||
PNEIGHBOR_CACHE_ENTRY *PrevNCE;
|
||||
PNEIGHBOR_CACHE_ENTRY CurNCE;
|
||||
ULONG HashValue;
|
||||
KIRQL OldIrql;
|
||||
|
||||
TI_DbgPrint(DEBUG_NCACHE, ("Called. NCE (0x%X).\n", NCE));
|
||||
|
||||
HashValue = *(PULONG)(&NCE->Address.Address);
|
||||
HashValue ^= HashValue >> 16;
|
||||
HashValue ^= HashValue >> 8;
|
||||
HashValue ^= HashValue >> 4;
|
||||
HashValue &= NB_HASHMASK;
|
||||
|
||||
TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);
|
||||
|
||||
/* Search the list and remove the NCE from the list if found */
|
||||
for (PrevNCE = &NeighborCache[HashValue].Cache;
|
||||
(CurNCE = *PrevNCE) != NULL;
|
||||
PrevNCE = &CurNCE->Next)
|
||||
{
|
||||
if (CurNCE == NCE)
|
||||
{
|
||||
/* Found it, now unlink it from the list */
|
||||
*PrevNCE = CurNCE->Next;
|
||||
|
||||
NBFlushPacketQueue( CurNCE, NDIS_STATUS_REQUEST_ABORTED );
|
||||
ExFreePoolWithTag(CurNCE, NCE_TAG);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
|
||||
}
|
||||
|
||||
ULONG NBCopyNeighbors
|
||||
(PIP_INTERFACE Interface,
|
||||
PIPARP_ENTRY ArpTable)
|
||||
{
|
||||
PNEIGHBOR_CACHE_ENTRY CurNCE;
|
||||
KIRQL OldIrql;
|
||||
UINT Size = 0, i;
|
||||
|
||||
for (i = 0; i <= NB_HASHMASK; i++) {
|
||||
TcpipAcquireSpinLock(&NeighborCache[i].Lock, &OldIrql);
|
||||
for( CurNCE = NeighborCache[i].Cache;
|
||||
CurNCE;
|
||||
CurNCE = CurNCE->Next ) {
|
||||
if( CurNCE->Interface == Interface &&
|
||||
!AddrIsEqual( &CurNCE->Address, &CurNCE->Interface->Unicast ) ) {
|
||||
if( ArpTable ) {
|
||||
ArpTable[Size].Index = Interface->Index;
|
||||
ArpTable[Size].AddrSize = CurNCE->LinkAddressLength;
|
||||
RtlCopyMemory
|
||||
(ArpTable[Size].PhysAddr,
|
||||
CurNCE->LinkAddress,
|
||||
CurNCE->LinkAddressLength);
|
||||
ArpTable[Size].LogAddr = CurNCE->Address.Address.IPv4Address;
|
||||
if( CurNCE->State & NUD_PERMANENT )
|
||||
ArpTable[Size].Type = ARP_ENTRY_STATIC;
|
||||
else if( CurNCE->State & NUD_INCOMPLETE )
|
||||
ArpTable[Size].Type = ARP_ENTRY_INVALID;
|
||||
else
|
||||
ArpTable[Size].Type = ARP_ENTRY_DYNAMIC;
|
||||
}
|
||||
Size++;
|
||||
}
|
||||
}
|
||||
TcpipReleaseSpinLock(&NeighborCache[i].Lock, OldIrql);
|
||||
}
|
||||
|
||||
return Size;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue