ReactOS  0.4.13-dev-259-g5ca9c9c
receive.c File Reference
#include "precomp.h"
Include dependency graph for receive.c:

Go to the source code of this file.

Functions

PIPDATAGRAM_HOLE CreateHoleDescriptor (ULONG First, ULONG Last)
 
VOID FreeIPDR (PIPDATAGRAM_REASSEMBLY IPDR)
 
VOID RemoveIPDR (PIPDATAGRAM_REASSEMBLY IPDR)
 
PIPDATAGRAM_REASSEMBLY GetReassemblyInfo (PIP_PACKET IPPacket)
 
BOOLEAN ReassembleDatagram (PIP_PACKET IPPacket, PIPDATAGRAM_REASSEMBLY IPDR)
 
__inline VOID Cleanup (PKSPIN_LOCK Lock, KIRQL OldIrql, PIPDATAGRAM_REASSEMBLY IPDR)
 
VOID ProcessFragment (PIP_INTERFACE IF, PIP_PACKET IPPacket)
 
VOID IPFreeReassemblyList (VOID)
 
VOID IPDatagramReassemblyTimeout (VOID)
 
VOID IPv4Receive (PIP_INTERFACE IF, PIP_PACKET IPPacket)
 
VOID IPReceive (PIP_INTERFACE IF, PIP_PACKET IPPacket)
 

Variables

LIST_ENTRY ReassemblyListHead
 
KSPIN_LOCK ReassemblyListLock
 
NPAGED_LOOKASIDE_LIST IPDRList
 
NPAGED_LOOKASIDE_LIST IPFragmentList
 
NPAGED_LOOKASIDE_LIST IPHoleList
 

Function Documentation

◆ Cleanup()

__inline VOID Cleanup ( PKSPIN_LOCK  Lock,
KIRQL  OldIrql,
PIPDATAGRAM_REASSEMBLY  IPDR 
)

Definition at line 250 of file receive.c.

262 {
263  TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
264 
266  RemoveIPDR(IPDR);
267  FreeIPDR(IPDR);
268 }
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
VOID TcpipReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL Irql)
Definition: lock.c:26
VOID RemoveIPDR(PIPDATAGRAM_REASSEMBLY IPDR)
Definition: receive.c:123
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG IN OUT PLONG IN LONG Increment IN PNDIS_RW_LOCK Lock
Definition: CrNtStubs.h:75
VOID FreeIPDR(PIPDATAGRAM_REASSEMBLY IPDR)
Definition: receive.c:53
#define MIN_TRACE
Definition: debug.h:14

Referenced by ProcessFragment().

◆ CreateHoleDescriptor()

PIPDATAGRAM_HOLE CreateHoleDescriptor ( ULONG  First,
ULONG  Last 
)

Definition at line 21 of file receive.c.

33 {
34  PIPDATAGRAM_HOLE Hole;
35 
36  TI_DbgPrint(DEBUG_IP, ("Called. First (%d) Last (%d).\n", First, Last));
37 
38  Hole = ExAllocateFromNPagedLookasideList(&IPHoleList);
39  if (!Hole) {
40  TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
41  return NULL;
42  }
43 
44  Hole->First = First;
45  Hole->Last = Last;
46 
47  TI_DbgPrint(DEBUG_IP, ("Returning hole descriptor at (0x%X).\n", Hole));
48 
49  return Hole;
50 }
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
NPAGED_LOOKASIDE_LIST IPHoleList
Definition: receive.c:19
WCHAR First[]
Definition: FormatMessage.c:11
smooth NULL
Definition: ftsmooth.c:416
#define DEBUG_IP
Definition: debug.h:26
#define MIN_TRACE
Definition: debug.h:14

Referenced by ProcessFragment().

◆ FreeIPDR()

VOID FreeIPDR ( PIPDATAGRAM_REASSEMBLY  IPDR)

Definition at line 53 of file receive.c.

