- Defined __NTDRIVER__ to turn on some code that is meant only for kernel mode.

- Removed another address object (AddrBuildAddress)
- Removed ROUTE_CACHE_NODE everywhere and replaced it with NEIGHBOR_CACHE_ENTRY
  anywhere it was used, since NCE contains sufficient information.
  - We will need to reintroduce PathMTU (the only unique information) in RCN.
    I intend to do that by expanding the NCE to contain an entry for each
    remote contact (not only neighbors), and add an MTU field there.
- ICMP, TCP, UDP, RawIP, IPSendDatagram - Changed RCN to NCE
- Protect ip timer work item from being multiply queued under load.
- Router: Add RouteGetRouteToDestination (the only function preserved from
  route.c).  This function is cut down to only calling FindOnLinkInterface
  and RouterGetRoute.
- Added DefaultGateway handling (The default route is automatically added).
- Cleaning in CONNECTION_ENDPOINT (removed ReceivedSegments)
- iinfo: Return correct type number for loopback adapter.

svn path=/trunk/; revision=11871
This commit is contained in:
Art Yerkes 2004-11-30 00:10:41 +00:00
parent 1abe87090e
commit fa6c7ae193
22 changed files with 109 additions and 756 deletions

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.8 2004/11/25 23:56:58 arty Exp $
# $Id: makefile,v 1.9 2004/11/30 00:10:40 arty Exp $
PATH_TO_TOP = ../../..
@ -12,6 +12,7 @@ TARGET_PCH = $(PATH_TO_TOP)/drivers/lib/ip/include/precomp.h
TARGET_CFLAGS = \
-D__USE_W32API \
-DMEMTRACK \
-D__NTDRIVER__ \
-D_SEH_NO_NATIVE_NLG \
-Wall -Werror \
-Iinclude \
@ -35,7 +36,6 @@ TARGET_OBJECTS = \
network/neighbor.o \
network/ports.o \
network/receive.o \
network/route.o \
network/router.o \
network/routines.o \
network/transmit.o \

View file

