mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 23:45:42 +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
681
sdk/lib/drivers/ip/network/receive.c
Normal file
681
sdk/lib/drivers/ip/network/receive.c
Normal file
|
@ -0,0 +1,681 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS TCP/IP protocol driver
|
||||
* FILE: network/receive.c
|
||||
* PURPOSE: Internet Protocol receive routines
|
||||
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||
* NOTES: The IP datagram reassembly algorithm is taken from
|
||||
* from RFC 815
|
||||
* REVISIONS:
|
||||
* CSH 01/08-2000 Created
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
LIST_ENTRY ReassemblyListHead;
|
||||
KSPIN_LOCK ReassemblyListLock;
|
||||
NPAGED_LOOKASIDE_LIST IPDRList;
|
||||
NPAGED_LOOKASIDE_LIST IPFragmentList;
|
||||
NPAGED_LOOKASIDE_LIST IPHoleList;
|
||||
|
||||
PIPDATAGRAM_HOLE CreateHoleDescriptor(
|
||||
ULONG First,
|
||||
ULONG Last)
|
||||
/*
|
||||
* FUNCTION: Returns a pointer to a IP datagram hole descriptor
|
||||
* ARGUMENTS:
|
||||
* First = Offset of first octet of the hole
|
||||
* Last = Offset of last octet of the hole
|
||||
* RETURNS:
|
||||
* Pointer to descriptor, NULL if there was not enough free
|
||||
* resources
|
||||
*/
|
||||
{
|
||||
PIPDATAGRAM_HOLE Hole;
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Called. First (%d) Last (%d).\n", First, Last));
|
||||
|
||||
Hole = ExAllocateFromNPagedLookasideList(&IPHoleList);
|
||||
if (!Hole) {
|
||||
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Hole->First = First;
|
||||
Hole->Last = Last;
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Returning hole descriptor at (0x%X).\n", Hole));
|
||||
|
||||
return Hole;
|
||||
}
|
||||
|
||||
|
||||
VOID FreeIPDR(
|
||||
PIPDATAGRAM_REASSEMBLY IPDR)
|
||||
/*
|
||||
* FUNCTION: Frees an IP datagram reassembly structure
|
||||
* ARGUMENTS:
|
||||
* IPDR = Pointer to IP datagram reassembly structure
|
||||
*/
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PLIST_ENTRY NextEntry;
|
||||
PIPDATAGRAM_HOLE CurrentH;
|
||||
PIP_FRAGMENT CurrentF;
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Freeing IP datagram reassembly descriptor (0x%X).\n", IPDR));
|
||||
|
||||
/* Free all descriptors */
|
||||
CurrentEntry = IPDR->HoleListHead.Flink;
|
||||
while (CurrentEntry != &IPDR->HoleListHead) {
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
CurrentH = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry);
|
||||
/* Unlink it from the list */
|
||||
RemoveEntryList(CurrentEntry);
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Freeing hole descriptor at (0x%X).\n", CurrentH));
|
||||
|
||||
/* And free the hole descriptor */
|
||||
ExFreeToNPagedLookasideList(&IPHoleList, CurrentH);
|
||||
|
||||
CurrentEntry = NextEntry;
|
||||
}
|
||||
|
||||
/* Free all fragments */
|
||||
CurrentEntry = IPDR->FragmentListHead.Flink;
|
||||
while (CurrentEntry != &IPDR->FragmentListHead) {
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
CurrentF = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry);
|
||||
/* Unlink it from the list */
|
||||
RemoveEntryList(CurrentEntry);
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Freeing fragment packet at (0x%X).\n", CurrentF->Packet));
|
||||
|
||||
/* Free the fragment data buffer */
|
||||
if (CurrentF->ReturnPacket)
|
||||
{
|
||||
NdisReturnPackets(&CurrentF->Packet, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeNdisPacket(CurrentF->Packet);
|
||||
}
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Freeing fragment at (0x%X).\n", CurrentF));
|
||||
|
||||
/* And free the fragment descriptor */
|
||||
ExFreeToNPagedLookasideList(&IPFragmentList, CurrentF);
|
||||
CurrentEntry = NextEntry;
|
||||
}
|
||||
|
||||
if (IPDR->IPv4Header)
|
||||
{
|
||||
TI_DbgPrint(DEBUG_IP, ("Freeing IPDR header at (0x%X).\n", IPDR->IPv4Header));
|
||||
ExFreePoolWithTag(IPDR->IPv4Header, PACKET_BUFFER_TAG);
|
||||
}
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Freeing IPDR data at (0x%X).\n", IPDR));
|
||||
|
||||
ExFreeToNPagedLookasideList(&IPDRList, IPDR);
|
||||
}
|
||||
|
||||
|
||||
VOID RemoveIPDR(
|
||||
PIPDATAGRAM_REASSEMBLY IPDR)
|
||||
/*
|
||||
* FUNCTION: Removes an IP datagram reassembly structure from the global list
|
||||
* ARGUMENTS:
|
||||
* IPDR = Pointer to IP datagram reassembly structure
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Removing IPDR at (0x%X).\n", IPDR));
|
||||
|
||||
TcpipAcquireSpinLock(&ReassemblyListLock, &OldIrql);
|
||||
RemoveEntryList(&IPDR->ListEntry);
|
||||
TcpipReleaseSpinLock(&ReassemblyListLock, OldIrql);
|
||||
}
|
||||
|
||||
|
||||
PIPDATAGRAM_REASSEMBLY GetReassemblyInfo(
|
||||
PIP_PACKET IPPacket)
|
||||
/*
|
||||
* FUNCTION: Returns a pointer to an IP datagram reassembly structure
|
||||
* ARGUMENTS:
|
||||
* IPPacket = Pointer to IP packet
|
||||
* NOTES:
|
||||
* A datagram is identified by four paramters, which are
|
||||
* Source and destination address, protocol number and
|
||||
* identification number
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PIPDATAGRAM_REASSEMBLY Current;
|
||||
PIPv4_HEADER Header = (PIPv4_HEADER)IPPacket->Header;
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Searching for IPDR for IP packet at (0x%X).\n", IPPacket));
|
||||
|
||||
TcpipAcquireSpinLock(&ReassemblyListLock, &OldIrql);
|
||||
|
||||
/* FIXME: Assume IPv4 */
|
||||
|
||||
CurrentEntry = ReassemblyListHead.Flink;
|
||||
while (CurrentEntry != &ReassemblyListHead) {
|
||||
Current = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_REASSEMBLY, ListEntry);
|
||||
if (AddrIsEqual(&IPPacket->SrcAddr, &Current->SrcAddr) &&
|
||||
(Header->Id == Current->Id) &&
|
||||
(Header->Protocol == Current->Protocol) &&
|
||||
(AddrIsEqual(&IPPacket->DstAddr, &Current->DstAddr))) {
|
||||
TcpipReleaseSpinLock(&ReassemblyListLock, OldIrql);
|
||||
|
||||
return Current;
|
||||
}
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
}
|
||||
|
||||
TcpipReleaseSpinLock(&ReassemblyListLock, OldIrql);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
ReassembleDatagram(
|
||||
PIP_PACKET IPPacket,
|
||||
PIPDATAGRAM_REASSEMBLY IPDR)
|
||||
/*
|
||||
* FUNCTION: Reassembles an IP datagram
|
||||
* ARGUMENTS:
|
||||
* IPDR = Pointer to IP datagram reassembly structure
|
||||
* NOTES:
|
||||
* This routine concatenates fragments into a complete IP datagram.
|
||||
* The lock is held when this routine is called
|
||||
* RETURNS:
|
||||
* Pointer to IP packet, NULL if there was not enough free resources
|
||||
* NOTES:
|
||||
* At this point, header is expected to point to the IP header
|
||||
*/
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PIP_FRAGMENT Fragment;
|
||||
PCHAR Data;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Reassembling datagram from IPDR at (0x%X).\n", IPDR));
|
||||
TI_DbgPrint(DEBUG_IP, ("IPDR->HeaderSize = %d\n", IPDR->HeaderSize));
|
||||
TI_DbgPrint(DEBUG_IP, ("IPDR->DataSize = %d\n", IPDR->DataSize));
|
||||
|
||||
IPPacket->TotalSize = IPDR->HeaderSize + IPDR->DataSize;
|
||||
IPPacket->HeaderSize = IPDR->HeaderSize;
|
||||
|
||||
RtlCopyMemory(&IPPacket->SrcAddr, &IPDR->SrcAddr, sizeof(IP_ADDRESS));
|
||||
RtlCopyMemory(&IPPacket->DstAddr, &IPDR->DstAddr, sizeof(IP_ADDRESS));
|
||||
|
||||
/* Allocate space for full IP datagram */
|
||||
IPPacket->Header = ExAllocatePoolWithTag(PagedPool, IPPacket->TotalSize, PACKET_BUFFER_TAG);
|
||||
if (!IPPacket->Header) {
|
||||
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
(*IPPacket->Free)(IPPacket);
|
||||
return FALSE;
|
||||
}
|
||||
IPPacket->MappedHeader = FALSE;
|
||||
|
||||
/* Copy the header into the buffer */
|
||||
RtlCopyMemory(IPPacket->Header, IPDR->IPv4Header, IPDR->HeaderSize);
|
||||
|
||||
Data = (PVOID)((ULONG_PTR)IPPacket->Header + IPDR->HeaderSize);
|
||||
IPPacket->Data = Data;
|
||||
|
||||
/* Copy data from all fragments into buffer */
|
||||
CurrentEntry = IPDR->FragmentListHead.Flink;
|
||||
while (CurrentEntry != &IPDR->FragmentListHead) {
|
||||
Fragment = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry);
|
||||
|
||||
/* Copy fragment data into datagram buffer */
|
||||
CopyPacketToBuffer(Data + Fragment->Offset,
|
||||
Fragment->Packet,
|
||||
Fragment->PacketOffset,
|
||||
Fragment->Size);
|
||||
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
__inline VOID Cleanup(
|
||||
PKSPIN_LOCK Lock,
|
||||
KIRQL OldIrql,
|
||||
PIPDATAGRAM_REASSEMBLY IPDR)
|
||||
/*
|
||||
* FUNCTION: Performs cleaning operations on errors
|
||||
* ARGUMENTS:
|
||||
* Lock = Pointer to spin lock to be released
|
||||
* OldIrql = Value of IRQL when spin lock was acquired
|
||||
* IPDR = Pointer to IP datagram reassembly structure to free
|
||||
* Buffer = Optional pointer to a buffer to free
|
||||
*/
|
||||
{
|
||||
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
|
||||
TcpipReleaseSpinLock(Lock, OldIrql);
|
||||
RemoveIPDR(IPDR);
|
||||
FreeIPDR(IPDR);
|
||||
}
|
||||
|
||||
|
||||
VOID ProcessFragment(
|
||||
PIP_INTERFACE IF,
|
||||
PIP_PACKET IPPacket)
|
||||
/*
|
||||
* FUNCTION: Processes an IP datagram or fragment
|
||||
* ARGUMENTS:
|
||||
* IF = Pointer to IP interface packet was receive on
|
||||
* IPPacket = Pointer to IP packet
|
||||
* NOTES:
|
||||
* This routine reassembles fragments and, if a whole datagram can
|
||||
* be assembled, passes the datagram on to the IP protocol dispatcher
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PIPDATAGRAM_REASSEMBLY IPDR;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PIPDATAGRAM_HOLE Hole, NewHole;
|
||||
USHORT FragFirst;
|
||||
USHORT FragLast;
|
||||
BOOLEAN MoreFragments;
|
||||
PIPv4_HEADER IPv4Header;
|
||||
IP_PACKET Datagram;
|
||||
PIP_FRAGMENT Fragment;
|
||||
BOOLEAN Success;
|
||||
|
||||
/* FIXME: Assume IPv4 */
|
||||
|
||||
IPv4Header = (PIPv4_HEADER)IPPacket->Header;
|
||||
|
||||
/* Check if we already have an reassembly structure for this datagram */
|
||||
IPDR = GetReassemblyInfo(IPPacket);
|
||||
if (IPDR) {
|
||||
TI_DbgPrint(DEBUG_IP, ("Continueing assembly.\n"));
|
||||
/* We have a reassembly structure */
|
||||
TcpipAcquireSpinLock(&IPDR->Lock, &OldIrql);
|
||||
|
||||
/* Reset the timeout since we received a fragment */
|
||||
IPDR->TimeoutCount = 0;
|
||||
} else {
|
||||
TI_DbgPrint(DEBUG_IP, ("Starting new assembly.\n"));
|
||||
|
||||
/* We don't have a reassembly structure, create one */
|
||||
IPDR = ExAllocateFromNPagedLookasideList(&IPDRList);
|
||||
if (!IPDR)
|
||||
/* We don't have the resources to process this packet, discard it */
|
||||
return;
|
||||
|
||||
/* Create a descriptor spanning from zero to infinity.
|
||||
Actually, we use a value slightly greater than the
|
||||
maximum number of octets an IP datagram can contain */
|
||||
Hole = CreateHoleDescriptor(0, 65536);
|
||||
if (!Hole) {
|
||||
/* We don't have the resources to process this packet, discard it */
|
||||
ExFreeToNPagedLookasideList(&IPDRList, IPDR);
|
||||
return;
|
||||
}
|
||||
AddrInitIPv4(&IPDR->SrcAddr, IPv4Header->SrcAddr);
|
||||
AddrInitIPv4(&IPDR->DstAddr, IPv4Header->DstAddr);
|
||||
IPDR->Id = IPv4Header->Id;
|
||||
IPDR->Protocol = IPv4Header->Protocol;
|
||||
IPDR->TimeoutCount = 0;
|
||||
InitializeListHead(&IPDR->FragmentListHead);
|
||||
InitializeListHead(&IPDR->HoleListHead);
|
||||
InsertTailList(&IPDR->HoleListHead, &Hole->ListEntry);
|
||||
|
||||
TcpipInitializeSpinLock(&IPDR->Lock);
|
||||
|
||||
TcpipAcquireSpinLock(&IPDR->Lock, &OldIrql);
|
||||
|
||||
/* Update the reassembly list */
|
||||
TcpipInterlockedInsertTailList(
|
||||
&ReassemblyListHead,
|
||||
&IPDR->ListEntry,
|
||||
&ReassemblyListLock);
|
||||
}
|
||||
|
||||
FragFirst = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_FRAGOFS_MASK) << 3;
|
||||
FragLast = FragFirst + WN2H(IPv4Header->TotalLength);
|
||||
MoreFragments = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_MF_MASK) > 0;
|
||||
|
||||
CurrentEntry = IPDR->HoleListHead.Flink;
|
||||
for (;;) {
|
||||
if (CurrentEntry == &IPDR->HoleListHead)
|
||||
break;
|
||||
|
||||
Hole = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry);
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Comparing Fragment (%d,%d) to Hole (%d,%d).\n",
|
||||
FragFirst, FragLast, Hole->First, Hole->Last));
|
||||
|
||||
if ((FragFirst > Hole->Last) || (FragLast < Hole->First)) {
|
||||
TI_DbgPrint(MID_TRACE, ("No overlap.\n"));
|
||||
/* The fragment does not overlap with the hole, try next
|
||||
descriptor in the list */
|
||||
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The fragment overlap with the hole, unlink the descriptor */
|
||||
RemoveEntryList(CurrentEntry);
|
||||
|
||||
if (FragFirst > Hole->First) {
|
||||
NewHole = CreateHoleDescriptor(Hole->First, FragFirst - 1);
|
||||
if (!NewHole) {
|
||||
/* We don't have the resources to process this packet, discard it */
|
||||
ExFreeToNPagedLookasideList(&IPHoleList, Hole);
|
||||
Cleanup(&IPDR->Lock, OldIrql, IPDR);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Put the new descriptor in the list */
|
||||
InsertTailList(&IPDR->HoleListHead, &NewHole->ListEntry);
|
||||
}
|
||||
|
||||
if ((FragLast < Hole->Last) && MoreFragments) {
|
||||
NewHole = CreateHoleDescriptor(FragLast + 1, Hole->Last);
|
||||
if (!NewHole) {
|
||||
/* We don't have the resources to process this packet, discard it */
|
||||
ExFreeToNPagedLookasideList(&IPHoleList, Hole);
|
||||
Cleanup(&IPDR->Lock, OldIrql, IPDR);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Put the new hole descriptor in the list */
|
||||
InsertTailList(&IPDR->HoleListHead, &NewHole->ListEntry);
|
||||
}
|
||||
|
||||
ExFreeToNPagedLookasideList(&IPHoleList, Hole);
|
||||
|
||||
/* If this is the first fragment, save the IP header */
|
||||
if (FragFirst == 0) {
|
||||
IPDR->IPv4Header = ExAllocatePoolWithTag(NonPagedPool,
|
||||
IPPacket->HeaderSize,
|
||||
PACKET_BUFFER_TAG);
|
||||
if (!IPDR->IPv4Header)
|
||||
{
|
||||
Cleanup(&IPDR->Lock, OldIrql, IPDR);
|
||||
return;
|
||||
}
|
||||
|
||||
RtlCopyMemory(IPDR->IPv4Header, IPPacket->Header, IPPacket->HeaderSize);
|
||||
IPDR->HeaderSize = IPPacket->HeaderSize;
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("First fragment found. Header buffer is at (0x%X). "
|
||||
"Header size is (%d).\n", &IPDR->IPv4Header, IPPacket->HeaderSize));
|
||||
|
||||
}
|
||||
|
||||
/* Create a buffer, copy the data into it and put it
|
||||
in the fragment list */
|
||||
|
||||
Fragment = ExAllocateFromNPagedLookasideList(&IPFragmentList);
|
||||
if (!Fragment) {
|
||||
/* We don't have the resources to process this packet, discard it */
|
||||
Cleanup(&IPDR->Lock, OldIrql, IPDR);
|
||||
return;
|
||||
}
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Fragment descriptor allocated at (0x%X).\n", Fragment));
|
||||
|
||||
Fragment->Size = IPPacket->TotalSize - IPPacket->HeaderSize;
|
||||
Fragment->Packet = IPPacket->NdisPacket;
|
||||
Fragment->ReturnPacket = IPPacket->ReturnPacket;
|
||||
Fragment->PacketOffset = IPPacket->Position + IPPacket->HeaderSize;
|
||||
Fragment->Offset = FragFirst;
|
||||
|
||||
/* Disassociate the NDIS packet so it isn't freed upon return from IPReceive() */
|
||||
IPPacket->NdisPacket = NULL;
|
||||
|
||||
/* If this is the last fragment, compute and save the datagram data size */
|
||||
if (!MoreFragments)
|
||||
IPDR->DataSize = FragFirst + Fragment->Size;
|
||||
|
||||
/* Put the fragment in the list */
|
||||
InsertTailList(&IPDR->FragmentListHead, &Fragment->ListEntry);
|
||||
break;
|
||||
}
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Done searching for hole descriptor.\n"));
|
||||
|
||||
if (IsListEmpty(&IPDR->HoleListHead)) {
|
||||
/* Hole list is empty which means a complete datagram can be assembled.
|
||||
Assemble the datagram and pass it to an upper layer protocol */
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Complete datagram received.\n"));
|
||||
|
||||
RemoveIPDR(IPDR);
|
||||
TcpipReleaseSpinLock(&IPDR->Lock, OldIrql);
|
||||
|
||||
/* FIXME: Assumes IPv4 */
|
||||
IPInitializePacket(&Datagram, IP_ADDRESS_V4);
|
||||
|
||||
Success = ReassembleDatagram(&Datagram, IPDR);
|
||||
|
||||
FreeIPDR(IPDR);
|
||||
|
||||
if (!Success)
|
||||
/* Not enough free resources, discard the packet */
|
||||
return;
|
||||
|
||||
DISPLAY_IP_PACKET(&Datagram);
|
||||
|
||||
/* Give the packet to the protocol dispatcher */
|
||||
IPDispatchProtocol(IF, &Datagram);
|
||||
|
||||
/* We're done with this datagram */
|
||||
TI_DbgPrint(MAX_TRACE, ("Freeing datagram at (0x%X).\n", Datagram));
|
||||
Datagram.Free(&Datagram);
|
||||
} else
|
||||
TcpipReleaseSpinLock(&IPDR->Lock, OldIrql);
|
||||
}
|
||||
|
||||
|
||||
VOID IPFreeReassemblyList(
|
||||
VOID)
|
||||
/*
|
||||
* FUNCTION: Frees all IP datagram reassembly structures in the list
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PLIST_ENTRY CurrentEntry, NextEntry;
|
||||
PIPDATAGRAM_REASSEMBLY Current;
|
||||
|
||||
TcpipAcquireSpinLock(&ReassemblyListLock, &OldIrql);
|
||||
|
||||
CurrentEntry = ReassemblyListHead.Flink;
|
||||
while (CurrentEntry != &ReassemblyListHead) {
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
Current = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_REASSEMBLY, ListEntry);
|
||||
|
||||
/* Unlink it from the list */
|
||||
RemoveEntryList(CurrentEntry);
|
||||
|
||||
/* And free the descriptor */
|
||||
FreeIPDR(Current);
|
||||
|
||||
CurrentEntry = NextEntry;
|
||||
}
|
||||
|
||||
TcpipReleaseSpinLock(&ReassemblyListLock, OldIrql);
|
||||
}
|
||||
|
||||
|
||||
VOID IPDatagramReassemblyTimeout(
|
||||
VOID)
|
||||
/*
|
||||
* FUNCTION: IP datagram reassembly timeout handler
|
||||
* NOTES:
|
||||
* This routine is called by IPTimeout to free any resources used
|
||||
* to hold IP fragments that have taken too long to reassemble
|
||||
*/
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry, NextEntry;
|
||||
PIPDATAGRAM_REASSEMBLY CurrentIPDR;
|
||||
|
||||
TcpipAcquireSpinLockAtDpcLevel(&ReassemblyListLock);
|
||||
|
||||
CurrentEntry = ReassemblyListHead.Flink;
|
||||
while (CurrentEntry != &ReassemblyListHead)
|
||||
{
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
CurrentIPDR = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_REASSEMBLY, ListEntry);
|
||||
|
||||
TcpipAcquireSpinLockAtDpcLevel(&CurrentIPDR->Lock);
|
||||
|
||||
if (++CurrentIPDR->TimeoutCount == MAX_TIMEOUT_COUNT)
|
||||
{
|
||||
TcpipReleaseSpinLockFromDpcLevel(&CurrentIPDR->Lock);
|
||||
RemoveEntryList(CurrentEntry);
|
||||
FreeIPDR(CurrentIPDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(CurrentIPDR->TimeoutCount < MAX_TIMEOUT_COUNT);
|
||||
TcpipReleaseSpinLockFromDpcLevel(&CurrentIPDR->Lock);
|
||||
}
|
||||
|
||||
CurrentEntry = NextEntry;
|
||||
}
|
||||
|
||||
TcpipReleaseSpinLockFromDpcLevel(&ReassemblyListLock);
|
||||
}
|
||||
|
||||
VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket)
|
||||
/*
|
||||
* FUNCTION: Receives an IPv4 datagram (or fragment)
|
||||
* ARGUMENTS:
|
||||
* Context = Pointer to context information (IP_INTERFACE)
|
||||
* IPPacket = Pointer to IP packet
|
||||
*/
|
||||
{
|
||||
UCHAR FirstByte;
|
||||
ULONG BytesCopied;
|
||||
|
||||
TI_DbgPrint(DEBUG_IP, ("Received IPv4 datagram.\n"));
|
||||
|
||||
/* Read in the first IP header byte for size information */
|
||||
BytesCopied = CopyPacketToBuffer((PCHAR)&FirstByte,
|
||||
IPPacket->NdisPacket,
|
||||
IPPacket->Position,
|
||||
sizeof(UCHAR));
|
||||
if (BytesCopied != sizeof(UCHAR))
|
||||
{
|
||||
TI_DbgPrint(MIN_TRACE, ("Failed to copy in first byte\n"));
|
||||
/* Discard packet */
|
||||
return;
|
||||
}
|
||||
|
||||
IPPacket->HeaderSize = (FirstByte & 0x0F) << 2;
|
||||
TI_DbgPrint(DEBUG_IP, ("IPPacket->HeaderSize = %d\n", IPPacket->HeaderSize));
|
||||
|
||||
if (IPPacket->HeaderSize > IPv4_MAX_HEADER_SIZE) {
|
||||
TI_DbgPrint(MIN_TRACE, ("Datagram received with incorrect header size (%d).\n",
|
||||
IPPacket->HeaderSize));
|
||||
/* Discard packet */
|
||||
return;
|
||||
}
|
||||
|
||||
/* This is freed by IPPacket->Free() */
|
||||
IPPacket->Header = ExAllocatePoolWithTag(NonPagedPool,
|
||||
IPPacket->HeaderSize,
|
||||
PACKET_BUFFER_TAG);
|
||||
if (!IPPacket->Header)
|
||||
{
|
||||
TI_DbgPrint(MIN_TRACE, ("No resources to allocate header\n"));
|
||||
/* Discard packet */
|
||||
return;
|
||||
}
|
||||
|
||||
IPPacket->MappedHeader = FALSE;
|
||||
|
||||
BytesCopied = CopyPacketToBuffer((PCHAR)IPPacket->Header,
|
||||
IPPacket->NdisPacket,
|
||||
IPPacket->Position,
|
||||
IPPacket->HeaderSize);
|
||||
if (BytesCopied != IPPacket->HeaderSize)
|
||||
{
|
||||
TI_DbgPrint(MIN_TRACE, ("Failed to copy in header\n"));
|
||||
/* Discard packet */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Checksum IPv4 header */
|
||||
if (!IPv4CorrectChecksum(IPPacket->Header, IPPacket->HeaderSize)) {
|
||||
TI_DbgPrint(MIN_TRACE, ("Datagram received with bad checksum. Checksum field (0x%X)\n",
|
||||
WN2H(((PIPv4_HEADER)IPPacket->Header)->Checksum)));
|
||||
/* Discard packet */
|
||||
return;
|
||||
}
|
||||
|
||||
IPPacket->TotalSize = WN2H(((PIPv4_HEADER)IPPacket->Header)->TotalLength);
|
||||
|
||||
AddrInitIPv4(&IPPacket->SrcAddr, ((PIPv4_HEADER)IPPacket->Header)->SrcAddr);
|
||||
AddrInitIPv4(&IPPacket->DstAddr, ((PIPv4_HEADER)IPPacket->Header)->DstAddr);
|
||||
|
||||
TI_DbgPrint(MID_TRACE,("IPPacket->Position = %d\n",
|
||||
IPPacket->Position));
|
||||
|
||||
/* FIXME: Possibly forward packets with multicast addresses */
|
||||
|
||||
/* FIXME: Should we allow packets to be received on the wrong interface? */
|
||||
/* XXX Find out if this packet is destined for us */
|
||||
ProcessFragment(IF, IPPacket);
|
||||
}
|
||||
|
||||
|
||||
VOID IPReceive( PIP_INTERFACE IF, PIP_PACKET IPPacket )
|
||||
/*
|
||||
* FUNCTION: Receives an IP datagram (or fragment)
|
||||
* ARGUMENTS:
|
||||
* IF = Interface
|
||||
* IPPacket = Pointer to IP packet
|
||||
*/
|
||||
{
|
||||
UCHAR FirstByte;
|
||||
UINT Version, BytesCopied;
|
||||
|
||||
/* Read in the first IP header byte for version information */
|
||||
BytesCopied = CopyPacketToBuffer((PCHAR)&FirstByte,
|
||||
IPPacket->NdisPacket,
|
||||
IPPacket->Position,
|
||||
sizeof(UCHAR));
|
||||
if (BytesCopied != sizeof(UCHAR))
|
||||
{
|
||||
TI_DbgPrint(MIN_TRACE, ("Failed to copy in first byte\n"));
|
||||
IPPacket->Free(IPPacket);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check that IP header has a supported version */
|
||||
Version = (FirstByte >> 4);
|
||||
|
||||
switch (Version) {
|
||||
case 4:
|
||||
IPPacket->Type = IP_ADDRESS_V4;
|
||||
IPv4Receive(IF, IPPacket);
|
||||
break;
|
||||
case 6:
|
||||
IPPacket->Type = IP_ADDRESS_V6;
|
||||
TI_DbgPrint(MAX_TRACE, ("Datagram of type IPv6 discarded.\n"));
|
||||
break;
|
||||
default:
|
||||
TI_DbgPrint(MIN_TRACE, ("Datagram has an unsupported IP version %d.\n", Version));
|
||||
break;
|
||||
}
|
||||
|
||||
IPPacket->Free(IPPacket);
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Add table
Add a link
Reference in a new issue