[ros-diffs] [cgutman] 43354: - 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)

cgutman at svn.reactos.org cgutman at svn.reactos.org
Sat Oct 10 09:43:39 CEST 2009


Author: cgutman
Date: Sat Oct 10 09:43:39 2009
New Revision: 43354

URL: http://svn.reactos.org/svn/reactos?rev=43354&view=rev
Log:
 - 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)

Modified:
    trunk/reactos/drivers/network/tcpip/include/arp.h
    trunk/reactos/drivers/network/tcpip/include/neighbor.h
    trunk/reactos/lib/drivers/ip/network/arp.c
    trunk/reactos/lib/drivers/ip/network/ip.c
    trunk/reactos/lib/drivers/ip/network/neighbor.c

Modified: trunk/reactos/drivers/network/tcpip/include/arp.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/include/arp.h?rev=43354&r1=43353&r2=43354&view=diff
==============================================================================
--- trunk/reactos/drivers/network/tcpip/include/arp.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/tcpip/include/arp.h [iso-8859-1] Sat Oct 10 09:43:39 2009
@@ -24,7 +24,7 @@
 #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,

Modified: trunk/reactos/drivers/network/tcpip/include/neighbor.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/include/neighbor.h?rev=43354&r1=43353&r2=43354&view=diff
==============================================================================
--- trunk/reactos/drivers/network/tcpip/include/neighbor.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/tcpip/include/neighbor.h [iso-8859-1] Sat Oct 10 09:43:39 2009
@@ -44,11 +44,14 @@
 #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 @@
     PIP_INTERFACE Interface,
     PIPARP_ENTRY ArpTable);
 
+VOID NBResetNeighborTimeout(
+    PIP_ADDRESS Address);
+
 #endif /* __NEIGHBOR_H */
 
 /* EOF */

Modified: trunk/reactos/lib/drivers/ip/network/arp.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/network/arp.c?rev=43354&r1=43353&r2=43354&view=diff
==============================================================================
--- trunk/reactos/lib/drivers/ip/network/arp.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/ip/network/arp.c [iso-8859-1] Sat Oct 10 09:43:39 2009
@@ -108,7 +108,8 @@
 }
 
 
-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 @@
         (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 @@
             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

Modified: trunk/reactos/lib/drivers/ip/network/ip.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/network/ip.c?rev=43354&r1=43353&r2=43354&view=diff
==============================================================================
--- trunk/reactos/lib/drivers/ip/network/ip.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/ip/network/ip.c [iso-8859-1] Sat Oct 10 09:43:39 2009
@@ -93,10 +93,12 @@
  */
 {
     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 @@
         return;
     }
 
+    NBResetNeighborTimeout(&SrcAddress);
+
     if (Protocol < IP_PROTOCOL_TABLE_SIZE)
     {
        /* Call the appropriate protocol handler */
@@ -219,7 +223,7 @@
     /* 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(

Modified: trunk/reactos/lib/drivers/ip/network/neighbor.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/network/neighbor.c?rev=43354&r1=43353&r2=43354&view=diff
==============================================================================
--- trunk/reactos/lib/drivers/ip/network/neighbor.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/ip/network/neighbor.c [iso-8859-1] Sat Oct 10 09:43:39 2009
@@ -105,20 +105,35 @@
         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;
-
-                    NCE->EventCount = 0;
+                    /* Solicit one last time */
+                    NBSendSolicit(NCE);
+
+                    /* 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 @@
 {
     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(
@@ -300,6 +316,37 @@
 
     if( !(NCE->State & NUD_INCOMPLETE) )
 	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(




More information about the Ros-diffs mailing list