From: Cameron Gutman Date: Sat, 10 Oct 2009 07:43:39 +0000 (+0000) Subject: - Fix timeout values X-Git-Tag: ReactOS-0.3.11~578 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=05c582bcbdd4605e8bfa5fabc101fc301b6296e8 - Fix timeout values - Don't reply to ARP requests unless they are address to us - We now reset the NCE timeout if we receive a packet from the neighbor - Fixes ARP flooding (bug 4879) svn path=/trunk/; revision=43354 --- diff --git a/reactos/drivers/network/tcpip/include/arp.h b/reactos/drivers/network/tcpip/include/arp.h index 95a24861138..dd9f23a53af 100644 --- a/reactos/drivers/network/tcpip/include/arp.h +++ b/reactos/drivers/network/tcpip/include/arp.h @@ -24,7 +24,7 @@ typedef struct ARP_HEADER { #define ARP_OPCODE_REPLY WH2N(0x0002) /* ARP reply */ -BOOLEAN ARPTransmit(PIP_ADDRESS Address, PIP_INTERFACE Interface); +BOOLEAN ARPTransmit(PIP_ADDRESS Address, PVOID LinkAddress, PIP_INTERFACE Interface); VOID ARPReceive( PVOID Context, diff --git a/reactos/drivers/network/tcpip/include/neighbor.h b/reactos/drivers/network/tcpip/include/neighbor.h index f1a43b247e1..95ea1f92769 100644 --- a/reactos/drivers/network/tcpip/include/neighbor.h +++ b/reactos/drivers/network/tcpip/include/neighbor.h @@ -44,11 +44,14 @@ typedef struct NEIGHBOR_CACHE_ENTRY { #define NUD_PERMANENT 0x02 #define NUD_STALE 0x04 +/* Number of seconds between ARP transmissions */ +#define ARP_RATE 900 + /* Number of seconds before the NCE times out */ -#define ARP_TIMEOUT 30 +#define ARP_TIMEOUT ARP_RATE + 15 -/* Number of seconds between ARP transmissions */ -#define ARP_RATE 10 +/* Number of seconds before retransmission */ +#define ARP_TIMEOUT_RETRANSMISSION 5 extern NEIGHBOR_CACHE_TABLE NeighborCache[NB_HASHMASK + 1]; @@ -98,6 +101,9 @@ ULONG NBCopyNeighbors( PIP_INTERFACE Interface, PIPARP_ENTRY ArpTable); +VOID NBResetNeighborTimeout( + PIP_ADDRESS Address); + #endif /* __NEIGHBOR_H */ /* EOF */ diff --git a/reactos/lib/drivers/ip/network/arp.c b/reactos/lib/drivers/ip/network/arp.c index d8c2f177c8e..3a956120bbf 100644 --- a/reactos/lib/drivers/ip/network/arp.c +++ b/reactos/lib/drivers/ip/network/arp.c @@ -108,7 +108,8 @@ VOID ARPTransmitComplete( } -BOOLEAN ARPTransmit(PIP_ADDRESS Address, PIP_INTERFACE Interface) +BOOLEAN ARPTransmit(PIP_ADDRESS Address, PVOID LinkAddress, + PIP_INTERFACE Interface) /* * FUNCTION: Creates an ARP request and transmits it on a network * ARGUMENTS: @@ -152,7 +153,7 @@ BOOLEAN ARPTransmit(PIP_ADDRESS Address, PIP_INTERFACE Interface) (UCHAR)ProtoAddrLen, /* Protocol address length */ Interface->Address, /* Sender's (local) hardware address */ &Interface->Unicast.Address.IPv4Address,/* Sender's (local) protocol address */ - NULL, /* Don't care */ + LinkAddress, /* Target's (remote) hardware address */ &Address->Address.IPv4Address, /* Target's (remote) protocol address */ ARP_OPCODE_REQUEST); /* ARP request */ @@ -225,7 +226,8 @@ VOID ARPReceive( Header->HWAddrLen, 0, ARP_TIMEOUT); } - if (Header->Opcode != ARP_OPCODE_REQUEST) + if (Header->Opcode != ARP_OPCODE_REQUEST || + !AddrIsEqual(&Address, &Interface->Unicast)) return; /* This is a request for our address. Swap the addresses and diff --git a/reactos/lib/drivers/ip/network/ip.c b/reactos/lib/drivers/ip/network/ip.c index a47d2ff28d2..f13dd614e8c 100644 --- a/reactos/lib/drivers/ip/network/ip.c +++ b/reactos/lib/drivers/ip/network/ip.c @@ -93,10 +93,12 @@ VOID IPDispatchProtocol( */ { UINT Protocol; + IP_ADDRESS SrcAddress; switch (IPPacket->Type) { case IP_ADDRESS_V4: Protocol = ((PIPv4_HEADER)(IPPacket->Header))->Protocol; + AddrInitIPv4(&SrcAddress, ((PIPv4_HEADER)(IPPacket->Header))->SrcAddr); break; case IP_ADDRESS_V6: /* FIXME: IPv6 adresses not supported */ @@ -107,6 +109,8 @@ VOID IPDispatchProtocol( return; } + NBResetNeighborTimeout(&SrcAddress); + if (Protocol < IP_PROTOCOL_TABLE_SIZE) { /* Call the appropriate protocol handler */ @@ -219,7 +223,7 @@ VOID IPAddInterfaceRoute( PIP_INTERFACE IF ) { /* Send a gratuitous ARP packet to update the route caches of * other computers */ if (IF != Loopback) - ARPTransmit(NULL, IF); + ARPTransmit(NULL, NULL, IF); } BOOLEAN IPRegisterInterface( diff --git a/reactos/lib/drivers/ip/network/neighbor.c b/reactos/lib/drivers/ip/network/neighbor.c index 295ac908cfd..941faccdb5c 100644 --- a/reactos/lib/drivers/ip/network/neighbor.c +++ b/reactos/lib/drivers/ip/network/neighbor.c @@ -105,20 +105,35 @@ VOID NBTimeout(VOID) TcpipAcquireSpinLock(&NeighborCache[i].Lock, &OldIrql); for (PrevNCE = &NeighborCache[i].Cache; - (NCE = *PrevNCE) != NULL; - PrevNCE = &NCE->Next) { + (NCE = *PrevNCE) != NULL;) { /* Check if event timer is running */ if (NCE->EventTimer > 0) { ASSERT(!(NCE->State & NUD_PERMANENT)); NCE->EventCount++; - if (NCE->EventCount % ARP_RATE == 0) + 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) { - NCE->State |= NUD_STALE; + /* Solicit one last time */ + NBSendSolicit(NCE); - NCE->EventCount = 0; + /* Unlink and destroy the NCE */ + *PrevNCE = NCE->Next; + + NBFlushPacketQueue(NCE, NDIS_STATUS_REQUEST_ABORTED); + exFreePool(NCE); + + continue; } } + PrevNCE = &NCE->Next; } TcpipReleaseSpinLock(&NeighborCache[i].Lock, OldIrql); @@ -188,7 +203,8 @@ VOID NBSendSolicit(PNEIGHBOR_CACHE_ENTRY NCE) { TI_DbgPrint(DEBUG_NCACHE, ("Called. NCE (0x%X).\n", NCE)); - ARPTransmit(&NCE->Address, NCE->Interface); + ARPTransmit(&NCE->Address, NCE->LinkAddress, + NCE->Interface); } PNEIGHBOR_CACHE_ENTRY NBAddNeighbor( @@ -302,6 +318,37 @@ VOID NBUpdateNeighbor( 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) /*