60 {
61  PLIST_ENTRY CurrentEntry;
62  PLIST_ENTRY NextEntry;
63  PIPDATAGRAM_HOLE CurrentH;
64  PIP_FRAGMENT CurrentF;
65 
66  TI_DbgPrint(DEBUG_IP, ("Freeing IP datagram reassembly descriptor (0x%X).\n", IPDR));
67 
68  /* Free all descriptors */
69  CurrentEntry = IPDR->HoleListHead.Flink;
70  while (CurrentEntry != &IPDR->HoleListHead) {
71  NextEntry = CurrentEntry->Flink;
72  CurrentH = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry);
73  /* Unlink it from the list */
74  RemoveEntryList(CurrentEntry);
75 
76  TI_DbgPrint(DEBUG_IP, ("Freeing hole descriptor at (0x%X).\n", CurrentH));
77 
78  /* And free the hole descriptor */
79  ExFreeToNPagedLookasideList(&IPHoleList, CurrentH);
80 
81  CurrentEntry = NextEntry;
82  }
83 
84  /* Free all fragments */
85  CurrentEntry = IPDR->FragmentListHead.Flink;
86  while (CurrentEntry != &IPDR->FragmentListHead) {
87  NextEntry = CurrentEntry->Flink;
88  CurrentF = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry);
89  /* Unlink it from the list */
90  RemoveEntryList(CurrentEntry);
91 
92  TI_DbgPrint(DEBUG_IP, ("Freeing fragment packet at (0x%X).\n", CurrentF->Packet));
93 
94  /* Free the fragment data buffer */
95  if (CurrentF->ReturnPacket)
96  {
97  NdisReturnPackets(&CurrentF->Packet, 1);
98  }
99  else
100  {
101  FreeNdisPacket(CurrentF->Packet);
102  }
103 
104  TI_DbgPrint(DEBUG_IP, ("Freeing fragment at (0x%X).\n", CurrentF));
105 
106  /* And free the fragment descriptor */
107  ExFreeToNPagedLookasideList(&IPFragmentList, CurrentF);
108  CurrentEntry = NextEntry;
109  }
110 
111  if (IPDR->IPv4Header)
112  {
113  TI_DbgPrint(DEBUG_IP, ("Freeing IPDR header at (0x%X).\n", IPDR->IPv4Header));
115  }
116 
117  TI_DbgPrint(DEBUG_IP, ("Freeing IPDR data at (0x%X).\n", IPDR));
118 
119  ExFreeToNPagedLookasideList(&IPDRList, IPDR);
120 }
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
PIP_HEADER IPv4Header
Definition: receive.h:41
PNDIS_PACKET Packet
Definition: receive.h:18
LIST_ENTRY HoleListHead
Definition: receive.h:44
#define FreeNdisPacket(x)
Definition: memtrack.h:8
NPAGED_LOOKASIDE_LIST IPHoleList
Definition: receive.c:19
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
NPAGED_LOOKASIDE_LIST IPFragmentList
Definition: receive.c:18
#define DEBUG_IP
Definition: debug.h:26
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID EXPORT NdisReturnPackets(IN PNDIS_PACKET *PacketsToReturn, IN UINT NumberOfPackets)
Definition: miniport.c:257
NPAGED_LOOKASIDE_LIST IPDRList
Definition: receive.c:17
Definition: typedefs.h:117
BOOLEAN ReturnPacket
Definition: receive.h:19
LIST_ENTRY FragmentListHead
Definition: receive.h:43
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define PACKET_BUFFER_TAG
Definition: tags.h:27

Referenced by Cleanup(), IPDatagramReassemblyTimeout(), IPFreeReassemblyList(), and ProcessFragment().

◆ GetReassemblyInfo()

PIPDATAGRAM_REASSEMBLY GetReassemblyInfo ( PIP_PACKET  IPPacket)

Definition at line 141 of file receive.c.

152 {
153  KIRQL OldIrql;
154  PLIST_ENTRY CurrentEntry;
155  PIPDATAGRAM_REASSEMBLY Current;
156  PIPv4_HEADER Header = (PIPv4_HEADER)IPPacket->Header;
157 
158  TI_DbgPrint(DEBUG_IP, ("Searching for IPDR for IP packet at (0x%X).\n", IPPacket));
159 
161 
162  /* FIXME: Assume IPv4 */
163 
164  CurrentEntry = ReassemblyListHead.Flink;
165  while (CurrentEntry != &ReassemblyListHead) {
166  Current = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_REASSEMBLY, ListEntry);
167  if (AddrIsEqual(&IPPacket->SrcAddr, &Current->SrcAddr) &&
168  (Header->Id == Current->Id) &&
169  (Header->Protocol == Current->Protocol) &&
170  (AddrIsEqual(&IPPacket->DstAddr, &Current->DstAddr))) {
172 
173  return Current;
174  }
175  CurrentEntry = CurrentEntry->Flink;
176  }
177 
179 
180  return NULL;
181 }
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
LIST_ENTRY ReassemblyListHead
Definition: receive.c:15
IP_ADDRESS SrcAddr
Definition: receive.h:37
IP_ADDRESS SrcAddr
Definition: ip.h:89
VOID TcpipReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL Irql)
Definition: lock.c:26
VOID TcpipAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL Irql)
Definition: lock.c:18
UCHAR KIRQL
Definition: env_spec_w32.h:591
Definition: Header.h:8
IP_ADDRESS DstAddr
Definition: receive.h:38
PVOID Header
Definition: ip.h:83
smooth NULL
Definition: ftsmooth.c:416
KSPIN_LOCK ReassemblyListLock
Definition: receive.c:16
#define DEBUG_IP
Definition: debug.h:26
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
BOOLEAN AddrIsEqual(PIP_ADDRESS Address1, PIP_ADDRESS Address2)
Definition: address.c:221
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Definition: typedefs.h:117
Definition: ip.h:37
IP_ADDRESS DstAddr
Definition: ip.h:90
struct IPv4_HEADER * PIPv4_HEADER

