mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 19:21:38 +00:00
Create a branch for network fixes.
svn path=/branches/aicom-network-fixes/; revision=34994
This commit is contained in:
parent
0e213bbc00
commit
c501d8112c
18148 changed files with 0 additions and 860488 deletions
489
lib/drivers/ip/network/ip.c
Normal file
489
lib/drivers/ip/network/ip.c
Normal file
|
@ -0,0 +1,489 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS TCP/IP protocol driver
|
||||
* FILE: network/ip.c
|
||||
* PURPOSE: Internet Protocol module
|
||||
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||
* REVISIONS:
|
||||
* CSH 01/08-2000 Created
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
|
||||
LIST_ENTRY InterfaceListHead;
|
||||
KSPIN_LOCK InterfaceListLock;
|
||||
LIST_ENTRY NetTableListHead;
|
||||
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 */
|
||||
|
||||
IP_PROTOCOL_HANDLER ProtocolTable[IP_PROTOCOL_TABLE_SIZE];
|
||||
|
||||
|
||||
VOID FreePacket(
|
||||
PVOID Object)
|
||||
/*
|
||||
* FUNCTION: Frees an IP packet object
|
||||
* ARGUMENTS:
|
||||
* Object = Pointer to an IP packet structure
|
||||
*/
|
||||
{
|
||||
TcpipFreeToNPagedLookasideList(&IPPacketList, Object);
|
||||
}
|
||||
|
||||
|
||||
VOID DontFreePacket(
|
||||
PVOID Object)
|
||||
/*
|
||||
* FUNCTION: Do nothing for when the IPPacket struct is part of another
|
||||
* ARGUMENTS:
|
||||
* Object = Pointer to an IP packet structure
|
||||
*/
|
||||
{
|
||||
}
|
||||
|
||||
VOID FreeIF(
|
||||
PVOID Object)
|
||||
/*
|
||||
* FUNCTION: Frees an interface object
|
||||
* ARGUMENTS:
|
||||
* Object = Pointer to an interface structure
|
||||
*/
|
||||
{
|
||||
exFreePool(Object);
|
||||
}
|
||||
|
||||
|
||||
PIP_PACKET IPCreatePacket(ULONG Type)
|
||||
/*
|
||||
* FUNCTION: Creates an IP packet object
|
||||
* ARGUMENTS:
|
||||
* Type = Type of IP packet
|
||||
* RETURNS:
|
||||
* Pointer to the created IP packet. NULL if there was not enough free resources.
|
||||
*/
|
||||
{
|
||||
PIP_PACKET IPPacket;
|
||||
|
||||
IPPacket = TcpipAllocateFromNPagedLookasideList(&IPPacketList);
|
||||
if (!IPPacket)
|
||||
return NULL;
|
||||
|
||||
/* FIXME: Is this needed? */
|
||||
RtlZeroMemory(IPPacket, sizeof(IP_PACKET));
|
||||
|
||||
INIT_TAG(IPPacket, TAG('I','P','K','T'));
|
||||
|
||||
IPPacket->Free = FreePacket;
|
||||
IPPacket->Type = Type;
|
||||
IPPacket->HeaderSize = 20;
|
||||
|
||||
return IPPacket;
|
||||
}
|
||||
|
||||
PIP_PACKET IPInitializePacket(
|
||||
PIP_PACKET IPPacket,
|
||||
ULONG Type)
|
||||
/*
|
||||
* FUNCTION: Creates an IP packet object
|
||||
* ARGUMENTS:
|
||||
* Type = Type of IP packet
|
||||
* RETURNS:
|
||||
* Pointer to the created IP packet. NULL if there was not enough free resources.
|
||||
*/
|
||||
{
|
||||
/* FIXME: Is this needed? */
|
||||
RtlZeroMemory(IPPacket, sizeof(IP_PACKET));
|
||||
|
||||
INIT_TAG(IPPacket, TAG('I','P','K','T'));
|
||||
|
||||
IPPacket->Free = DontFreePacket;
|
||||
IPPacket->Type = Type;
|
||||
|
||||
return IPPacket;
|
||||
}
|
||||
|
||||
|
||||
void STDCALL IPTimeout( PVOID Context ) {
|
||||
IpWorkItemQueued = FALSE;
|
||||
|
||||
/* Check if datagram fragments have taken too long to assemble */
|
||||
IPDatagramReassemblyTimeout();
|
||||
|
||||
/* Clean possible outdated cached neighbor addresses */
|
||||
NBTimeout();
|
||||
|
||||
/* Call upper layer timeout routines */
|
||||
TCPTimeout();
|
||||
}
|
||||
|
||||
|
||||
VOID IPDispatchProtocol(
|
||||
PIP_INTERFACE Interface,
|
||||
PIP_PACKET IPPacket)
|
||||
/*
|
||||
* FUNCTION: IP protocol dispatcher
|
||||
* ARGUMENTS:
|
||||
* NTE = Pointer to net table entry which the packet was received on
|
||||
* IPPacket = Pointer to an IP packet that was received
|
||||
* NOTES:
|
||||
* This routine examines the IP header and passes the packet on to the
|
||||
* right upper level protocol receive handler
|
||||
*/
|
||||
{
|
||||
UINT Protocol;
|
||||
|
||||
switch (IPPacket->Type) {
|
||||
case IP_ADDRESS_V4:
|
||||
Protocol = ((PIPv4_HEADER)(IPPacket->Header))->Protocol;
|
||||
break;
|
||||
case IP_ADDRESS_V6:
|
||||
/* FIXME: IPv6 adresses not supported */
|
||||
TI_DbgPrint(MIN_TRACE, ("IPv6 datagram discarded.\n"));
|
||||
return;
|
||||
default:
|
||||
Protocol = 0;
|
||||
}
|
||||
|
||||
/* Call the appropriate protocol handler */
|
||||
(*ProtocolTable[Protocol])(Interface, IPPacket);
|
||||
/* Special case for ICMP -- ICMP can be caught by a SOCK_RAW but also
|
||||
* must be handled here. */
|
||||
if( Protocol == IPPROTO_ICMP )
|
||||
ICMPReceive( Interface, IPPacket );
|
||||
}
|
||||
|
||||
|
||||
PIP_INTERFACE IPCreateInterface(
|
||||
PLLIP_BIND_INFO BindInfo)
|
||||
/*
|
||||
* FUNCTION: Creates an IP interface
|
||||
* ARGUMENTS:
|
||||
* BindInfo = Pointer to link layer to IP binding information
|
||||
* RETURNS:
|
||||
* Pointer to IP_INTERFACE structure, NULL if there was
|
||||
* not enough free resources
|
||||
*/
|
||||
{
|
||||
PIP_INTERFACE IF;
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Called. BindInfo (0x%X).\n", BindInfo));
|
||||
|
||||
#ifdef DBG
|
||||
if (BindInfo->Address) {
|
||||
PUCHAR A = BindInfo->Address;
|
||||
TI_DbgPrint(DEBUG_IP, ("Interface address (%02X %02X %02X %02X %02X %02X).\n",
|
||||
A[0], A[1], A[2], A[3], A[4], A[5]));
|
||||
}
|
||||
#endif
|
||||
|
||||
IF = exAllocatePool(NonPagedPool, sizeof(IP_INTERFACE));
|
||||
if (!IF) {
|
||||
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT_TAG(IF, TAG('F','A','C','E'));
|
||||
|
||||
IF->Free = FreeIF;
|
||||
IF->Context = BindInfo->Context;
|
||||
IF->HeaderSize = BindInfo->HeaderSize;
|
||||
if (IF->HeaderSize > MaxLLHeaderSize)
|
||||
MaxLLHeaderSize = IF->HeaderSize;
|
||||
|
||||
IF->MinFrameSize = BindInfo->MinFrameSize;
|
||||
if (IF->MinFrameSize > MinLLFrameSize)
|
||||
MinLLFrameSize = IF->MinFrameSize;
|
||||
|
||||
IF->MTU = BindInfo->MTU;
|
||||
IF->Address = BindInfo->Address;
|
||||
IF->AddressLength = BindInfo->AddressLength;
|
||||
IF->Transmit = BindInfo->Transmit;
|
||||
|
||||
TcpipInitializeSpinLock(&IF->Lock);
|
||||
|
||||
#ifdef __NTDRIVER__
|
||||
InsertTDIInterfaceEntity( IF );
|
||||
#endif
|
||||
|
||||
return IF;
|
||||
}
|
||||
|
||||
|
||||
VOID IPDestroyInterface(
|
||||
PIP_INTERFACE IF)
|
||||
/*
|
||||
* FUNCTION: Destroys an IP interface
|
||||
* ARGUMENTS:
|
||||
* IF = Pointer to interface to destroy
|
||||
*/
|
||||
{
|
||||
TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X).\n", IF));
|
||||
|
||||
#ifdef __NTDRIVER__
|
||||
RemoveTDIInterfaceEntity( IF );
|
||||
#endif
|
||||
|
||||
exFreePool(IF);
|
||||
}
|
||||
|
||||
VOID IPAddInterfaceRoute( PIP_INTERFACE IF ) {
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
IP_ADDRESS NetworkAddress;
|
||||
|
||||
/* Add a permanent neighbor for this NTE */
|
||||
NCE = NBAddNeighbor(IF, &IF->Unicast,
|
||||
IF->Address, IF->AddressLength,
|
||||
NUD_PERMANENT);
|
||||
if (!NCE) {
|
||||
TI_DbgPrint(MIN_TRACE, ("Could not create NCE.\n"));
|
||||
}
|
||||
|
||||
AddrWidenAddress( &NetworkAddress, &IF->Unicast, &IF->Netmask );
|
||||
|
||||
if (!RouterAddRoute(&NetworkAddress, &IF->Netmask, NCE, 1)) {
|
||||
TI_DbgPrint(MIN_TRACE, ("Could not add route due to insufficient resources.\n"));
|
||||
}
|
||||
|
||||
/* Allow TCP to hang some configuration on this interface */
|
||||
IF->TCPContext = TCPPrepareInterface( IF );
|
||||
}
|
||||
|
||||
BOOLEAN IPRegisterInterface(
|
||||
PIP_INTERFACE IF)
|
||||
/*
|
||||
* FUNCTION: Registers an IP interface with IP layer
|
||||
* ARGUMENTS:
|
||||
* IF = Pointer to interface to register
|
||||
* RETURNS;
|
||||
* TRUE if interface was successfully registered, FALSE if not
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
UINT ChosenIndex = 1;
|
||||
BOOLEAN IndexHasBeenChosen;
|
||||
IF_LIST_ITER(Interface);
|
||||
|
||||
TI_DbgPrint(MID_TRACE, ("Called. IF (0x%X).\n", IF));
|
||||
|
||||
TcpipAcquireSpinLock(&IF->Lock, &OldIrql);
|
||||
|
||||
/* Choose an index */
|
||||
do {
|
||||
IndexHasBeenChosen = TRUE;
|
||||
ForEachInterface(Interface) {
|
||||
if( Interface->Index == ChosenIndex ) {
|
||||
ChosenIndex++;
|
||||
IndexHasBeenChosen = FALSE;
|
||||
}
|
||||
} EndFor(Interface);
|
||||
} while( !IndexHasBeenChosen );
|
||||
|
||||
IF->Index = ChosenIndex;
|
||||
|
||||
IPAddInterfaceRoute( IF );
|
||||
|
||||
/* Add interface to the global interface list */
|
||||
TcpipInterlockedInsertTailList(&InterfaceListHead,
|
||||
&IF->ListEntry,
|
||||
&InterfaceListLock);
|
||||
|
||||
TcpipReleaseSpinLock(&IF->Lock, OldIrql);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID IPRemoveInterfaceRoute( PIP_INTERFACE IF ) {
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
IP_ADDRESS GeneralRoute;
|
||||
|
||||
TCPDisposeInterfaceData( IF->TCPContext );
|
||||
IF->TCPContext = NULL;
|
||||
|
||||
TI_DbgPrint(DEBUG_IP,("Removing interface Addr %s\n", A2S(&IF->Unicast)));
|
||||
TI_DbgPrint(DEBUG_IP,(" Mask %s\n", A2S(&IF->Netmask)));
|
||||
|
||||
AddrWidenAddress(&GeneralRoute,&IF->Unicast,&IF->Netmask);
|
||||
|
||||
RouterRemoveRoute(&GeneralRoute, &IF->Unicast);
|
||||
|
||||
/* Remove permanent NCE, but first we have to find it */
|
||||
NCE = NBLocateNeighbor(&IF->Unicast);
|
||||
if (NCE)
|
||||
NBRemoveNeighbor(NCE);
|
||||
else
|
||||
TI_DbgPrint(DEBUG_IP, ("Could not delete IF route (0x%X)\n", IF));
|
||||
}
|
||||
|
||||
VOID IPUnregisterInterface(
|
||||
PIP_INTERFACE IF)
|
||||
/*
|
||||
* FUNCTION: Unregisters an IP interface with IP layer
|
||||
* ARGUMENTS:
|
||||
* IF = Pointer to interface to unregister
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql3;
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X).\n", IF));
|
||||
|
||||
IPRemoveInterfaceRoute( IF );
|
||||
|
||||
TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql3);
|
||||
RemoveEntryList(&IF->ListEntry);
|
||||
TcpipReleaseSpinLock(&InterfaceListLock, OldIrql3);
|
||||
}
|
||||
|
||||
|
||||
VOID IPRegisterProtocol(
|
||||
UINT ProtocolNumber,
|
||||
IP_PROTOCOL_HANDLER Handler)
|
||||
/*
|
||||
* FUNCTION: Registers a handler for an IP protocol number
|
||||
* ARGUMENTS:
|
||||
* ProtocolNumber = Internet Protocol number for which to register handler
|
||||
* Handler = Pointer to handler to be called when a packet is received
|
||||
* NOTES:
|
||||
* To unregister a protocol handler, call this function with Handler = NULL
|
||||
*/
|
||||
{
|
||||
#ifdef DBG
|
||||
if (ProtocolNumber >= IP_PROTOCOL_TABLE_SIZE)
|
||||
TI_DbgPrint(MIN_TRACE, ("Protocol number is out of range (%d).\n", ProtocolNumber));
|
||||
#endif
|
||||
|
||||
ProtocolTable[ProtocolNumber] = Handler;
|
||||
}
|
||||
|
||||
|
||||
VOID DefaultProtocolHandler(
|
||||
PIP_INTERFACE Interface,
|
||||
PIP_PACKET IPPacket)
|
||||
/*
|
||||
* FUNCTION: Default handler for Internet protocols
|
||||
* ARGUMENTS:
|
||||
* NTE = Pointer to net table entry which the packet was received on
|
||||
* IPPacket = Pointer to an IP packet that was received
|
||||
*/
|
||||
{
|
||||
TI_DbgPrint(MID_TRACE, ("[IF %x] Packet of unknown Internet protocol "
|
||||
"discarded.\n", Interface));
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS IPStartup(PUNICODE_STRING RegistryPath)
|
||||
/*
|
||||
* FUNCTION: Initializes the IP subsystem
|
||||
* ARGUMENTS:
|
||||
* RegistryPath = Our registry node for configuration parameters
|
||||
* RETURNS:
|
||||
* Status of operation
|
||||
*/
|
||||
{
|
||||
UINT i;
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
|
||||
|
||||
MaxLLHeaderSize = 0;
|
||||
MinLLFrameSize = 0;
|
||||
|
||||
/* Initialize lookaside lists */
|
||||
ExInitializeNPagedLookasideList(
|
||||
&IPDRList, /* Lookaside list */
|
||||
NULL, /* Allocate routine */
|
||||
NULL, /* Free routine */
|
||||
0, /* Flags */
|
||||
sizeof(IPDATAGRAM_REASSEMBLY), /* Size of each entry */
|
||||
TAG('I','P','D','R'), /* Tag */
|
||||
0); /* Depth */
|
||||
|
||||
ExInitializeNPagedLookasideList(
|
||||
&IPPacketList, /* Lookaside list */
|
||||
NULL, /* Allocate routine */
|
||||
NULL, /* Free routine */
|
||||
0, /* Flags */
|
||||
sizeof(IP_PACKET), /* Size of each entry */
|
||||
TAG('I','P','P','K'), /* Tag */
|
||||
0); /* Depth */
|
||||
|
||||
ExInitializeNPagedLookasideList(
|
||||
&IPFragmentList, /* Lookaside list */
|
||||
NULL, /* Allocate routine */
|
||||
NULL, /* Free routine */
|
||||
0, /* Flags */
|
||||
sizeof(IP_FRAGMENT), /* Size of each entry */
|
||||
TAG('I','P','F','G'), /* Tag */
|
||||
0); /* Depth */
|
||||
|
||||
ExInitializeNPagedLookasideList(
|
||||
&IPHoleList, /* Lookaside list */
|
||||
NULL, /* Allocate routine */
|
||||
NULL, /* Free routine */
|
||||
0, /* Flags */
|
||||
sizeof(IPDATAGRAM_HOLE), /* Size of each entry */
|
||||
TAG('I','P','H','L'), /* Tag */
|
||||
0); /* Depth */
|
||||
|
||||
/* Start routing subsystem */
|
||||
RouterStartup();
|
||||
|
||||
/* Start neighbor cache subsystem */
|
||||
NBStartup();
|
||||
|
||||
/* Fill the protocol dispatch table with pointers
|
||||
to the default protocol handler */
|
||||
for (i = 0; i < IP_PROTOCOL_TABLE_SIZE; i++)
|
||||
IPRegisterProtocol(i, DefaultProtocolHandler);
|
||||
|
||||
/* Initialize NTE list and protecting lock */
|
||||
InitializeListHead(&NetTableListHead);
|
||||
TcpipInitializeSpinLock(&NetTableListLock);
|
||||
|
||||
/* Initialize reassembly list and protecting lock */
|
||||
InitializeListHead(&ReassemblyListHead);
|
||||
TcpipInitializeSpinLock(&ReassemblyListLock);
|
||||
|
||||
IPInitialized = TRUE;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS IPShutdown(
|
||||
VOID)
|
||||
/*
|
||||
* FUNCTION: Shuts down the IP subsystem
|
||||
* RETURNS:
|
||||
* Status of operation
|
||||
*/
|
||||
{
|
||||
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
|
||||
|
||||
if (!IPInitialized)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
/* Shutdown neighbor cache subsystem */
|
||||
NBShutdown();
|
||||
|
||||
/* Shutdown routing subsystem */
|
||||
RouterShutdown();
|
||||
|
||||
IPFreeReassemblyList();
|
||||
|
||||
/* Destroy lookaside lists */
|
||||
ExDeleteNPagedLookasideList(&IPHoleList);
|
||||
ExDeleteNPagedLookasideList(&IPDRList);
|
||||
ExDeleteNPagedLookasideList(&IPPacketList);
|
||||
ExDeleteNPagedLookasideList(&IPFragmentList);
|
||||
|
||||
IPInitialized = FALSE;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Add table
Add a link
Reference in a new issue