mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 18:35:41 +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
520
sdk/lib/drivers/ip/network/router.c
Normal file
520
sdk/lib/drivers/ip/network/router.c
Normal file
|
@ -0,0 +1,520 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS TCP/IP protocol driver
|
||||
* FILE: network/router.c
|
||||
* PURPOSE: IP routing subsystem
|
||||
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||
* NOTES:
|
||||
* This file holds authoritative routing information.
|
||||
* Information queries on the route table should be handled here.
|
||||
* This information should always override the route cache info.
|
||||
* REVISIONS:
|
||||
* CSH 01/08-2000 Created
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
LIST_ENTRY FIBListHead;
|
||||
KSPIN_LOCK FIBLock;
|
||||
|
||||
void RouterDumpRoutes() {
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PLIST_ENTRY NextEntry;
|
||||
PFIB_ENTRY Current;
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
|
||||
TI_DbgPrint(DEBUG_ROUTER,("Dumping Routes\n"));
|
||||
|
||||
CurrentEntry = FIBListHead.Flink;
|
||||
while (CurrentEntry != &FIBListHead) {
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);
|
||||
|
||||
NCE = Current->Router;
|
||||
|
||||
TI_DbgPrint(DEBUG_ROUTER,("Examining FIBE %x\n", Current));
|
||||
TI_DbgPrint(DEBUG_ROUTER,("... NetworkAddress %s\n", A2S(&Current->NetworkAddress)));
|
||||
TI_DbgPrint(DEBUG_ROUTER,("... NCE->Address . %s\n", A2S(&NCE->Address)));
|
||||
|
||||
CurrentEntry = NextEntry;
|
||||
}
|
||||
|
||||
TI_DbgPrint(DEBUG_ROUTER,("Dumping Routes ... Done\n"));
|
||||
}
|
||||
|
||||
VOID FreeFIB(
|
||||
PVOID Object)
|
||||
/*
|
||||
* FUNCTION: Frees an forward information base object
|
||||
* ARGUMENTS:
|
||||
* Object = Pointer to an forward information base structure
|
||||
*/
|
||||
{
|
||||
ExFreePoolWithTag(Object, FIB_TAG);
|
||||
}
|
||||
|
||||
|
||||
VOID DestroyFIBE(
|
||||
PFIB_ENTRY FIBE)
|
||||
/*
|
||||
* FUNCTION: Destroys an forward information base entry
|
||||
* ARGUMENTS:
|
||||
* FIBE = Pointer to FIB entry
|
||||
* NOTES:
|
||||
* The forward information base lock must be held when called
|
||||
*/
|
||||
{
|
||||
TI_DbgPrint(DEBUG_ROUTER, ("Called. FIBE (0x%X).\n", FIBE));
|
||||
|
||||
/* Unlink the FIB entry from the list */
|
||||
RemoveEntryList(&FIBE->ListEntry);
|
||||
|
||||
/* And free the FIB entry */
|
||||
FreeFIB(FIBE);
|
||||
}
|
||||
|
||||
|
||||
VOID DestroyFIBEs(
|
||||
VOID)
|
||||
/*
|
||||
* FUNCTION: Destroys all forward information base entries
|
||||
* NOTES:
|
||||
* The forward information base lock must be held when called
|
||||
*/
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PLIST_ENTRY NextEntry;
|
||||
PFIB_ENTRY Current;
|
||||
|
||||
/* Search the list and remove every FIB entry we find */
|
||||
CurrentEntry = FIBListHead.Flink;
|
||||
while (CurrentEntry != &FIBListHead) {
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);
|
||||
/* Destroy the FIB entry */
|
||||
DestroyFIBE(Current);
|
||||
CurrentEntry = NextEntry;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UINT CountFIBs(PIP_INTERFACE IF) {
|
||||
UINT FibCount = 0;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PLIST_ENTRY NextEntry;
|
||||
PFIB_ENTRY Current;
|
||||
|
||||
CurrentEntry = FIBListHead.Flink;
|
||||
while (CurrentEntry != &FIBListHead) {
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);
|
||||
if (Current->Router->Interface == IF)
|
||||
FibCount++;
|
||||
CurrentEntry = NextEntry;
|
||||
}
|
||||
|
||||
return FibCount;
|
||||
}
|
||||
|
||||
|
||||
UINT CopyFIBs( PIP_INTERFACE IF, PFIB_ENTRY Target ) {
|
||||
UINT FibCount = 0;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PLIST_ENTRY NextEntry;
|
||||
PFIB_ENTRY Current;
|
||||
|
||||
CurrentEntry = FIBListHead.Flink;
|
||||
while (CurrentEntry != &FIBListHead) {
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);
|
||||
if (Current->Router->Interface == IF)
|
||||
{
|
||||
Target[FibCount] = *Current;
|
||||
FibCount++;
|
||||
}
|
||||
CurrentEntry = NextEntry;
|
||||
}
|
||||
|
||||
return FibCount;
|
||||
}
|
||||
|
||||
|
||||
UINT CommonPrefixLength(
|
||||
PIP_ADDRESS Address1,
|
||||
PIP_ADDRESS Address2)
|
||||
/*
|
||||
* FUNCTION: Computes the length of the longest prefix common to two addresses
|
||||
* ARGUMENTS:
|
||||
* Address1 = Pointer to first address
|
||||
* Address2 = Pointer to second address
|
||||
* NOTES:
|
||||
* The two addresses must be of the same type
|
||||
* RETURNS:
|
||||
* Length of longest common prefix
|
||||
*/
|
||||
{
|
||||
PUCHAR Addr1, Addr2;
|
||||
UINT Size;
|
||||
UINT i, j;
|
||||
UINT Bitmask;
|
||||
|
||||
TI_DbgPrint(DEBUG_ROUTER, ("Called. Address1 (0x%X) Address2 (0x%X).\n", Address1, Address2));
|
||||
|
||||
/*TI_DbgPrint(DEBUG_ROUTER, ("Target (%s) \n", A2S(Address1)));*/
|
||||
/*TI_DbgPrint(DEBUG_ROUTER, ("Adapter (%s).\n", A2S(Address2)));*/
|
||||
|
||||
if (Address1->Type == IP_ADDRESS_V4)
|
||||
Size = sizeof(IPv4_RAW_ADDRESS);
|
||||
else
|
||||
Size = sizeof(IPv6_RAW_ADDRESS);
|
||||
|
||||
Addr1 = (PUCHAR)&Address1->Address.IPv4Address;
|
||||
Addr2 = (PUCHAR)&Address2->Address.IPv4Address;
|
||||
|
||||
/* Find first non-matching byte */
|
||||
for (i = 0; i < Size && Addr1[i] == Addr2[i]; i++);
|
||||
if( i == Size ) return 8 * i;
|
||||
|
||||
/* Find first non-matching bit */
|
||||
Bitmask = 0x80;
|
||||
for (j = 0; (Addr1[i] & Bitmask) == (Addr2[i] & Bitmask); j++)
|
||||
Bitmask >>= 1;
|
||||
|
||||
TI_DbgPrint(DEBUG_ROUTER, ("Returning %d\n", 8 * i + j));
|
||||
|
||||
return 8 * i + j;
|
||||
}
|
||||
|
||||
|
||||
PFIB_ENTRY RouterAddRoute(
|
||||
PIP_ADDRESS NetworkAddress,
|
||||
PIP_ADDRESS Netmask,
|
||||
PNEIGHBOR_CACHE_ENTRY Router,
|
||||
UINT Metric)
|
||||
/*
|
||||
* FUNCTION: Adds a route to the Forward Information Base (FIB)
|
||||
* ARGUMENTS:
|
||||
* NetworkAddress = Pointer to address of network
|
||||
* Netmask = Pointer to netmask of network
|
||||
* Router = Pointer to NCE of router to use
|
||||
* Metric = Cost of this route
|
||||
* RETURNS:
|
||||
* Pointer to FIB entry if the route was added, NULL if not
|
||||
* NOTES:
|
||||
* The FIB entry references the NetworkAddress, Netmask and
|
||||
* the NCE of the router. The caller is responsible for providing
|
||||
* these references
|
||||
*/
|
||||
{
|
||||
PFIB_ENTRY FIBE;
|
||||
|
||||
TI_DbgPrint(DEBUG_ROUTER, ("Called. NetworkAddress (0x%X) Netmask (0x%X) "
|
||||
"Router (0x%X) Metric (%d).\n", NetworkAddress, Netmask, Router, Metric));
|
||||
|
||||
TI_DbgPrint(DEBUG_ROUTER, ("NetworkAddress (%s) Netmask (%s) Router (%s).\n",
|
||||
A2S(NetworkAddress),
|
||||
A2S(Netmask),
|
||||
A2S(&Router->Address)));
|
||||
|
||||
FIBE = ExAllocatePoolWithTag(NonPagedPool, sizeof(FIB_ENTRY), FIB_TAG);
|
||||
if (!FIBE) {
|
||||
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RtlCopyMemory( &FIBE->NetworkAddress, NetworkAddress,
|
||||
sizeof(FIBE->NetworkAddress) );
|
||||
RtlCopyMemory( &FIBE->Netmask, Netmask,
|
||||
sizeof(FIBE->Netmask) );
|
||||
FIBE->Router = Router;
|
||||
FIBE->Metric = Metric;
|
||||
|
||||
/* Add FIB to the forward information base */
|
||||
TcpipInterlockedInsertTailList(&FIBListHead, &FIBE->ListEntry, &FIBLock);
|
||||
|
||||
return FIBE;
|
||||
}
|
||||
|
||||
|
||||
PNEIGHBOR_CACHE_ENTRY RouterGetRoute(PIP_ADDRESS Destination)
|
||||
/*
|
||||
* FUNCTION: Finds a router to use to get to Destination
|
||||
* ARGUMENTS:
|
||||
* Destination = Pointer to destination address (NULL means don't care)
|
||||
* RETURNS:
|
||||
* Pointer to NCE for router, NULL if none was found
|
||||
* NOTES:
|
||||
* If found the NCE is referenced
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PLIST_ENTRY NextEntry;
|
||||
PFIB_ENTRY Current;
|
||||
UCHAR State;
|
||||
UINT Length, BestLength = 0, MaskLength;
|
||||
PNEIGHBOR_CACHE_ENTRY NCE, BestNCE = NULL;
|
||||
|
||||
TI_DbgPrint(DEBUG_ROUTER, ("Called. Destination (0x%X)\n", Destination));
|
||||
|
||||
TI_DbgPrint(DEBUG_ROUTER, ("Destination (%s)\n", A2S(Destination)));
|
||||
|
||||
TcpipAcquireSpinLock(&FIBLock, &OldIrql);
|
||||
|
||||
CurrentEntry = FIBListHead.Flink;
|
||||
while (CurrentEntry != &FIBListHead) {
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);
|
||||
|
||||
NCE = Current->Router;
|
||||
State = NCE->State;
|
||||
|
||||
Length = CommonPrefixLength(Destination, &Current->NetworkAddress);
|
||||
MaskLength = AddrCountPrefixBits(&Current->Netmask);
|
||||
|
||||
TI_DbgPrint(DEBUG_ROUTER,("This-Route: %s (Sharing %d bits)\n",
|
||||
A2S(&NCE->Address), Length));
|
||||
|
||||
if(Length >= MaskLength && (Length > BestLength || !BestNCE) &&
|
||||
((!(State & NUD_STALE) && !(State & NUD_INCOMPLETE)) || !BestNCE)) {
|
||||
/* This seems to be a better router */
|
||||
BestNCE = NCE;
|
||||
BestLength = Length;
|
||||
TI_DbgPrint(DEBUG_ROUTER,("Route selected\n"));
|
||||
}
|
||||
|
||||
CurrentEntry = NextEntry;
|
||||
}
|
||||
|
||||
TcpipReleaseSpinLock(&FIBLock, OldIrql);
|
||||
|
||||
if( BestNCE ) {
|
||||
TI_DbgPrint(DEBUG_ROUTER,("Routing to %s\n", A2S(&BestNCE->Address)));
|
||||
} else {
|
||||
TI_DbgPrint(DEBUG_ROUTER,("Packet won't be routed\n"));
|
||||
}
|
||||
|
||||
return BestNCE;
|
||||
}
|
||||
|
||||
PNEIGHBOR_CACHE_ENTRY RouteGetRouteToDestination(PIP_ADDRESS Destination)
|
||||
/*
|
||||
* FUNCTION: Locates an RCN describing a route to a destination address
|
||||
* ARGUMENTS:
|
||||
* Destination = Pointer to destination address to find route to
|
||||
* RCN = Address of pointer to an RCN
|
||||
* RETURNS:
|
||||
* Status of operation
|
||||
* NOTES:
|
||||
* The RCN is referenced for the caller. The caller is responsible
|
||||
* for dereferencing it after use
|
||||
*/
|
||||
{
|
||||
PNEIGHBOR_CACHE_ENTRY NCE = NULL;
|
||||
PIP_INTERFACE Interface;
|
||||
|
||||
TI_DbgPrint(DEBUG_RCACHE, ("Called. Destination (0x%X)\n", Destination));
|
||||
|
||||
TI_DbgPrint(DEBUG_RCACHE, ("Destination (%s)\n", A2S(Destination)));
|
||||
|
||||
#if 0
|
||||
TI_DbgPrint(MIN_TRACE, ("Displaying tree (before).\n"));
|
||||
PrintTree(RouteCache);
|
||||
#endif
|
||||
|
||||
/* Check if the destination is on-link */
|
||||
Interface = FindOnLinkInterface(Destination);
|
||||
if (Interface) {
|
||||
/* The destination address is on-link. Check our neighbor cache */
|
||||
NCE = NBFindOrCreateNeighbor(Interface, Destination, FALSE);
|
||||
} else {
|
||||
/* Destination is not on any subnets we're on. Find a router to use */
|
||||
NCE = RouterGetRoute(Destination);
|
||||
}
|
||||
|
||||
if( NCE )
|
||||
TI_DbgPrint(DEBUG_ROUTER,("Interface->MTU: %d\n", NCE->Interface->MTU));
|
||||
|
||||
return NCE;
|
||||
}
|
||||
|
||||
VOID RouterRemoveRoutesForInterface(PIP_INTERFACE Interface)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PLIST_ENTRY NextEntry;
|
||||
PFIB_ENTRY Current;
|
||||
|
||||
TcpipAcquireSpinLock(&FIBLock, &OldIrql);
|
||||
|
||||
CurrentEntry = FIBListHead.Flink;
|
||||
while (CurrentEntry != &FIBListHead) {
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);
|
||||
|
||||
if (Interface == Current->Router->Interface)
|
||||
DestroyFIBE(Current);
|
||||
|
||||
CurrentEntry = NextEntry;
|
||||
}
|
||||
|
||||
TcpipReleaseSpinLock(&FIBLock, OldIrql);
|
||||
}
|
||||
|
||||
NTSTATUS RouterRemoveRoute(PIP_ADDRESS Target, PIP_ADDRESS Router)
|
||||
/*
|
||||
* FUNCTION: Removes a route from the Forward Information Base (FIB)
|
||||
* ARGUMENTS:
|
||||
* Target: The machine or network targeted by the route
|
||||
* Router: The router used to pass the packet to the destination
|
||||
*
|
||||
* Searches the FIB and removes a route matching the indicated parameters.
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PLIST_ENTRY NextEntry;
|
||||
PFIB_ENTRY Current;
|
||||
BOOLEAN Found = FALSE;
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
|
||||
TI_DbgPrint(DEBUG_ROUTER, ("Called\n"));
|
||||
TI_DbgPrint(DEBUG_ROUTER, ("Deleting Route From: %s\n", A2S(Router)));
|
||||
TI_DbgPrint(DEBUG_ROUTER, (" To: %s\n", A2S(Target)));
|
||||
|
||||
TcpipAcquireSpinLock(&FIBLock, &OldIrql);
|
||||
|
||||
RouterDumpRoutes();
|
||||
|
||||
CurrentEntry = FIBListHead.Flink;
|
||||
while (CurrentEntry != &FIBListHead) {
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);
|
||||
|
||||
NCE = Current->Router;
|
||||
|
||||
if( AddrIsEqual( &Current->NetworkAddress, Target ) &&
|
||||
AddrIsEqual( &NCE->Address, Router ) ) {
|
||||
Found = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
Current = NULL;
|
||||
CurrentEntry = NextEntry;
|
||||
}
|
||||
|
||||
if( Found ) {
|
||||
TI_DbgPrint(DEBUG_ROUTER, ("Deleting route\n"));
|
||||
DestroyFIBE( Current );
|
||||
}
|
||||
|
||||
RouterDumpRoutes();
|
||||
|
||||
TcpipReleaseSpinLock(&FIBLock, OldIrql);
|
||||
|
||||
TI_DbgPrint(DEBUG_ROUTER, ("Leaving\n"));
|
||||
|
||||
return Found ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
PFIB_ENTRY RouterCreateRoute(
|
||||
PIP_ADDRESS NetworkAddress,
|
||||
PIP_ADDRESS Netmask,
|
||||
PIP_ADDRESS RouterAddress,
|
||||
PIP_INTERFACE Interface,
|
||||
UINT Metric)
|
||||
/*
|
||||
* FUNCTION: Creates a route with IPv4 addresses as parameters
|
||||
* ARGUMENTS:
|
||||
* NetworkAddress = Address of network
|
||||
* Netmask = Netmask of network
|
||||
* RouterAddress = Address of router to use
|
||||
* NTE = Pointer to NTE to use
|
||||
* Metric = Cost of this route
|
||||
* RETURNS:
|
||||
* Pointer to FIB entry if the route was created, NULL if not.
|
||||
* The FIB entry references the NTE. The caller is responsible
|
||||
* for providing this reference
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PLIST_ENTRY NextEntry;
|
||||
PFIB_ENTRY Current;
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
|
||||
TcpipAcquireSpinLock(&FIBLock, &OldIrql);
|
||||
|
||||
CurrentEntry = FIBListHead.Flink;
|
||||
while (CurrentEntry != &FIBListHead) {
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);
|
||||
|
||||
NCE = Current->Router;
|
||||
|
||||
if(AddrIsEqual(NetworkAddress, &Current->NetworkAddress) &&
|
||||
AddrIsEqual(Netmask, &Current->Netmask) &&
|
||||
NCE->Interface == Interface)
|
||||
{
|
||||
TI_DbgPrint(DEBUG_ROUTER,("Attempting to add duplicate route to %s\n", A2S(NetworkAddress)));
|
||||
TcpipReleaseSpinLock(&FIBLock, OldIrql);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CurrentEntry = NextEntry;
|
||||
}
|
||||
|
||||
TcpipReleaseSpinLock(&FIBLock, OldIrql);
|
||||
|
||||
/* The NCE references RouterAddress. The NCE is referenced for us */
|
||||
NCE = NBFindOrCreateNeighbor(Interface, RouterAddress, TRUE);
|
||||
|
||||
if (!NCE) {
|
||||
/* Not enough free resources */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return RouterAddRoute(NetworkAddress, Netmask, NCE, Metric);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS RouterStartup(
|
||||
VOID)
|
||||
/*
|
||||
* FUNCTION: Initializes the routing subsystem
|
||||
* RETURNS:
|
||||
* Status of operation
|
||||
*/
|
||||
{
|
||||
TI_DbgPrint(DEBUG_ROUTER, ("Called.\n"));
|
||||
|
||||
/* Initialize the Forward Information Base */
|
||||
InitializeListHead(&FIBListHead);
|
||||
TcpipInitializeSpinLock(&FIBLock);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS RouterShutdown(
|
||||
VOID)
|
||||
/*
|
||||
* FUNCTION: Shuts down the routing subsystem
|
||||
* RETURNS:
|
||||
* Status of operation
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
TI_DbgPrint(DEBUG_ROUTER, ("Called.\n"));
|
||||
|
||||
/* Clear Forward Information Base */
|
||||
TcpipAcquireSpinLock(&FIBLock, &OldIrql);
|
||||
DestroyFIBEs();
|
||||
TcpipReleaseSpinLock(&FIBLock, OldIrql);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Add table
Add a link
Reference in a new issue