Referenced by ProcessFragment().

◆ IPDatagramReassemblyTimeout()

VOID IPDatagramReassemblyTimeout ( VOID  )

Definition at line 515 of file receive.c.

523 {
524  PLIST_ENTRY CurrentEntry, NextEntry;
525  PIPDATAGRAM_REASSEMBLY CurrentIPDR;
526 
528 
529  CurrentEntry = ReassemblyListHead.Flink;
530  while (CurrentEntry != &ReassemblyListHead)
531  {
532  NextEntry = CurrentEntry->Flink;
533  CurrentIPDR = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_REASSEMBLY, ListEntry);
534 
535  TcpipAcquireSpinLockAtDpcLevel(&CurrentIPDR->Lock);
536 
537  if (++CurrentIPDR->TimeoutCount == MAX_TIMEOUT_COUNT)
538  {
539  TcpipReleaseSpinLockFromDpcLevel(&CurrentIPDR->Lock);
540  RemoveEntryList(CurrentEntry);
541  FreeIPDR(CurrentIPDR);
542  }
543  else
544  {
545  ASSERT(CurrentIPDR->TimeoutCount < MAX_TIMEOUT_COUNT);
546  TcpipReleaseSpinLockFromDpcLevel(&CurrentIPDR->Lock);
547  }
548 
549  CurrentEntry = NextEntry;
550  }
551 
553 }
LIST_ENTRY ReassemblyListHead
Definition: receive.c:15
#define MAX_TIMEOUT_COUNT
Definition: receive.h:13
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
KSPIN_LOCK ReassemblyListLock
Definition: receive.c:16
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
VOID TcpipReleaseSpinLockFromDpcLevel(PKSPIN_LOCK SpinLock)
Definition: lock.c:30
Definition: typedefs.h:117
VOID FreeIPDR(PIPDATAGRAM_REASSEMBLY IPDR)
Definition: receive.c:53
VOID TcpipAcquireSpinLockAtDpcLevel(PKSPIN_LOCK SpinLock)
Definition: lock.c:22
KSPIN_LOCK Lock
Definition: receive.h:35

Referenced by IPTimeoutDpcFn().

◆ IPFreeReassemblyList()

VOID IPFreeReassemblyList ( VOID  )

Definition at line 485 of file receive.c.

490 {
491  KIRQL OldIrql;
492  PLIST_ENTRY CurrentEntry, NextEntry;
493  PIPDATAGRAM_REASSEMBLY Current;
494 
496 
497  CurrentEntry = ReassemblyListHead.Flink;
498  while (CurrentEntry != &ReassemblyListHead) {
499  NextEntry = CurrentEntry->Flink;
500  Current = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_REASSEMBLY, ListEntry);
501 
502  /* Unlink it from the list */
503  RemoveEntryList(CurrentEntry);
504 
505  /* And free the descriptor */
506  FreeIPDR(Current);
507 
508  CurrentEntry = NextEntry;
509  }
510 
512 }
LIST_ENTRY ReassemblyListHead
Definition: receive.c:15
VOID TcpipReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL Irql)
Definition: lock.c:26
VOID TcpipAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL Irql)
Definition: lock.c:18
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
UCHAR KIRQL
Definition: env_spec_w32.h:591
KSPIN_LOCK ReassemblyListLock
Definition: receive.c:16
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Definition: typedefs.h:117
VOID FreeIPDR(PIPDATAGRAM_REASSEMBLY IPDR)
Definition: receive.c:53

Referenced by IPShutdown().

◆ IPReceive()

VOID IPReceive ( PIP_INTERFACE  IF,
PIP_PACKET  IPPacket 
)

Definition at line 638 of file receive.c.

