ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

neighbor.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS TCP/IP protocol driver
00004  * FILE:        network/neighbor.c
00005  * PURPOSE:     Neighbor address cache
00006  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
00007  * REVISIONS:
00008  *   CSH 01/08-2000 Created
00009  */
00010 
00011 #include "precomp.h"
00012 
00013 NEIGHBOR_CACHE_TABLE NeighborCache[NB_HASHMASK + 1];
00014 
00015 VOID NBCompleteSend( PVOID Context,
00016              PNDIS_PACKET NdisPacket,
00017              NDIS_STATUS Status ) {
00018     PNEIGHBOR_PACKET Packet = (PNEIGHBOR_PACKET)Context;
00019     TI_DbgPrint(MID_TRACE, ("Called\n"));
00020     ASSERT_KM_POINTER(Packet);
00021     ASSERT_KM_POINTER(Packet->Complete);
00022     Packet->Complete( Packet->Context, Packet->Packet, Status );
00023     TI_DbgPrint(MID_TRACE, ("Completed\n"));
00024     ExFreePoolWithTag( Packet, NEIGHBOR_PACKET_TAG );
00025     TI_DbgPrint(MID_TRACE, ("Freed\n"));
00026 }
00027 
00028 VOID NBSendPackets( PNEIGHBOR_CACHE_ENTRY NCE ) {
00029     PLIST_ENTRY PacketEntry;
00030     PNEIGHBOR_PACKET Packet;
00031     UINT HashValue;
00032 
00033     ASSERT(!(NCE->State & NUD_INCOMPLETE));
00034 
00035     HashValue  = *(PULONG)(&NCE->Address.Address);
00036     HashValue ^= HashValue >> 16;
00037     HashValue ^= HashValue >> 8;
00038     HashValue ^= HashValue >> 4;
00039     HashValue &= NB_HASHMASK;
00040 
00041     /* Send any waiting packets */
00042     while ((PacketEntry = ExInterlockedRemoveHeadList(&NCE->PacketQueue,
00043                                               &NeighborCache[HashValue].Lock)) != NULL)
00044     {
00045     Packet = CONTAINING_RECORD( PacketEntry, NEIGHBOR_PACKET, Next );
00046 
00047     TI_DbgPrint
00048         (MID_TRACE,
00049          ("PacketEntry: %x, NdisPacket %x\n",
00050           PacketEntry, Packet->Packet));
00051 
00052     PC(Packet->Packet)->DLComplete = NBCompleteSend;
00053     PC(Packet->Packet)->Context  = Packet;
00054 
00055     NCE->Interface->Transmit
00056         ( NCE->Interface->Context,
00057           Packet->Packet,
00058           0,
00059           NCE->LinkAddress,
00060           LAN_PROTO_IPv4 );
00061     }
00062 }
00063 
00064 /* Must be called with table lock acquired */
00065 VOID NBFlushPacketQueue( PNEIGHBOR_CACHE_ENTRY NCE,
00066              NTSTATUS ErrorCode ) {
00067     PLIST_ENTRY PacketEntry;
00068     PNEIGHBOR_PACKET Packet;
00069 
00070     while( !IsListEmpty(&NCE->PacketQueue) ) {
00071         PacketEntry = RemoveHeadList(&NCE->PacketQueue);
00072     Packet = CONTAINING_RECORD
00073         ( PacketEntry, NEIGHBOR_PACKET, Next );
00074 
00075         ASSERT_KM_POINTER(Packet);
00076 
00077     TI_DbgPrint
00078         (MID_TRACE,
00079          ("PacketEntry: %x, NdisPacket %x\n",
00080           PacketEntry, Packet->Packet));
00081 
00082         ASSERT_KM_POINTER(Packet->Complete);
00083     Packet->Complete( Packet->Context,
00084                           Packet->Packet,
00085                           ErrorCode );
00086 
00087     ExFreePoolWithTag( Packet, NEIGHBOR_PACKET_TAG );
00088     }
00089 }
00090 
00091 VOID NBTimeout(VOID)
00092 /*
00093  * FUNCTION: Neighbor address cache timeout handler
00094  * NOTES:
00095  *     This routine is called by IPTimeout to remove outdated cache
00096  *     entries.
00097  */
00098 {
00099     UINT i;
00100     PNEIGHBOR_CACHE_ENTRY *PrevNCE;
00101     PNEIGHBOR_CACHE_ENTRY NCE;
00102     NDIS_STATUS Status;
00103 
00104     for (i = 0; i <= NB_HASHMASK; i++) {
00105         TcpipAcquireSpinLockAtDpcLevel(&NeighborCache[i].Lock);
00106 
00107         for (PrevNCE = &NeighborCache[i].Cache;
00108              (NCE = *PrevNCE) != NULL;) {
00109             if (NCE->State & NUD_INCOMPLETE)
00110             {
00111                 /* Solicit for an address */
00112                 NBSendSolicit(NCE);
00113                 if (NCE->EventTimer == 0)
00114                 {
00115                     NCE->EventCount++;
00116                     if (NCE->EventCount == ARP_INCOMPLETE_TIMEOUT)
00117                     {
00118                         NBFlushPacketQueue(NCE, NDIS_STATUS_NETWORK_UNREACHABLE);
00119                         NCE->EventCount = 0;
00120                     }
00121                 }
00122             }
00123 
00124             /* Check if event timer is running */
00125             if (NCE->EventTimer > 0)  {
00126                 ASSERT(!(NCE->State & NUD_PERMANENT));
00127                 NCE->EventCount++;
00128 
00129                 if ((NCE->EventCount > ARP_RATE &&
00130                      NCE->EventCount % ARP_TIMEOUT_RETRANSMISSION == 0) ||
00131                     (NCE->EventCount == ARP_RATE))
00132                 {
00133                     /* We haven't gotten a packet from them in
00134                      * EventCount seconds so we mark them as stale
00135                      * and solicit now */
00136                     NCE->State |= NUD_STALE;
00137                     NBSendSolicit(NCE);
00138                 }
00139                 if (NCE->EventTimer - NCE->EventCount == 0) {
00140                     /* Unlink and destroy the NCE */
00141                     *PrevNCE = NCE->Next;
00142                     
00143                     /* Choose the proper failure status */
00144                     if (NCE->State & NUD_INCOMPLETE)
00145                     {
00146                         /* We couldn't get an address to this IP at all */
00147                         Status = NDIS_STATUS_NETWORK_UNREACHABLE;
00148                     }
00149                     else
00150                     {
00151                         /* This guy was stale for way too long */
00152                         Status = NDIS_STATUS_REQUEST_ABORTED;
00153                     }
00154                     
00155                     NBFlushPacketQueue(NCE, Status);
00156 
00157                     ExFreePoolWithTag(NCE, NCE_TAG);
00158 
00159                     continue;
00160                 }
00161             }
00162             PrevNCE = &NCE->Next;
00163         }
00164 
00165         TcpipReleaseSpinLockFromDpcLevel(&NeighborCache[i].Lock);
00166     }
00167 }
00168 
00169 VOID NBStartup(VOID)
00170 /*
00171  * FUNCTION: Starts the neighbor cache
00172  */
00173 {
00174     UINT i;
00175 
00176     TI_DbgPrint(DEBUG_NCACHE, ("Called.\n"));
00177 
00178     for (i = 0; i <= NB_HASHMASK; i++) {
00179     NeighborCache[i].Cache = NULL;
00180     TcpipInitializeSpinLock(&NeighborCache[i].Lock);
00181     }
00182 }
00183 
00184 VOID NBShutdown(VOID)
00185 /*
00186  * FUNCTION: Shuts down the neighbor cache
00187  */
00188 {
00189   PNEIGHBOR_CACHE_ENTRY NextNCE;
00190   PNEIGHBOR_CACHE_ENTRY CurNCE;
00191   KIRQL OldIrql;
00192   UINT i;
00193 
00194   TI_DbgPrint(DEBUG_NCACHE, ("Called.\n"));
00195 
00196   /* Remove possible entries from the cache */
00197   for (i = 0; i <= NB_HASHMASK; i++)
00198     {
00199       TcpipAcquireSpinLock(&NeighborCache[i].Lock, &OldIrql);
00200 
00201       CurNCE = NeighborCache[i].Cache;
00202       while (CurNCE) {
00203           NextNCE = CurNCE->Next;
00204 
00205           /* Flush wait queue */
00206       NBFlushPacketQueue( CurNCE, NDIS_STATUS_NOT_ACCEPTED );
00207 
00208           ExFreePoolWithTag(CurNCE, NCE_TAG);
00209 
00210       CurNCE = NextNCE;
00211       }
00212 
00213     NeighborCache[i].Cache = NULL;
00214 
00215     TcpipReleaseSpinLock(&NeighborCache[i].Lock, OldIrql);
00216   }
00217 
00218   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
00219 }
00220 
00221 VOID NBSendSolicit(PNEIGHBOR_CACHE_ENTRY NCE)
00222 /*
00223  * FUNCTION: Sends a neighbor solicitation message
00224  * ARGUMENTS:
00225  *   NCE = Pointer to NCE of neighbor to solicit
00226  * NOTES:
00227  *   May be called with lock held on NCE's table
00228  */
00229 {
00230     TI_DbgPrint(DEBUG_NCACHE, ("Called. NCE (0x%X).\n", NCE));
00231 
00232     ARPTransmit(&NCE->Address,
00233                 (NCE->State & NUD_INCOMPLETE) ? NULL : NCE->LinkAddress,
00234                 NCE->Interface);
00235 }
00236 
00237 VOID NBDestroyNeighborsForInterface(PIP_INTERFACE Interface)
00238 {
00239     KIRQL OldIrql;
00240     PNEIGHBOR_CACHE_ENTRY *PrevNCE;
00241     PNEIGHBOR_CACHE_ENTRY NCE;
00242     ULONG i;
00243 
00244     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00245     for (i = 0; i <= NB_HASHMASK; i++)
00246     {
00247         TcpipAcquireSpinLockAtDpcLevel(&NeighborCache[i].Lock);
00248         
00249         for (PrevNCE = &NeighborCache[i].Cache;
00250              (NCE = *PrevNCE) != NULL;)
00251         {
00252             if (NCE->Interface == Interface)
00253             {
00254                 /* Unlink and destroy the NCE */
00255                 *PrevNCE = NCE->Next;
00256 
00257                 NBFlushPacketQueue(NCE, NDIS_STATUS_REQUEST_ABORTED);
00258                 ExFreePoolWithTag(NCE, NCE_TAG);
00259 
00260                 continue;
00261             }
00262             else
00263             {
00264                 PrevNCE = &NCE->Next;
00265             }
00266         }
00267         
00268         TcpipReleaseSpinLockFromDpcLevel(&NeighborCache[i].Lock);
00269     }
00270     KeLowerIrql(OldIrql);
00271 }
00272 
00273 PNEIGHBOR_CACHE_ENTRY NBAddNeighbor(
00274   PIP_INTERFACE Interface,
00275   PIP_ADDRESS Address,
00276   PVOID LinkAddress,
00277   UINT LinkAddressLength,
00278   UCHAR State,
00279   UINT EventTimer)
00280 /*
00281  * FUNCTION: Adds a neighbor to the neighbor cache
00282  * ARGUMENTS:
00283  *   Interface         = Pointer to interface
00284  *   Address           = Pointer to IP address
00285  *   LinkAddress       = Pointer to link address (may be NULL)
00286  *   LinkAddressLength = Length of link address
00287  *   State             = State of NCE
00288  * RETURNS:
00289  *   Pointer to NCE, NULL there is not enough free resources
00290  * NOTES:
00291  *   The NCE if referenced for the caller if created. The NCE retains
00292  *   a reference to the IP address if it is created, the caller is
00293  *   responsible for providing this reference
00294  */
00295 {
00296   PNEIGHBOR_CACHE_ENTRY NCE;
00297   ULONG HashValue;
00298   KIRQL OldIrql;
00299 
00300   TI_DbgPrint
00301       (DEBUG_NCACHE,
00302        ("Called. Interface (0x%X)  Address (0x%X)  "
00303     "LinkAddress (0x%X)  LinkAddressLength (%d)  State (0x%X)\n",
00304     Interface, Address, LinkAddress, LinkAddressLength, State));
00305 
00306   NCE = ExAllocatePoolWithTag
00307       (NonPagedPool, sizeof(NEIGHBOR_CACHE_ENTRY) + LinkAddressLength,
00308        NCE_TAG);
00309   if (NCE == NULL)
00310     {
00311       TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00312       return NULL;
00313     }
00314 
00315   NCE->Interface = Interface;
00316   NCE->Address = *Address;
00317   NCE->LinkAddressLength = LinkAddressLength;
00318   NCE->LinkAddress = (PVOID)&NCE[1];
00319   if( LinkAddress )
00320       RtlCopyMemory(NCE->LinkAddress, LinkAddress, LinkAddressLength);
00321   else
00322       memset(NCE->LinkAddress, 0xff, LinkAddressLength);
00323   NCE->State = State;
00324   NCE->EventTimer = EventTimer;
00325   NCE->EventCount = 0;
00326   InitializeListHead( &NCE->PacketQueue );
00327 
00328   TI_DbgPrint(MID_TRACE,("NCE: %x\n", NCE));
00329 
00330   HashValue = *(PULONG)&Address->Address;
00331   HashValue ^= HashValue >> 16;
00332   HashValue ^= HashValue >> 8;
00333   HashValue ^= HashValue >> 4;
00334   HashValue &= NB_HASHMASK;
00335 
00336   TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);
00337 
00338   NCE->Next = NeighborCache[HashValue].Cache;
00339   NeighborCache[HashValue].Cache = NCE;
00340 
00341   TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
00342 
00343   return NCE;
00344 }
00345 
00346 VOID NBUpdateNeighbor(
00347   PNEIGHBOR_CACHE_ENTRY NCE,
00348   PVOID LinkAddress,
00349   UCHAR State)
00350 /*
00351  * FUNCTION: Update link address information in NCE
00352  * ARGUMENTS:
00353  *   NCE         = Pointer to NCE to update
00354  *   LinkAddress = Pointer to link address
00355  *   State       = State of NCE
00356  * NOTES:
00357  *   The link address and state is updated. Any waiting packets are sent
00358  */
00359 {
00360     KIRQL OldIrql;
00361     UINT HashValue;
00362 
00363     TI_DbgPrint(DEBUG_NCACHE, ("Called. NCE (0x%X)  LinkAddress (0x%X)  State (0x%X).\n", NCE, LinkAddress, State));
00364 
00365     HashValue  = *(PULONG)(&NCE->Address.Address);
00366     HashValue ^= HashValue >> 16;
00367     HashValue ^= HashValue >> 8;
00368     HashValue ^= HashValue >> 4;
00369     HashValue &= NB_HASHMASK;
00370 
00371     TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);
00372 
00373     RtlCopyMemory(NCE->LinkAddress, LinkAddress, NCE->LinkAddressLength);
00374     NCE->State = State;
00375     NCE->EventCount = 0;
00376 
00377     TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
00378 
00379     if( !(NCE->State & NUD_INCOMPLETE) )
00380     {
00381         if (NCE->EventTimer) NCE->EventTimer = ARP_COMPLETE_TIMEOUT;
00382         NBSendPackets( NCE );
00383     }
00384 }
00385 
00386 VOID
00387 NBResetNeighborTimeout(PIP_ADDRESS Address)
00388 {
00389     KIRQL OldIrql;
00390     UINT HashValue;
00391     PNEIGHBOR_CACHE_ENTRY NCE;
00392 
00393     TI_DbgPrint(DEBUG_NCACHE, ("Resetting NCE timout for 0x%s\n", A2S(Address)));
00394 
00395     HashValue  = *(PULONG)(&Address->Address);
00396     HashValue ^= HashValue >> 16;
00397     HashValue ^= HashValue >> 8;
00398     HashValue ^= HashValue >> 4;
00399     HashValue &= NB_HASHMASK;
00400 
00401     TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);
00402 
00403     for (NCE = NeighborCache[HashValue].Cache;
00404          NCE != NULL;
00405          NCE = NCE->Next)
00406     {
00407          if (AddrIsEqual(Address, &NCE->Address))
00408          {
00409              NCE->EventCount = 0;
00410              break;
00411          }
00412     }
00413 
00414     TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
00415 }
00416 
00417 PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor(
00418   PIP_ADDRESS Address)
00419 /*
00420  * FUNCTION: Locates a neighbor in the neighbor cache
00421  * ARGUMENTS:
00422  *   Address = Pointer to IP address
00423  * RETURNS:
00424  *   Pointer to NCE, NULL if not found
00425  * NOTES:
00426  *   If the NCE is found, it is referenced. The caller is
00427  *   responsible for dereferencing it again after use
00428  */
00429 {
00430   PNEIGHBOR_CACHE_ENTRY NCE;
00431   UINT HashValue;
00432   KIRQL OldIrql;
00433 
00434   TI_DbgPrint(DEBUG_NCACHE, ("Called. Address (0x%X).\n", Address));
00435 
00436   HashValue = *(PULONG)&Address->Address;
00437   HashValue ^= HashValue >> 16;
00438   HashValue ^= HashValue >> 8;
00439   HashValue ^= HashValue >> 4;
00440   HashValue &= NB_HASHMASK;
00441 
00442   TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);
00443 
00444   NCE = NeighborCache[HashValue].Cache;
00445 
00446   while ((NCE) && (!AddrIsEqual(Address, &NCE->Address)))
00447     {
00448       NCE = NCE->Next;
00449     }
00450 
00451   TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
00452 
00453   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
00454 
00455   return NCE;
00456 }
00457 
00458 PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor(
00459   PIP_INTERFACE Interface,
00460   PIP_ADDRESS Address,
00461   BOOLEAN NoTimeout)
00462 /*
00463  * FUNCTION: Tries to find a neighbor and if unsuccesful, creates a new NCE
00464  * ARGUMENTS:
00465  *   Interface = Pointer to interface to use (in case NCE is not found)
00466  *   Address   = Pointer to IP address
00467  * RETURNS:
00468  *   Pointer to NCE, NULL if there is not enough free resources
00469  * NOTES:
00470  *   The NCE is referenced if found or created. The caller is
00471  *   responsible for dereferencing it again after use
00472  */
00473 {
00474   PNEIGHBOR_CACHE_ENTRY NCE;
00475 
00476   TI_DbgPrint(DEBUG_NCACHE, ("Called. Interface (0x%X)  Address (0x%X).\n", Interface, Address));
00477 
00478   NCE = NBLocateNeighbor(Address);
00479   if (NCE == NULL)
00480     {
00481         TI_DbgPrint(MID_TRACE,("BCAST: %s\n", A2S(&Interface->Broadcast)));
00482         if( AddrIsEqual(Address, &Interface->Broadcast) ||
00483             AddrIsUnspecified(Address) ) {
00484             TI_DbgPrint(MID_TRACE,("Packet targeted at broadcast addr\n"));
00485             NCE = NBAddNeighbor(Interface, Address, NULL,
00486                                 Interface->AddressLength, NUD_PERMANENT, 0);
00487         } else {
00488             NCE = NBAddNeighbor(Interface, Address, NULL,
00489                                 Interface->AddressLength, NUD_INCOMPLETE, NoTimeout ? 0 : ARP_INCOMPLETE_TIMEOUT);
00490             if (!NCE) return NULL;
00491             NBSendSolicit(NCE);
00492         }
00493     }
00494 
00495   return NCE;
00496 }
00497 
00498 BOOLEAN NBQueuePacket(
00499   PNEIGHBOR_CACHE_ENTRY NCE,
00500   PNDIS_PACKET NdisPacket,
00501   PNEIGHBOR_PACKET_COMPLETE PacketComplete,
00502   PVOID PacketContext)
00503 /*
00504  * FUNCTION: Queues a packet on an NCE for later transmission
00505  * ARGUMENTS:
00506  *   NCE        = Pointer to NCE to queue packet on
00507  *   NdisPacket = Pointer to NDIS packet to queue
00508  * RETURNS:
00509  *   TRUE if the packet was successfully queued, FALSE if not
00510  */
00511 {
00512   KIRQL OldIrql;
00513   PNEIGHBOR_PACKET Packet;
00514   UINT HashValue;
00515 
00516   TI_DbgPrint
00517       (DEBUG_NCACHE,
00518        ("Called. NCE (0x%X)  NdisPacket (0x%X).\n", NCE, NdisPacket));
00519 
00520   Packet = ExAllocatePoolWithTag( NonPagedPool, sizeof(NEIGHBOR_PACKET),
00521                                   NEIGHBOR_PACKET_TAG );
00522   if( !Packet ) return FALSE;
00523 
00524   /* FIXME: Should we limit the number of queued packets? */
00525 
00526   HashValue  = *(PULONG)(&NCE->Address.Address);
00527   HashValue ^= HashValue >> 16;
00528   HashValue ^= HashValue >> 8;
00529   HashValue ^= HashValue >> 4;
00530   HashValue &= NB_HASHMASK;
00531 
00532   TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);
00533 
00534   Packet->Complete = PacketComplete;
00535   Packet->Context = PacketContext;
00536   Packet->Packet = NdisPacket;
00537   InsertTailList( &NCE->PacketQueue, &Packet->Next );
00538 
00539   TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
00540 
00541   if( !(NCE->State & NUD_INCOMPLETE) )
00542       NBSendPackets( NCE );
00543 
00544   return TRUE;
00545 }
00546 
00547 VOID NBRemoveNeighbor(
00548   PNEIGHBOR_CACHE_ENTRY NCE)
00549 /*
00550  * FUNCTION: Removes a neighbor from the neighbor cache
00551  * ARGUMENTS:
00552  *   NCE = Pointer to NCE to remove from cache
00553  * NOTES:
00554  *   The NCE must be in a safe state
00555  */
00556 {
00557   PNEIGHBOR_CACHE_ENTRY *PrevNCE;
00558   PNEIGHBOR_CACHE_ENTRY CurNCE;
00559   ULONG HashValue;
00560   KIRQL OldIrql;
00561 
00562   TI_DbgPrint(DEBUG_NCACHE, ("Called. NCE (0x%X).\n", NCE));
00563 
00564   HashValue  = *(PULONG)(&NCE->Address.Address);
00565   HashValue ^= HashValue >> 16;
00566   HashValue ^= HashValue >> 8;
00567   HashValue ^= HashValue >> 4;
00568   HashValue &= NB_HASHMASK;
00569 
00570   TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);
00571 
00572   /* Search the list and remove the NCE from the list if found */
00573   for (PrevNCE = &NeighborCache[HashValue].Cache;
00574     (CurNCE = *PrevNCE) != NULL;
00575     PrevNCE = &CurNCE->Next)
00576     {
00577       if (CurNCE == NCE)
00578         {
00579           /* Found it, now unlink it from the list */
00580           *PrevNCE = CurNCE->Next;
00581 
00582       NBFlushPacketQueue( CurNCE, NDIS_STATUS_REQUEST_ABORTED );
00583           ExFreePoolWithTag(CurNCE, NCE_TAG);
00584 
00585       break;
00586         }
00587     }
00588 
00589   TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
00590 }
00591 
00592 ULONG NBCopyNeighbors
00593 (PIP_INTERFACE Interface,
00594  PIPARP_ENTRY ArpTable)
00595 {
00596   PNEIGHBOR_CACHE_ENTRY CurNCE;
00597   KIRQL OldIrql;
00598   UINT Size = 0, i;
00599 
00600   for (i = 0; i <= NB_HASHMASK; i++) {
00601       TcpipAcquireSpinLock(&NeighborCache[i].Lock, &OldIrql);
00602       for( CurNCE = NeighborCache[i].Cache;
00603        CurNCE;
00604        CurNCE = CurNCE->Next ) {
00605       if( CurNCE->Interface == Interface &&
00606               !AddrIsEqual( &CurNCE->Address, &CurNCE->Interface->Unicast ) ) {
00607           if( ArpTable ) {
00608           ArpTable[Size].Index = Interface->Index;
00609           ArpTable[Size].AddrSize = CurNCE->LinkAddressLength;
00610           RtlCopyMemory
00611               (ArpTable[Size].PhysAddr, 
00612                CurNCE->LinkAddress,
00613                CurNCE->LinkAddressLength);
00614           ArpTable[Size].LogAddr = CurNCE->Address.Address.IPv4Address;
00615           if( CurNCE->State & NUD_PERMANENT )
00616               ArpTable[Size].Type = ARP_ENTRY_STATIC;
00617           else if( CurNCE->State & NUD_INCOMPLETE )
00618               ArpTable[Size].Type = ARP_ENTRY_INVALID;
00619           else
00620               ArpTable[Size].Type = ARP_ENTRY_DYNAMIC;
00621           }
00622           Size++;
00623       }
00624       }
00625       TcpipReleaseSpinLock(&NeighborCache[i].Lock, OldIrql);
00626   }
00627   
00628   return Size;
00629 }

Generated on Fri May 25 2012 04:34:30 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.