@ -181,12 +181,11 @@ NTSTATUS AddrGetAddress(
*/
NTSTATUS AddrBuildAddress(
PTRANSPORT_ADDRESS TaAddress,
PIP_ADDRESS *Address,
PIP_ADDRESS Address,
PUSHORT Port)
{
PTDI_ADDRESS_IP ValidAddr;
PTA_ADDRESS TdiAddress = &TaAddress->Address[0];
PIP_ADDRESS IPAddress;
if (TdiAddress->AddressType != TDI_ADDRESS_TYPE_IP) {
TI_DbgPrint
@ -203,12 +202,7 @@ NTSTATUS AddrBuildAddress(
ValidAddr = (PTDI_ADDRESS_IP)TdiAddress->Address;
IPAddress = PoolAllocateBuffer(sizeof(IP_ADDRESS));
if (!IPAddress)
return STATUS_INSUFFICIENT_RESOURCES;
AddrInitIPv4(IPAddress, ValidAddr->in_addr);
*Address = IPAddress;
AddrInitIPv4(Address, ValidAddr->in_addr);
*Port = ValidAddr->sin_port;
return STATUS_SUCCESS;

View file

@ -180,7 +180,7 @@ VOID ICMPTransmit(
* IPPacket = Pointer to IP packet to transmit
*/
{
PROUTE_CACHE_NODE RCN;
PNEIGHBOR_CACHE_ENTRY NCE;
TI_DbgPrint(DEBUG_ICMP, ("Called.\n"));
@ -189,12 +189,10 @@ VOID ICMPTransmit(
IPv4Checksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize, 0);
/* Get a route to the destination address */
if (RouteGetRouteToDestination(&IPPacket->DstAddr, &RCN) == IP_SUCCESS) {
if ((NCE = RouteGetRouteToDestination(&IPPacket->DstAddr))) {
/* Send the packet */
IPSendDatagram(IPPacket, RCN, Complete, Context);
IPSendDatagram(IPPacket, NCE, Complete, Context);
} else {
TI_DbgPrint(MIN_TRACE, ("RCN at (0x%X).\n", RCN));
/* No route to destination (or no free resources) */
TI_DbgPrint(DEBUG_ICMP, ("No route to destination address 0x%X.\n",
IPPacket->DstAddr.Address.IPv4Address));

View file

@ -18,6 +18,7 @@ KSPIN_LOCK NetTableListLock;
UINT MaxLLHeaderSize; /* Largest maximum header size */
UINT MinLLFrameSize; /* Largest minimum frame size */
BOOLEAN IPInitialized = FALSE;
BOOLEAN IpWorkItemQueued = FALSE;
NPAGED_LOOKASIDE_LIST IPPacketList;
/* Work around calling timer at Dpc level */
@ -109,6 +110,8 @@ PIP_PACKET IPInitializePacket(
void STDCALL IPTimeout( PVOID Context ) {
IpWorkItemQueued = FALSE;
/* Check if datagram fragments have taken too long to assemble */
IPDatagramReassemblyTimeout();
@ -238,7 +241,6 @@ BOOLEAN IPRegisterInterface(
{
KIRQL OldIrql;
IP_ADDRESS NetworkAddress;
PROUTE_CACHE_NODE RCN;
PNEIGHBOR_CACHE_ENTRY NCE;
TI_DbgPrint(MID_TRACE, ("Called. IF (0x%X).\n", IF));
@ -261,12 +263,6 @@ BOOLEAN IPRegisterInterface(
TI_DbgPrint(MIN_TRACE, ("Could not add route due to insufficient resources.\n"));
}
RCN = RouteAddRouteToDestination(&NetworkAddress, IF, NCE);
if (!RCN) {
TI_DbgPrint(MIN_TRACE, ("Could not create RCN.\n"));
TcpipReleaseSpinLock(&IF->Lock, OldIrql);
}
/* Add interface to the global interface list */
ASSERT(&IF->ListEntry);
TcpipInterlockedInsertTailList(&InterfaceListHead,
@ -301,8 +297,6 @@ VOID IPUnregisterInterface(
NBRemoveNeighbor(NCE);
TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql3);
/* Ouch...three spinlocks acquired! Fortunately
we don't unregister interfaces very often */
RemoveEntryList(&IF->ListEntry);
TcpipReleaseSpinLock(&InterfaceListLock, OldIrql3);
}
@ -400,9 +394,6 @@ NTSTATUS IPStartup(PUNICODE_STRING RegistryPath)
/* Start routing subsystem */
RouterStartup();
/* Start route cache subsystem */
RouteStartup();
/* Start neighbor cache subsystem */
NBStartup();
@ -444,9 +435,6 @@ NTSTATUS IPShutdown(
/* Shutdown neighbor cache subsystem */
NBShutdown();
/* Shutdown route cache subsystem */
RouteShutdown();
/* Shutdown routing subsystem */
RouterShutdown();

View file

@ -107,11 +107,6 @@ VOID NCETimeout(
/* Flush packet queue */
NBFlushPacketQueue( NCE, TRUE, NDIS_STATUS_REQUEST_ABORTED );
NCE->EventCount = 0;
/* Remove route cache entries with references to this NCE.
Remember that neighbor cache lock is acquired before the
route cache lock */
RouteInvalidateNCE(NCE);
}
else
{
@ -205,9 +200,6 @@ VOID NBShutdown(VOID)
while (CurNCE) {
NextNCE = CurNCE->Next;
/* Remove all references from route cache */
RouteInvalidateNCE(CurNCE);
/* Flush wait queue */
NBFlushPacketQueue( CurNCE, FALSE, STATUS_SUCCESS );
@ -501,9 +493,6 @@ VOID NBRemoveNeighbor(
*PrevNCE = CurNCE->Next;
NBFlushPacketQueue( CurNCE, TRUE, NDIS_STATUS_REQUEST_ABORTED );
/* Remove all references from route cache */
RouteInvalidateNCE(CurNCE);
ExFreePool(CurNCE);
break;

View file

@ -1,610 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: network/route.c
* PURPOSE: Route cache
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* NOTES: The route cache is implemented as a binary search
* tree to obtain fast searches
*
* This data is not authoritative. It is a searchable cache that allows
* quick access to route information to selected hosts. This information
* should always defer to the FIB.
*
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include "precomp.h"
/* This RCN is shared by all external nodes. It complicates things,
but the memory requirements are reduced by approximately 50%.
The RCN is protected by the route cache spin lock */
PROUTE_CACHE_NODE ExternalRCN;
PROUTE_CACHE_NODE RouteCache;
KSPIN_LOCK RouteCacheLock;
NPAGED_LOOKASIDE_LIST IPRCNList;
#ifdef DBG
VOID PrintTree(
PROUTE_CACHE_NODE Node)
/*
* FUNCTION: Prints all nodes on tree
* ARGUMENTS:
* Node = Pointer to root node of tree
* NOTES:
* This function must be called with the route cache lock held.
*/
{
if (IsInternalRCN(Node)) {
/* Traverse left subtree */
PrintTree(Node->Left);
/* Traverse right subtree */
PrintTree(Node->Right);
/* Finally check the node itself */
TI_DbgPrint(MIN_TRACE, ("(Internal) Self,Parent,Left,Right,Data = (%08X, %08X, %08X, %08X, %08X).\n",
Node, Node->Parent, Node->Left, Node->Right, (ULONG_PTR)Node->Destination.Address.IPv4Address));
} else
TI_DbgPrint(MIN_TRACE, ("(External) Self,Parent,Left,Right = (%08X, %08X, %08X, %08X).\n",
Node, Node->Parent, Node->Left, Node->Right));
}
#endif
UINT CountRouteNodes( PROUTE_CACHE_NODE Node ) {
if( !Node ) Node = RouteCache;
if( IsInternalRCN(Node) )
return
/* Traverse left subtree */
CountRouteNodes(Node->Left) +
/* Traverse right subtree */
CountRouteNodes(Node->Right) + 1;
else
return 0;
}
VOID FreeRCN(
PVOID Object)
/*
* FUNCTION: Frees an route cache node object
* ARGUMENTS:
* Object = Pointer to an route cache node structure
*/
{
ExFreeToNPagedLookasideList(&IPRCNList, Object);
}
VOID RemoveAboveExternal(VOID)
/*
* FUNCTION: Removes the parent node of the selected external node from the route cache tree
* NOTES:
* This function must be called with the route cache lock held.
* ExternalRCN->Parent must be initialized
*/
{
PROUTE_CACHE_NODE Parent;
PROUTE_CACHE_NODE Sibling;
TI_DbgPrint(DEBUG_RCACHE, ("Called.\n"));
#if 0
TI_DbgPrint(MIN_TRACE, ("Displaying tree (before).\n"));
PrintTree(RouteCache);
#endif
Parent = ExternalRCN->Parent;
/* Find sibling of external node */
if (ExternalRCN == Parent->Left)
Sibling = Parent->Right;
else
Sibling = Parent->Left;
/* Replace parent node with sibling of external node */
if (Parent != RouteCache) {
if (Parent->Parent->Left == Parent)
Parent->Parent->Left = Sibling;
else
Parent->Parent->Right = Sibling;
/* Give sibling a new parent */
Sibling->Parent = Parent->Parent;
} else {
/* This is the root we're removing */
RouteCache = Sibling;
Sibling->Parent = NULL;
}
}
PROUTE_CACHE_NODE SearchRouteCache(
PIP_ADDRESS Destination,
PROUTE_CACHE_NODE Node)
/*
* FUNCTION: Searches route cache for a RCN for a destination address
* ARGUMENTS:
* Destination = Pointer to destination address (key)
* Node = Pointer to start route cache node
* NOTES:
* This function must be called with the route cache lock held
* RETURNS:
* Pointer to internal node if a matching node was found, or
* external node where it should be if none was found
*/
{
INT Value;
TI_DbgPrint(DEBUG_RCACHE, ("Called. Destination (0x%X) Node (0x%X)\n", Destination, Node));
/* Is this an external node? */
if (IsExternalRCN(Node))
return Node;
/* Is it this node we are looking for? */
Value = AddrCompare(Destination, &Node->Destination);
if (Value == 0)
return Node;
/* Traverse down the left subtree if the key is smaller than
the key of the node, otherwise traverse the right subtree */
if (Value < 0) {
Node->Left->Parent = Node;
ExternalRCN->Left = (PROUTE_CACHE_NODE)&Node->Left;
return SearchRouteCache(Destination, Node->Left);
} else {
Node->Right->Parent = Node;
ExternalRCN->Left = (PROUTE_CACHE_NODE)&Node->Right;
return SearchRouteCache(Destination, Node->Right);
}
}
PROUTE_CACHE_NODE ExpandExternalRCN(VOID)
/*
* FUNCTION: Expands an external route cache node
* NOTES:
* This function must be called with the route cache lock held.
* We cheat a little here to save memory. We don't actually allocate memory
* for external nodes. We wait until they're turned into internal nodes.
* ExternalRCN->Parent must be initialized
* ExternalRCN->Left must be a pointer to the correct child link of it's parent
* RETURNS:
* Pointer to new internal node if the external node was expanded, NULL if not
*/
{
PROUTE_CACHE_NODE RCN;
MTMARK();
TI_DbgPrint(DEBUG_RCACHE, ("Called.\n"));
RCN = ExAllocateFromNPagedLookasideList(&IPRCNList);
if (!RCN) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return NULL;
}
MTMARK();
RCN->Free = FreeRCN;
if (ExternalRCN->Left)
/* Register RCN as a child with it's parent */
*(PROUTE_CACHE_NODE*)ExternalRCN->Left = RCN;
RCN->Parent = ExternalRCN->Parent;
RCN->Left = ExternalRCN;
RCN->Right = ExternalRCN;
MTMARK();
return RCN;
}
#if 0
VOID SwapRCN(
PROUTE_CACHE_NODE *Node1,
PROUTE_CACHE_NODE *Node2)
/*
* FUNCTION: Swaps two nodes
* ARGUMENTS:
* Node1 = Address of pointer to first node
* Node2 = Address of pointer to second node
*/
{
PROUTE_CACHE_NODE Temp;
Temp = *Node2;
*Node2 = *Node1;
*Node1 = Temp;
}
#endif
/*
* FUNCTION: Removes a route to a destination
* ARGUMENTS:
* RCN = Pointer to route cache node to remove
* NOTES:
* Internal version. Route cache lock must be held
*/
VOID RemoveRouteToDestination(
PROUTE_CACHE_NODE RCN)
{
PROUTE_CACHE_NODE RemNode, Parent, SwapNode;
TI_DbgPrint(DEBUG_RCACHE, ("Called. RCN (0x%X).\n", RCN));
if (IsExternalRCN(RCN->Left)) {
/* Left node is external */
RemNode = RCN->Left;
RemNode->Parent = RCN;
} else if (IsExternalRCN(RCN->Right)) {
/* Right node is external */
RemNode = RCN->Right;
RemNode->Parent = RCN;
} else {
/* The node has internal children */
/* Normally we would replace the item of RCN with the item
of the leftmost external node on the right subtree of
RCN. This we cannot do here because there may be
references directly to that node. Instead we swap pointer
values (parent, left and right) of the two nodes */
RemNode = RCN->Right;
do {
Parent = RemNode;
RemNode = RemNode->Left;
} while (IsInternalRCN(RemNode));
RemNode->Parent = Parent;
SwapNode = RemNode->Parent;
#if 0
if (RCN != RouteCache) {
/* Set SwapNode to be child of RCN's parent instead of RCN */
Parent = RCN->Parent;
if (RCN == Parent->Left)
Parent->Left = SwapNode;
else
Parent->Right = SwapNode;
} else
/* SwapNode is the new cache root */
RouteCache = SwapNode;
/* Set RCN to be child of SwapNode's parent instead of SwapNode */
Parent = SwapNode->Parent;
if (SwapNode == Parent->Left)
Parent->Left = RCN;
else
Parent->Right = RCN;
/* Swap parents */
SwapRCN(&SwapNode->Parent, &RCN->Parent);
/* Swap children */
SwapRCN(&SwapNode->Left, &RCN->Left);
SwapRCN(&SwapNode->Right, &RCN->Right);
#endif
}
ExternalRCN->Parent = RemNode->Parent;
RemoveAboveExternal();
}
VOID InvalidateNCEOnSubtree(
PNEIGHBOR_CACHE_ENTRY NCE,
PROUTE_CACHE_NODE Node)
/*
* FUNCTION: Removes all RCNs with references to an NCE on a subtree
* ARGUMENNTS:
* NCE = Pointer to NCE to invalidate
* Node = Pointer to RCN to start removing nodes at
* NOTES:
* This function must be called with the route cache lock held
*/
{
TI_DbgPrint(DEBUG_RCACHE, ("Called. NCE (0x%X) Node (0x%X).\n", NCE, Node));
if (IsInternalRCN(Node)) {
/* Traverse left subtree */
InvalidateNCEOnSubtree(NCE, Node->Left);
/* Traverse right subtree */
InvalidateNCEOnSubtree(NCE, Node->Right);
/* Finally check the node itself */
if (Node->NCE == NCE)
RemoveRouteToDestination(Node);
}
}
VOID RemoveSubtree(
PROUTE_CACHE_NODE Node)
/*
* FUNCTION: Removes a subtree from the tree using recursion
* ARGUMENNTS:
* Node = Pointer to RCN to start removing nodes at
* NOTES:
* This function must be called with the route cache lock held
*/
{
TI_DbgPrint(DEBUG_RCACHE, ("Called. Node (0x%X).\n", Node));
if (IsInternalRCN(Node)) {
/* Traverse left subtree */
RemoveSubtree(Node->Left);
/* Traverse right subtree */
RemoveSubtree(Node->Right);
}
}
NTSTATUS RouteStartup(
VOID)
/*
* FUNCTION: Initializes the routing subsystem
* RETURNS:
* Status of operation
*/
{
TI_DbgPrint(DEBUG_RCACHE, ("Called.\n"));
ExInitializeNPagedLookasideList(
&IPRCNList, /* Lookaside list */
NULL, /* Allocate routine */
NULL, /* Free routine */
0, /* Flags */
sizeof(ROUTE_CACHE_NODE), /* Size of each entry */
TAG('I','P','R','C'), /* Tag */
0); /* Depth */
/* Initialize the pseudo external route cache node */
ExternalRCN = ExAllocateFromNPagedLookasideList(&IPRCNList);
if (!ExternalRCN) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
INIT_TAG(ExternalRCN, TAG('R','C','N',' '));
ExternalRCN->Free = FreeRCN;
ExternalRCN->Parent = NULL;
ExternalRCN->Left = NULL;
ExternalRCN->Right = NULL;
/* Initialize the route cache root */
RouteCache = ExternalRCN;
KeInitializeSpinLock(&RouteCacheLock);
#if 0
TI_DbgPrint(MIN_TRACE, ("Displaying tree.\n"));
PrintTree(RouteCache);
#endif
return STATUS_SUCCESS;
}
NTSTATUS RouteShutdown(
VOID)
/*
* FUNCTION: Shuts down the routing subsystem
* RETURNS:
* Status of operation
*/
{
KIRQL OldIrql;
TI_DbgPrint(DEBUG_RCACHE, ("Called.\n"));
TcpipAcquireSpinLock(&RouteCacheLock, &OldIrql);
#if 0
TI_DbgPrint(MIN_TRACE, ("Displaying tree.\n"));
PrintTree(RouteCache);
#endif
/* Clear route cache */
RemoveSubtree(RouteCache);
FreeRCN(ExternalRCN);
TcpipReleaseSpinLock(&RouteCacheLock, OldIrql);
ExDeleteNPagedLookasideList(&IPRCNList);
return STATUS_SUCCESS;
}
UINT RouteGetRouteToDestination
(PIP_ADDRESS Destination, PROUTE_CACHE_NODE *RCN)
/*
* 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
*/
{
KIRQL OldIrql;
PROUTE_CACHE_NODE RCN2;
PNEIGHBOR_CACHE_ENTRY NCE;
PIP_INTERFACE Interface;
TI_DbgPrint(DEBUG_RCACHE, ("Called. Destination (0x%X)\n", Destination));
TI_DbgPrint(DEBUG_RCACHE, ("Destination (%s)\n", A2S(Destination)));
TcpipAcquireSpinLock(&RouteCacheLock, &OldIrql);
#if 0
TI_DbgPrint(MIN_TRACE, ("Displaying tree (before).\n"));
PrintTree(RouteCache);
#endif
ExternalRCN->Left = NULL;
RCN2 = SearchRouteCache(Destination, RouteCache);
if (IsExternalRCN(RCN2)) {
/* No route was found in the cache */
/* 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);
if (!NCE) {
TcpipReleaseSpinLock(&RouteCacheLock, OldIrql);
return IP_NO_RESOURCES;
}
} else {
/* Destination is not on any subnets we're on. Find a router to use */
NCE = RouterGetRoute(Destination);
if (!NCE) {
/* We cannot get to the specified destination. Return error */
TcpipReleaseSpinLock(&RouteCacheLock, OldIrql);
return IP_NO_ROUTE_TO_DESTINATION;
}
}
/* Add the new route to the route cache */
if (RCN2 == RouteCache) {
RCN2 = ExpandExternalRCN();
RouteCache = RCN2;
} else
RCN2 = ExpandExternalRCN();
if (!RCN2) {
TcpipReleaseSpinLock(&RouteCacheLock, OldIrql);
return IP_NO_RESOURCES;
}
RCN2->State = RCN_STATE_COMPUTED;
RtlCopyMemory(&RCN2->Destination, Destination, sizeof(IP_ADDRESS));
RCN2->PathMTU = NCE->Interface->MTU;
RCN2->NCE = NCE;
/* The route cache node references the NTE and the NCE. The
NTE was referenced before and NCE is already referenced by
RouteGetRoute() or NBFindOrCreateNeighbor() so we don't
reference them here */
}
TcpipReleaseSpinLock(&RouteCacheLock, OldIrql);
*RCN = RCN2;
TI_DbgPrint(MID_TRACE,("RCN->PathMTU: %d\n", RCN2->PathMTU));
return IP_SUCCESS;
}
PROUTE_CACHE_NODE RouteAddRouteToDestination(
PIP_ADDRESS Destination,
PIP_INTERFACE IF,
PNEIGHBOR_CACHE_ENTRY NCE)
/*
* FUNCTION: Adds a (permanent) route to a destination
* ARGUMENTS:
* Destination = Pointer to destination address
* IF = Pointer to interface to use
* NCE = Pointer to first hop to destination
* RETURNS:
* Pointer to RCN if the route was added, NULL if not.
* There can be at most one RCN per destination address / interface pair
*/
{
KIRQL OldIrql;
PROUTE_CACHE_NODE RCN;
TI_DbgPrint(DEBUG_RCACHE, ("Called. Destination (0x%X) IF (0x%X) NCE (0x%X).\n",
Destination, IF, NCE));
TI_DbgPrint(DEBUG_RCACHE, ("Destination (%s) NCE (%s).\n",
A2S(Destination),
A2S(&NCE->Address)));
TcpipAcquireSpinLock(&RouteCacheLock, &OldIrql);
/* Locate an external RCN we can expand */
RCN = RouteCache;
ExternalRCN->Left = NULL;
for (;;) {
RCN = SearchRouteCache(Destination, RCN);
if (IsInternalRCN(RCN)) {
ExternalRCN->Left = (PROUTE_CACHE_NODE)&RCN->Right;
/* This is an internal node, continue the search to the right */
RCN = RCN->Right;
} else
/* This is an external node, we've found an empty spot */
break;
}
/* Expand the external node */
if (RCN == RouteCache) {
RCN = ExpandExternalRCN();
RouteCache = RCN;
} else
RCN = ExpandExternalRCN();
if (!RCN) {
TcpipReleaseSpinLock(&RouteCacheLock, OldIrql);
return NULL;
}
/* Initialize the newly created internal node */
INIT_TAG(RCN, TAG('R','C','N',' '));
/* Reference once for beeing alive */
RCN->State = RCN_STATE_PERMANENT;
RtlCopyMemory(&RCN->Destination, Destination, sizeof(IP_ADDRESS));
RCN->PathMTU = IF->MTU;
RCN->NCE = NCE;
TcpipReleaseSpinLock(&RouteCacheLock, OldIrql);
return RCN;
}
VOID RouteRemoveRouteToDestination(
PROUTE_CACHE_NODE RCN)
/*
* FUNCTION: Removes a route to a destination
* ARGUMENTS:
* RCN = Pointer to route cache node to remove
*/
{
KIRQL OldIrql;
TI_DbgPrint(DEBUG_RCACHE, ("Called. RCN (0x%X).\n", RCN));
TcpipAcquireSpinLock(&RouteCacheLock, &OldIrql);
RemoveRouteToDestination(RCN);
TcpipReleaseSpinLock(&RouteCacheLock, OldIrql);
}
VOID RouteInvalidateNCE(
PNEIGHBOR_CACHE_ENTRY NCE)
/*
* FUNCTION: Removes all RCNs with references to an NCE
* ARGUMENTS:
* NCE = Pointer to neighbor cache entry to invalidate
*/
{
KIRQL OldIrql;
TI_DbgPrint(DEBUG_RCACHE, ("Called. NCE (0x%X).\n", NCE));
TcpipAcquireSpinLock(&RouteCacheLock, &OldIrql);
InvalidateNCEOnSubtree(NCE, RouteCache);
TcpipReleaseSpinLock(&RouteCacheLock, OldIrql);
}
/* EOF */

View file

@ -272,6 +272,46 @@ PNEIGHBOR_CACHE_ENTRY RouterGetRoute(PIP_ADDRESS Destination)
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);
} else {
/* Destination is not on any subnets we're on. Find a router to use */
NCE = RouterGetRoute(Destination);
}
if( NCE )
TI_DbgPrint(MID_TRACE,("Interface->MTU: %d\n", NCE->Interface->MTU));
return NCE;
}
NTSTATUS RouterRemoveRoute(PIP_ADDRESS Target, PIP_ADDRESS Router)
/*

View file

@ -212,7 +212,7 @@ NTSTATUS SendFragments(
return STATUS_SUCCESS;
}
NTSTATUS IPSendDatagram(PIP_PACKET IPPacket, PROUTE_CACHE_NODE RCN,
NTSTATUS IPSendDatagram(PIP_PACKET IPPacket, PNEIGHBOR_CACHE_ENTRY NCE,
PIP_TRANSMIT_COMPLETE Complete, PVOID Context)
/*
* FUNCTION: Sends an IP datagram to a remote address
@ -227,17 +227,13 @@ NTSTATUS IPSendDatagram(PIP_PACKET IPPacket, PROUTE_CACHE_NODE RCN,
* send routine (IPSendFragment)
*/
{
PNEIGHBOR_CACHE_ENTRY NCE;
TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X) RCN (0x%X)\n", IPPacket, RCN));
TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X) NCE (0x%X)\n", IPPacket, NCE));
DISPLAY_IP_PACKET(IPPacket);
/*OskitDumpBuffer( IPPacket->Header, IPPacket->TotalSize );*/
NCE = RCN->NCE;
/* Fetch path MTU now, because it may change */
TI_DbgPrint(MID_TRACE,("PathMTU: %d\n", RCN->PathMTU));
TI_DbgPrint(MID_TRACE,("PathMTU: %d\n", NCE->Interface->MTU));
if ((IPPacket->Flags & IP_PACKET_FLAG_RAW) == 0) {
/* Calculate checksum of IP header */
@ -255,7 +251,8 @@ NTSTATUS IPSendDatagram(PIP_PACKET IPPacket, PROUTE_CACHE_NODE RCN,
IPPacket->Flags));
}
return SendFragments(IPPacket, NCE, RCN->PathMTU, Complete, Context);
return SendFragments(IPPacket, NCE, NCE->Interface->MTU,
Complete, Context);
}
/* EOF */

View file

@ -98,7 +98,7 @@ NTSTATUS RawIPSendDatagram(
{
NDIS_STATUS Status;
IP_PACKET Packet;
PROUTE_CACHE_NODE RCN;
PNEIGHBOR_CACHE_ENTRY NCE;
IP_ADDRESS RemoteAddress;
Status = AllocatePacketWithBuffer( &Packet.NdisPacket,
@ -121,14 +121,12 @@ NTSTATUS RawIPSendDatagram(
BufferData + FIELD_OFFSET(IPv4_HEADER, DstAddr),
sizeof(IPv4_RAW_ADDRESS) );
Status = RouteGetRouteToDestination( &RemoteAddress, &RCN );
if( !NT_SUCCESS(Status) ) {
if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) {
FreeNdisPacket( Packet.NdisPacket );
return Status;
return STATUS_NO_SUCH_DEVICE;
}
IPSendDatagram( &Packet, RCN, RawIPSendComplete, NULL );
IPSendDatagram( &Packet, NCE, RawIPSendComplete, NULL );
} else
FreeNdisPacket( Packet.NdisPacket );

View file

@ -156,9 +156,8 @@ void TCPPacketSendComplete( PVOID Context,
#define STRINGIFY(x) #x
int TCPPacketSend(void *ClientData, OSK_PCHAR data, OSK_UINT len ) {
NTSTATUS Status;
NDIS_STATUS NdisStatus;
ROUTE_CACHE_NODE *RCN;
PNEIGHBOR_CACHE_ENTRY NCE;
IP_PACKET Packet = { 0 };
IP_ADDRESS RemoteAddress, LocalAddress;
PIPv4_HEADER Header;
@ -180,9 +179,8 @@ int TCPPacketSend(void *ClientData, OSK_PCHAR data, OSK_UINT len ) {
LocalAddress.Address.IPv4Address,
RemoteAddress.Address.IPv4Address);
Status = RouteGetRouteToDestination( &RemoteAddress, &RCN );
if( !NT_SUCCESS(Status) || !RCN ) return OSK_EADDRNOTAVAIL;
if(!(NCE = RouteGetRouteToDestination( &RemoteAddress )))
return OSK_EADDRNOTAVAIL;
NdisStatus = AllocatePacketWithBuffer( &Packet.NdisPacket, NULL,
MaxLLHeaderSize + len );
@ -202,7 +200,7 @@ int TCPPacketSend(void *ClientData, OSK_PCHAR data, OSK_UINT len ) {
Packet.SrcAddr = LocalAddress;
Packet.DstAddr = RemoteAddress;
IPSendDatagram( &Packet, RCN, TCPPacketSendComplete, NULL );
IPSendDatagram( &Packet, NCE, TCPPacketSendComplete, NULL );
if( !NT_SUCCESS(NdisStatus) ) return OSK_EINVAL;
else return 0;

View file

@ -36,9 +36,6 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
/* Save client context pointer */
Connection->ClientContext = ClientContext;
/* Initialize received segments queue */
InitializeListHead(&Connection->ReceivedSegments);
return Connection;
}
@ -244,7 +241,7 @@ NTSTATUS TCPConnect
PVOID Context ) {
NTSTATUS Status;
SOCKADDR_IN AddressToConnect = { 0 }, AddressToBind = { 0 };
PIP_ADDRESS RemoteAddress;
IP_ADDRESS RemoteAddress;
USHORT RemotePort;
PTDI_BUCKET Bucket;
@ -267,7 +264,7 @@ NTSTATUS TCPConnect
&RemotePort);
DbgPrint("Connecting to address %x:%x\n",
RemoteAddress->Address.IPv4Address,
RemoteAddress.Address.IPv4Address,
RemotePort);
if (!NT_SUCCESS(Status)) {
@ -284,7 +281,7 @@ NTSTATUS TCPConnect
sizeof(AddressToBind) );
memcpy( &AddressToConnect.sin_addr,
&RemoteAddress->Address.IPv4Address,
&RemoteAddress.Address.IPv4Address,
sizeof(AddressToConnect.sin_addr) );
AddressToConnect.sin_port = RemotePort;

View file

@ -197,7 +197,7 @@ NTSTATUS UDPSendDatagram(
IP_ADDRESS RemoteAddress;
USHORT RemotePort;
NTSTATUS Status;
PROUTE_CACHE_NODE RCN;
PNEIGHBOR_CACHE_ENTRY NCE;
TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
AddrFile, ConnInfo, BufferData, DataSize));
@ -226,12 +226,10 @@ NTSTATUS UDPSendDatagram(
if( !NT_SUCCESS(Status) )
return Status;
Status = RouteGetRouteToDestination( &RemoteAddress, &RCN );
if(!(NCE = RouteGetRouteToDestination( &RemoteAddress )))
return STATUS_UNSUCCESSFUL;
if( !NT_SUCCESS(Status) )
return Status;
IPSendDatagram( &Packet, RCN, UDPSendPacketComplete, NULL );
IPSendDatagram( &Packet, NCE, UDPSendPacketComplete, NULL );
return STATUS_SUCCESS;
}

View file

@ -734,6 +734,7 @@ VOID BindAdapter(
PIP_INTERFACE IF;
NDIS_STATUS NdisStatus;
LLIP_BIND_INFO BindInfo;
IP_ADDRESS DefaultGateway, DefaultMask = { 0 };
ULONG Lookahead = LOOKAHEAD_SIZE;
NTSTATUS Status;
HANDLE RegHandle = 0;
@ -779,6 +780,14 @@ VOID BindAdapter(
Status = OpenRegistryKey( RegistryPath, &RegHandle );
if(NT_SUCCESS(Status))
Status = ReadIPAddressFromRegistry( RegHandle, L"DefaultGateway",
&DefaultGateway );
if(!NT_SUCCESS(Status)) {
Status = STATUS_SUCCESS;
RtlZeroMemory( &DefaultGateway, sizeof(DefaultGateway) );
}
if(NT_SUCCESS(Status))
Status = ReadIPAddressFromRegistry( RegHandle, L"IPAddress",
&IF->Unicast );
@ -820,6 +829,20 @@ VOID BindAdapter(
("--> Our net mask on this interface: '%s'\n",
A2S(&IF->Netmask)));
if( DefaultGateway.Address.IPv4Address ) {
TI_DbgPrint
(MID_TRACE,
("--> Our gateway is: '%s'\n",
A2S(&DefaultGateway)));
/* Create a default route */
RouterCreateRoute( &DefaultMask, /* Zero */
&DefaultMask, /* Zero */
&DefaultGateway,
IF,
1 );
}
/* Register interface with IP layer */
IPRegisterInterface(IF);

View file

@ -40,7 +40,7 @@ NTSTATUS AddrGetAddress(
NTSTATUS AddrBuildAddress(
PTRANSPORT_ADDRESS TdiAddress,
PIP_ADDRESS *Address,
PIP_ADDRESS Address,
PUSHORT Port);
BOOLEAN AddrIsEqual(

View file

@ -3,6 +3,8 @@
#include <ip.h>
#define IFENT_SOFTWARE_LOOPBACK 24 /* This is an SNMP constant from rfc1213 */
NTSTATUS GetInterfaceIPv4Address( PIP_INTERFACE Interface,
ULONG Type,
PULONG Address );

View file

@ -188,6 +188,7 @@ extern LIST_ENTRY NetTableListHead;
extern KSPIN_LOCK NetTableListLock;
extern UINT MaxLLHeaderSize;
extern UINT MinLLFrameSize;
extern BOOLEAN IpWorkItemQueued;
PIP_PACKET IPCreatePacket(
ULONG Type);

View file

@ -14,61 +14,7 @@
#include <info.h>
#include <arp.h>
/* Route Cache Node structure.
* The primary purpose of the RCN is to cache selected source and
* next-hop addresses. The routing cache is implemented as a binary
* search tree to provide fast lookups when many RCNs are in the cache.
*/
typedef struct ROUTE_CACHE_NODE {
struct ROUTE_CACHE_NODE *Parent; /* Pointer to parent */
struct ROUTE_CACHE_NODE *Left; /* Pointer to left child */
struct ROUTE_CACHE_NODE *Right; /* Pointer to right child */
/* Memebers above this line must not be moved */
DEFINE_TAG
OBJECT_FREE_ROUTINE Free; /* Routine used to free resources for the object */
UCHAR State; /* RCN state (RCN_STATE_*) */
IP_ADDRESS Destination; /* Destination address */
PNEIGHBOR_CACHE_ENTRY NCE; /* Pointer to NCE for first hop (NULL if none) */
UINT PathMTU; /* Path MTU to destination */
} ROUTE_CACHE_NODE, *PROUTE_CACHE_NODE;
/* RCN states */
#define RCN_STATE_PERMANENT 0x00 /* RCN is permanent (properly local) */
#define RCN_STATE_COMPUTED 0x01 /* RCN is computed */
extern NPAGED_LOOKASIDE_LIST IPRCNList;
#define IsExternalRCN(RCN) \
(RCN == ExternalRCN)
#define IsInternalRCN(RCN) \
(RCN != ExternalRCN)
NTSTATUS RouteStartup(
VOID);
NTSTATUS RouteShutdown(
VOID);
UINT RouteGetRouteToDestination(
PIP_ADDRESS Destination,
PROUTE_CACHE_NODE *RCN);
PROUTE_CACHE_NODE RouteAddRouteToDestination(
PIP_ADDRESS Destination,
PIP_INTERFACE IF,
PNEIGHBOR_CACHE_ENTRY NCE);
VOID RouteRemoveRouteToDestination( PROUTE_CACHE_NODE RCN );
VOID RouteInvalidateNCE( PNEIGHBOR_CACHE_ENTRY NCE );
NTSTATUS RouteFriendlyAddRoute( PIPROUTE_ENTRY ire );
UINT CountRouteNodes( PROUTE_CACHE_NODE Node );
PNEIGHBOR_CACHE_ENTRY RouteGetRouteToDestination(PIP_ADDRESS Destination);
#endif /* __ROUTE_H */

View file

@ -321,9 +321,6 @@ typedef struct _CONNECTION_ENDPOINT {
LIST_ENTRY ConnectRequest; /* Queued connect rqueusts */
LIST_ENTRY ListenRequest; /* Queued listen requests */
LIST_ENTRY ReceiveRequest; /* Queued receive requests */
/* Queues */
LIST_ENTRY ReceivedSegments;/* Segments that are received */
} CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT;

View file

@ -30,7 +30,7 @@ typedef struct IPFRAGMENT_CONTEXT {
} IPFRAGMENT_CONTEXT, *PIPFRAGMENT_CONTEXT;
NTSTATUS IPSendDatagram(PIP_PACKET IPPacket, PROUTE_CACHE_NODE RCN,
NTSTATUS IPSendDatagram(PIP_PACKET IPPacket, PNEIGHBOR_CACHE_ENTRY NCE,
PIP_TRANSMIT_COMPLETE Complete, PVOID Context);
#endif /* __TRANSMIT_H */

View file

@ -380,14 +380,6 @@ NTSTATUS FileOpenConnection(
Status = TCPSocket( Connection, AF_INET, SOCK_STREAM, IPPROTO_TCP );
DbgPrint("STATUS from OSKITTCP was %08x\n", Status);
/* Initialize received segments queue */
InitializeListHead(&Connection->ReceivedSegments);
TI_DbgPrint(MIN_TRACE, ("X1 cur 0x%x\n", &Connection->ReceivedSegments));
TI_DbgPrint(MIN_TRACE, ("X1 Flink 0x%x\n", Connection->ReceivedSegments.Flink));
TI_DbgPrint(MIN_TRACE, ("X1 Blink 0x%x\n", Connection->ReceivedSegments.Blink));
/* Return connection endpoint file object */
Request->Handle.ConnectionContext = Connection;
@ -417,7 +409,7 @@ PCONNECTION_ENDPOINT FileFindConnectionByContext( PVOID Context ) {
KIRQL OldIrql;
PCONNECTION_ENDPOINT Connection = NULL;
KeAcquireSpinLock( &ConnectionEndpointListLock, &OldIrql );
TcpipAcquireSpinLock( &ConnectionEndpointListLock, &OldIrql );
for( Entry = ConnectionEndpointListHead.Flink;
Entry != &ConnectionEndpointListHead;
@ -428,7 +420,7 @@ PCONNECTION_ENDPOINT FileFindConnectionByContext( PVOID Context ) {
else Connection = NULL;
}
KeReleaseSpinLock( &ConnectionEndpointListLock, OldIrql );
TcpipReleaseSpinLock( &ConnectionEndpointListLock, OldIrql );
return Connection;
}

View file

@ -35,7 +35,7 @@ TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIEntityID *ID,
OutData->Index = ID->tei_instance + 1;
/* viz: tcpip keeps those indices */
OutData->Type = IF ? 1 : 0; /* XXX other -- for now ... */
OutData->Type = Interface == Loopback ? IFENT_SOFTWARE_LOOPBACK : 0;
OutData->Mtu = Interface->MTU;
TI_DbgPrint(MAX_TRACE,
("Getting interface speed\n"));

View file

@ -29,6 +29,7 @@ ULONG EntityCount = 0;
ULONG EntityMax = 0;
UDP_STATISTICS UDPStats;
/* Network timers */
KTIMER IPTimer;
KDPC IPTimeoutDpc;
KSPIN_LOCK IpWorkLock;
@ -256,6 +257,7 @@ CP
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
Irp->IoStatus.Status = Status;
return Status;
}
@ -670,7 +672,10 @@ VOID STDCALL IPTimeoutDpcFn(
* This routine is dispatched once in a while to do maintainance jobs
*/
{
if( !IpWorkItemQueued ) {
ExQueueWorkItem( &IpWorkItem, CriticalWorkQueue );
IpWorkItemQueued = TRUE;
}
}
NTSTATUS