645 {
646  UCHAR FirstByte;
648 
649  /* Read in the first IP header byte for version information */
650  BytesCopied = CopyPacketToBuffer((PCHAR)&FirstByte,
651  IPPacket->NdisPacket,
652  IPPacket->Position,
653  sizeof(UCHAR));
654  if (BytesCopied != sizeof(UCHAR))
655  {
656  TI_DbgPrint(MIN_TRACE, ("Failed to copy in first byte\n"));
657  IPPacket->Free(IPPacket);
658  return;
659  }
660 
661  /* Check that IP header has a supported version */
662  Version = (FirstByte >> 4);
663 
664  switch (Version) {
665  case 4:
666  IPPacket->Type = IP_ADDRESS_V4;
667  IPv4Receive(IF, IPPacket);
668  break;
669  case 6:
670  IPPacket->Type = IP_ADDRESS_V6;
671  TI_DbgPrint(MAX_TRACE, ("Datagram of type IPv6 discarded.\n"));
672  break;
673  default:
674  TI_DbgPrint(MIN_TRACE, ("Datagram has an unsupported IP version %d.\n", Version));
675  break;
676  }
677 
678  IPPacket->Free(IPPacket);
679 }
signed char * PCHAR
Definition: retypes.h:7
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
IN PVOID IN PVOID IN USHORT Version
Definition: pci.h:359
OBJECT_FREE_ROUTINE Free
Definition: ip.h:78
#define IP_ADDRESS_V4
Definition: ip.h:32
_In_ UINT _In_ UINT _In_ PNDIS_PACKET _In_ UINT _Out_ PUINT BytesCopied
Definition: ndis.h:3167
VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket)
Definition: receive.c:555
#define IP_ADDRESS_V6
Definition: ip.h:33
UINT Position
Definition: ip.h:87
UCHAR Type
Definition: ip.h:79
unsigned char UCHAR
Definition: xmlstorage.h:181
#define MAX_TRACE
Definition: debug.h:16
UINT CopyPacketToBuffer(PUCHAR DstData, PNDIS_PACKET SrcPacket, UINT SrcOffset, UINT Length)
Definition: buffer.c:170
unsigned int UINT
Definition: ndis.h:50
PNDIS_PACKET NdisPacket
Definition: ip.h:88
#define MIN_TRACE
Definition: debug.h:14

Referenced by LanReceiveWorker(), LoopPassiveWorker(), main(), and RunTest().

◆ IPv4Receive()

VOID IPv4Receive ( PIP_INTERFACE  IF,
PIP_PACKET  IPPacket 
)

Definition at line 555 of file receive.c.

562 {
563  UCHAR FirstByte;
565 
566  TI_DbgPrint(DEBUG_IP, ("Received IPv4 datagram.\n"));
567 
568  /* Read in the first IP header byte for size information */
569  BytesCopied = CopyPacketToBuffer((PCHAR)&FirstByte,
570  IPPacket->NdisPacket,
571  IPPacket->Position,
572  sizeof(UCHAR));
573  if (BytesCopied != sizeof(UCHAR))
574  {
575  TI_DbgPrint(MIN_TRACE, ("Failed to copy in first byte\n"));
576  /* Discard packet */
577  return;
578  }
579 
580  IPPacket->HeaderSize = (FirstByte & 0x0F) << 2;
581  TI_DbgPrint(DEBUG_IP, ("IPPacket->HeaderSize = %d\n", IPPacket->HeaderSize));
582 
583  if (IPPacket->HeaderSize > IPv4_MAX_HEADER_SIZE) {
584  TI_DbgPrint(MIN_TRACE, ("Datagram received with incorrect header size (%d).\n",
585  IPPacket->HeaderSize));
586  /* Discard packet */
587  return;
588  }
589 
590  /* This is freed by IPPacket->Free() */
592  IPPacket->HeaderSize,
594  if (!IPPacket->Header)
595  {
596  TI_DbgPrint(MIN_TRACE, ("No resources to allocate header\n"));
597  /* Discard packet */
598  return;
599  }
600 
601  IPPacket->MappedHeader = FALSE;
602 
604  IPPacket->NdisPacket,
605  IPPacket->Position,
606  IPPacket->HeaderSize);
607  if (BytesCopied != IPPacket->HeaderSize)
608  {
609  TI_DbgPrint(MIN_TRACE, ("Failed to copy in header\n"));
610  /* Discard packet */
611  return;
612  }
613 
614  /* Checksum IPv4 header */
615  if (!IPv4CorrectChecksum(IPPacket->Header, IPPacket->HeaderSize)) {
616  TI_DbgPrint(MIN_TRACE, ("Datagram received with bad checksum. Checksum field (0x%X)\n",
617  WN2H(((PIPv4_HEADER)IPPacket->Header)->Checksum)));
618  /* Discard packet */
619  return;
620  }
621 
622  IPPacket->TotalSize = WN2H(((PIPv4_HEADER)IPPacket->Header)->TotalLength);
623 
624  AddrInitIPv4(&IPPacket->SrcAddr, ((PIPv4_HEADER)IPPacket->Header)->SrcAddr);
625  AddrInitIPv4(&IPPacket->DstAddr, ((PIPv4_HEADER)IPPacket->Header)->DstAddr);
626 
627  TI_DbgPrint(MID_TRACE,("IPPacket->Position = %d\n",
628  IPPacket->Position));
629 
630  /* FIXME: Possibly forward packets with multicast addresses */
631 
632  /* FIXME: Should we allow packets to be received on the wrong interface? */
633  /* XXX Find out if this packet is destined for us */
634  ProcessFragment(IF, IPPacket);
635 }
signed char * PCHAR
Definition: retypes.h:7
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
#define MID_TRACE
Definition: debug.h:15
IP_ADDRESS SrcAddr
Definition: ip.h:89
PVOID Header
Definition: ip.h:83
_In_ UINT _In_ UINT _In_ PNDIS_PACKET _In_ UINT _Out_ PUINT BytesCopied
Definition: ndis.h:3167
#define DEBUG_IP
Definition: debug.h:26
VOID ProcessFragment(PIP_INTERFACE IF, PIP_PACKET IPPacket)
Definition: receive.c:271
#define AddrInitIPv4(IPAddress, RawAddress)
Definition: address.h:16
UINT Position
Definition: ip.h:87
UINT TotalSize
Definition: ip.h:86
#define WN2H(w)
Definition: addrconv.c:35
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned char UCHAR
Definition: xmlstorage.h:181
UINT HeaderSize
Definition: ip.h:84
#define IPv4_MAX_HEADER_SIZE
Definition: ip.h:68
UINT CopyPacketToBuffer(PUCHAR DstData, PNDIS_PACKET SrcPacket, UINT SrcOffset, UINT Length)
Definition: buffer.c:170
PNDIS_PACKET NdisPacket
Definition: ip.h:88
Definition: ip.h:37
BOOLEAN MappedHeader
Definition: ip.h:81
unsigned int ULONG
Definition: retypes.h:1
#define MIN_TRACE
Definition: debug.h:14
IP_ADDRESS DstAddr
Definition: ip.h:90
#define PACKET_BUFFER_TAG
Definition: tags.h:27
#define IPv4CorrectChecksum(Data, Count)
Definition: checksum.h:38

