Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenneighbor.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
1.7.6.1
|