Referenced by IPReceive().

◆ ProcessFragment()

VOID ProcessFragment ( PIP_INTERFACE  IF,
PIP_PACKET  IPPacket 
)

Definition at line 271 of file receive.c.

283 {
284  KIRQL OldIrql;
286  PLIST_ENTRY CurrentEntry;
287  PIPDATAGRAM_HOLE Hole, NewHole;
288  USHORT FragFirst;
289  USHORT FragLast;
290  BOOLEAN MoreFragments;
291  PIPv4_HEADER IPv4Header;
292  IP_PACKET Datagram;
293  PIP_FRAGMENT Fragment;
295 
296  /* FIXME: Assume IPv4 */
297 
298  IPv4Header = (PIPv4_HEADER)IPPacket->Header;
299 
300  /* Check if we already have an reassembly structure for this datagram */
301  IPDR = GetReassemblyInfo(IPPacket);
302  if (IPDR) {
303  TI_DbgPrint(DEBUG_IP, ("Continueing assembly.\n"));
304  /* We have a reassembly structure */
306 
307  /* Reset the timeout since we received a fragment */
308  IPDR->TimeoutCount = 0;
309  } else {
310  TI_DbgPrint(DEBUG_IP, ("Starting new assembly.\n"));
311 
312  /* We don't have a reassembly structure, create one */
313  IPDR = ExAllocateFromNPagedLookasideList(&IPDRList);
314  if (!IPDR)
315  /* We don't have the resources to process this packet, discard it */
316  return;
317 
318  /* Create a descriptor spanning from zero to infinity.
319  Actually, we use a value slightly greater than the
320  maximum number of octets an IP datagram can contain */
321  Hole = CreateHoleDescriptor(0, 65536);
322  if (!Hole) {
323  /* We don't have the resources to process this packet, discard it */
324  ExFreeToNPagedLookasideList(&IPDRList, IPDR);
325  return;
326  }
327  AddrInitIPv4(&IPDR->SrcAddr, IPv4Header->SrcAddr);
328  AddrInitIPv4(&IPDR->DstAddr, IPv4Header->DstAddr);
329  IPDR->Id = IPv4Header->Id;
330  IPDR->Protocol = IPv4Header->Protocol;
331  IPDR->TimeoutCount = 0;
334  InsertTailList(&IPDR->HoleListHead, &Hole->ListEntry);
335 
337 
339 
340  /* Update the reassembly list */
343  &IPDR->ListEntry,
345  }
346 
347  FragFirst = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_FRAGOFS_MASK) << 3;
348  FragLast = FragFirst + WN2H(IPv4Header->TotalLength);
349  MoreFragments = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_MF_MASK) > 0;
350 
351  CurrentEntry = IPDR->HoleListHead.Flink;
352  for (;;) {
353  if (CurrentEntry == &IPDR->HoleListHead)
354  break;
355 
356  Hole = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry);
357 
358  TI_DbgPrint(DEBUG_IP, ("Comparing Fragment (%d,%d) to Hole (%d,%d).\n",
359  FragFirst, FragLast, Hole->First, Hole->Last));
360 
361  if ((FragFirst > Hole->Last) || (FragLast < Hole->First)) {
362  TI_DbgPrint(MID_TRACE, ("No overlap.\n"));
363  /* The fragment does not overlap with the hole, try next
364  descriptor in the list */
365 
366  CurrentEntry = CurrentEntry->Flink;
367  continue;
368  }
369 
370  /* The fragment overlap with the hole, unlink the descriptor */
371  RemoveEntryList(CurrentEntry);
372 
373  if (FragFirst > Hole->First) {
374  NewHole = CreateHoleDescriptor(Hole->First, FragFirst - 1);
375  if (!NewHole) {
376  /* We don't have the resources to process this packet, discard it */
377  ExFreeToNPagedLookasideList(&IPHoleList, Hole);
378  Cleanup(&IPDR->Lock, OldIrql, IPDR);
379  return;
380  }
381 
382  /* Put the new descriptor in the list */
383  InsertTailList(&IPDR->HoleListHead, &NewHole->ListEntry);
384  }
385 
386  if ((FragLast < Hole->Last) && MoreFragments) {
387  NewHole = CreateHoleDescriptor(FragLast + 1, Hole->Last);
388  if (!NewHole) {
389  /* We don't have the resources to process this packet, discard it */
390  ExFreeToNPagedLookasideList(&IPHoleList, Hole);
391  Cleanup(&IPDR->Lock, OldIrql, IPDR);
392  return;
393  }
394 
395  /* Put the new hole descriptor in the list */
396  InsertTailList(&IPDR->HoleListHead, &NewHole->ListEntry);
397  }
398 
399  ExFreeToNPagedLookasideList(&IPHoleList, Hole);
400 
401  /* If this is the first fragment, save the IP header */
402  if (FragFirst == 0) {
404  IPPacket->HeaderSize,
406  if (!IPDR->IPv4Header)
407  {
408  Cleanup(&IPDR->Lock, OldIrql, IPDR);
409  return;
410  }
411 
412  RtlCopyMemory(IPDR->IPv4Header, IPPacket->Header, IPPacket->HeaderSize);
413  IPDR->HeaderSize = IPPacket->HeaderSize;
414 
415  TI_DbgPrint(DEBUG_IP, ("First fragment found. Header buffer is at (0x%X). "
416  "Header size is (%d).\n", &IPDR->IPv4Header, IPPacket->HeaderSize));
417 
418  }
419 
420  /* Create a buffer, copy the data into it and put it
421  in the fragment list */
422 
423  Fragment = ExAllocateFromNPagedLookasideList(&IPFragmentList);
424  if (!Fragment) {
425  /* We don't have the resources to process this packet, discard it */
426  Cleanup(&IPDR->Lock, OldIrql, IPDR);
427  return;
428  }
429 
430  TI_DbgPrint(DEBUG_IP, ("Fragment descriptor allocated at (0x%X).\n", Fragment));
431 
432  Fragment->Size = IPPacket->TotalSize - IPPacket->HeaderSize;
433  Fragment->Packet = IPPacket->NdisPacket;
434  Fragment->ReturnPacket = IPPacket->ReturnPacket;
435  Fragment->PacketOffset = IPPacket->Position + IPPacket->HeaderSize;
436  Fragment->Offset = FragFirst;
437 
438  /* Disassociate the NDIS packet so it isn't freed upon return from IPReceive() */
439  IPPacket->NdisPacket = NULL;
440 
441  /* If this is the last fragment, compute and save the datagram data size */
442  if (!MoreFragments)
443  IPDR->DataSize = FragFirst + Fragment->Size;
444 
445  /* Put the fragment in the list */
446  InsertTailList(&IPDR->FragmentListHead, &Fragment->ListEntry);
447  break;
448  }
449 
450  TI_DbgPrint(DEBUG_IP, ("Done searching for hole descriptor.\n"));
451 
452  if (IsListEmpty(&IPDR->HoleListHead)) {
453  /* Hole list is empty which means a complete datagram can be assembled.
454  Assemble the datagram and pass it to an upper layer protocol */
455 
456  TI_DbgPrint(DEBUG_IP, ("Complete datagram received.\n"));
457 
458  RemoveIPDR(IPDR);
460 
461  /* FIXME: Assumes IPv4 */
462  IPInitializePacket(&Datagram, IP_ADDRESS_V4);
463 
464  Success = ReassembleDatagram(&Datagram, IPDR);
465 
466  FreeIPDR(IPDR);
467 
468  if (!Success)
469  /* Not enough free resources, discard the packet */
470  return;
471 
472  DISPLAY_IP_PACKET(&Datagram);
473 
474  /* Give the packet to the protocol dispatcher */
475  IPDispatchProtocol(IF, &Datagram);
476 
477  /* We're done with this datagram */
478  TI_DbgPrint(MAX_TRACE, ("Freeing datagram at (0x%X).\n", Datagram));
479  Datagram.Free(&Datagram);
480  } else
482 }
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
PIP_HEADER IPv4Header
Definition: receive.h:41
VOID IPDispatchProtocol(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
Definition: ip.c:142
UINT Offset
Definition: receive.h:21
#define DISPLAY_IP_PACKET(x)
Definition: routines.h:69
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define MID_TRACE
Definition: debug.h:15
UINT Size
Definition: receive.h:22
LIST_ENTRY ReassemblyListHead
Definition: receive.c:15
PNDIS_PACKET Packet
Definition: receive.h:18
LIST_ENTRY HoleListHead
Definition: receive.h:44
IP_ADDRESS SrcAddr
Definition: receive.h:37
UINT PacketOffset
Definition: receive.h:20
USHORT TotalLength
Definition: ip.h:40
NPAGED_LOOKASIDE_LIST IPHoleList
Definition: receive.c:19
LIST_ENTRY ListEntry
Definition: receive.h:34
#define InsertTailList(ListHead, Entry)
OBJECT_FREE_ROUTINE Free
Definition: ip.h:78
VOID TcpipReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL Irql)
Definition: lock.c:26
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
VOID TcpipAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL Irql)
Definition: lock.c:18
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
WCHAR First[]
Definition: FormatMessage.c:11
NPAGED_LOOKASIDE_LIST IPFragmentList
Definition: receive.c:18
UCHAR KIRQL
Definition: env_spec_w32.h:591
USHORT FlagsFragOfs
Definition: ip.h:42
#define IP_ADDRESS_V4
Definition: ip.h:32
PIP_PACKET IPInitializePacket(PIP_PACKET IPPacket, ULONG Type)
Definition: ip.c:92
IP_ADDRESS DstAddr
Definition: receive.h:38
PVOID Header
Definition: ip.h:83
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
KSPIN_LOCK ReassemblyListLock
Definition: receive.c:16
#define DEBUG_IP
Definition: debug.h:26
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
LIST_ENTRY ListEntry
Definition: receive.h:27
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID RemoveIPDR(PIPDATAGRAM_REASSEMBLY IPDR)
Definition: receive.c:123
#define AddrInitIPv4(IPAddress, RawAddress)
Definition: address.h:16
#define IPv4_MF_MASK
Definition: ip.h:66
UINT Position
Definition: ip.h:87
UINT TotalSize
Definition: ip.h:86
IPv4_RAW_ADDRESS DstAddr
Definition: ip.h:47
BOOLEAN ReassembleDatagram(PIP_PACKET IPPacket, PIPDATAGRAM_REASSEMBLY IPDR)
Definition: receive.c:185
#define WN2H(w)
Definition: addrconv.c:35
UCHAR Protocol
Definition: ip.h:44
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UINT HeaderSize
Definition: ip.h:84
NPAGED_LOOKASIDE_LIST IPDRList
Definition: receive.c:17
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
VOID TcpipInterlockedInsertTailList(PLIST_ENTRY ListHead, PLIST_ENTRY Item, PKSPIN_LOCK Lock)
Definition: lock.c:34
Definition: typedefs.h:117
PIPDATAGRAM_HOLE CreateHoleDescriptor(ULONG First, ULONG Last)
Definition: receive.c:21
PIPDATAGRAM_REASSEMBLY GetReassemblyInfo(PIP_PACKET IPPacket)
Definition: receive.c:141
#define IPv4_FRAGOFS_MASK
Definition: ip.h:65
VOID FreeIPDR(PIPDATAGRAM_REASSEMBLY IPDR)
Definition: receive.c:53
#define MAX_TRACE
Definition: debug.h:16
IPv4_RAW_ADDRESS SrcAddr
Definition: ip.h:46
unsigned short USHORT
Definition: pedump.c:61
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
VOID TcpipInitializeSpinLock(PKSPIN_LOCK SpinLock)
Definition: lock.c:14
BOOLEAN ReturnPacket
Definition: ip.h:82
PNDIS_PACKET NdisPacket
Definition: ip.h:88
Definition: ip.h:37
BOOLEAN ReturnPacket
Definition: receive.h:19
LIST_ENTRY FragmentListHead
Definition: receive.h:43
Definition: ip.h:77
KSPIN_LOCK Lock
Definition: receive.h:35
LIST_ENTRY ListEntry
Definition: receive.h:17
USHORT Id
Definition: ip.h:41
struct IPv4_HEADER * PIPv4_HEADER
#define PACKET_BUFFER_TAG
Definition: tags.h:27
__inline VOID Cleanup(PKSPIN_LOCK Lock, KIRQL OldIrql, PIPDATAGRAM_REASSEMBLY IPDR)
Definition: receive.c:250

Referenced by IPv4Receive().

◆ ReassembleDatagram()

BOOLEAN ReassembleDatagram ( PIP_PACKET  IPPacket,
PIPDATAGRAM_REASSEMBLY  IPDR 
)

Definition at line 185 of file receive.c.

200 {
201  PLIST_ENTRY CurrentEntry;
202  PIP_FRAGMENT Fragment;
203  PCHAR Data;
204 
205  PAGED_CODE();
206 
207  TI_DbgPrint(DEBUG_IP, ("Reassembling datagram from IPDR at (0x%X).\n", IPDR));
208  TI_DbgPrint(DEBUG_IP, ("IPDR->HeaderSize = %d\n", IPDR->HeaderSize));
209  TI_DbgPrint(DEBUG_IP, ("IPDR->DataSize = %d\n", IPDR->DataSize));
210 
211  IPPacket->TotalSize = IPDR->HeaderSize + IPDR->DataSize;
212  IPPacket->HeaderSize = IPDR->HeaderSize;
213 
214  RtlCopyMemory(&IPPacket->SrcAddr, &IPDR->SrcAddr, sizeof(IP_ADDRESS));
215  RtlCopyMemory(&IPPacket->DstAddr, &IPDR->DstAddr, sizeof(IP_ADDRESS));
216 
217  /* Allocate space for full IP datagram */
219  if (!IPPacket->Header) {
220  TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
221  (*IPPacket->Free)(IPPacket);
222  return FALSE;
223  }
224  IPPacket->MappedHeader = FALSE;
225 
226  /* Copy the header into the buffer */
227  RtlCopyMemory(IPPacket->Header, IPDR->IPv4Header, IPDR->HeaderSize);
228 
229  Data = (PVOID)((ULONG_PTR)IPPacket->Header + IPDR->HeaderSize);
230  IPPacket->Data = Data;
231 
232  /* Copy data from all fragments into buffer */
233  CurrentEntry = IPDR->FragmentListHead.Flink;
234  while (CurrentEntry != &IPDR->FragmentListHead) {
235  Fragment = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry);
236 
237  /* Copy fragment data into datagram buffer */
238  CopyPacketToBuffer(Data + Fragment->Offset,
239  Fragment->Packet,
240  Fragment->PacketOffset,
241  Fragment->Size);
242 
243  CurrentEntry = CurrentEntry->Flink;
244  }
245 
246  return TRUE;
247 }
signed char * PCHAR
Definition: retypes.h:7
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
PIP_HEADER IPv4Header
Definition: receive.h:41
UINT Offset
Definition: receive.h:21
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
UINT Size
Definition: receive.h:22
PNDIS_PACKET Packet
Definition: receive.h:18
IP_ADDRESS SrcAddr
Definition: receive.h:37
IP_ADDRESS SrcAddr
Definition: ip.h:89
UINT PacketOffset
Definition: receive.h:20
OBJECT_FREE_ROUTINE Free
Definition: ip.h:78
#define PAGED_CODE()
Definition: video.h:57
uint32_t ULONG_PTR
Definition: typedefs.h:63
PVOID Data
Definition: ip.h:85
Definition: ip.h:23
IP_ADDRESS DstAddr
Definition: receive.h:38
PVOID Header
Definition: ip.h:83
_In_ LPGUID _In_ PVOID Data
Definition: classpnp.h:778
#define DEBUG_IP
Definition: debug.h:26
void * PVOID
Definition: retypes.h:9
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
UINT TotalSize
Definition: ip.h:86
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UINT HeaderSize
Definition: ip.h:84
Definition: typedefs.h:117
UINT CopyPacketToBuffer(PUCHAR DstData, PNDIS_PACKET SrcPacket, UINT SrcOffset, UINT Length)
Definition: buffer.c:170
LIST_ENTRY FragmentListHead
Definition: receive.h:43
BOOLEAN MappedHeader
Definition: ip.h:81
#define MIN_TRACE
Definition: debug.h:14
IP_ADDRESS DstAddr
Definition: ip.h:90
#define PACKET_BUFFER_TAG
Definition: tags.h:27

Referenced by ProcessFragment().

◆ RemoveIPDR()

VOID RemoveIPDR ( PIPDATAGRAM_REASSEMBLY  IPDR)

Definition at line 123 of file receive.c.

130 {
131  KIRQL OldIrql;
132 
133  TI_DbgPrint(DEBUG_IP, ("Removing IPDR at (0x%X).\n", IPDR));
134 
136  RemoveEntryList(&IPDR->ListEntry);
138 }
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
LIST_ENTRY ListEntry
Definition: receive.h:34
VOID TcpipReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL Irql)
Definition: lock.c:26
VOID TcpipAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL Irql)
Definition: lock.c:18
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
UCHAR KIRQL
Definition: env_spec_w32.h:591
KSPIN_LOCK ReassemblyListLock
Definition: receive.c:16
#define DEBUG_IP
Definition: debug.h:26
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803

Referenced by Cleanup(), and ProcessFragment().

Variable Documentation

◆ IPDRList

Definition at line 17 of file receive.c.

Referenced by FreeIPDR(), IPShutdown(), IPStartup(), and ProcessFragment().

◆ IPFragmentList

NPAGED_LOOKASIDE_LIST IPFragmentList

Definition at line 18 of file receive.c.

Referenced by FreeIPDR(), IPShutdown(), IPStartup(), and ProcessFragment().

◆ IPHoleList

Definition at line 19 of file receive.c.

Referenced by CreateHoleDescriptor(), FreeIPDR(), IPShutdown(), IPStartup(), and ProcessFragment().

◆ ReassemblyListHead

◆ ReassemblyListLock