ReactOS 0.4.15-dev-8100-g1887773
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)
 
static 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()

static VOID Cleanup ( PKSPIN_LOCK  Lock,
KIRQL  OldIrql,
PIPDATAGRAM_REASSEMBLY  IPDR 
)
inlinestatic

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 MIN_TRACE
Definition: debug.h:14
#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
VOID FreeIPDR(PIPDATAGRAM_REASSEMBLY IPDR)
Definition: receive.c:53
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

◆ CreateHoleDescriptor()

PIPDATAGRAM_HOLE CreateHoleDescriptor ( ULONG  First,
ULONG  Last 
)

Definition at line 21 of file receive.c.

33{
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}
WCHAR First[]
Definition: FormatMessage.c:11
#define NULL
Definition: types.h:112
#define DEBUG_IP
Definition: debug.h:26
NPAGED_LOOKASIDE_LIST IPHoleList
Definition: receive.c:19

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 PACKET_BUFFER_TAG
Definition: tags.h:27
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define FreeNdisPacket(x)
Definition: memtrack.h:8
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
VOID EXPORT NdisReturnPackets(IN PNDIS_PACKET *PacketsToReturn, IN UINT NumberOfPackets)
Definition: miniport.c:258
NPAGED_LOOKASIDE_LIST IPDRList
Definition: receive.c:17
NPAGED_LOOKASIDE_LIST IPFragmentList
Definition: receive.c:18
PIP_HEADER IPv4Header
Definition: receive.h:41
LIST_ENTRY FragmentListHead
Definition: receive.h:43
LIST_ENTRY HoleListHead
Definition: receive.h:44
PNDIS_PACKET Packet
Definition: receive.h:18
BOOLEAN ReturnPacket
Definition: receive.h:19
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

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

◆ GetReassemblyInfo()

PIPDATAGRAM_REASSEMBLY GetReassemblyInfo ( PIP_PACKET  IPPacket)

Definition at line 141 of file receive.c.

152{
154 PLIST_ENTRY CurrentEntry;
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}
BOOLEAN AddrIsEqual(PIP_ADDRESS Address1, PIP_ADDRESS Address2)
Definition: address.c:221
Definition: Header.h:9
VOID TcpipAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL Irql)
Definition: lock.c:18
UCHAR KIRQL
Definition: env_spec_w32.h:591
struct IPv4_HEADER * PIPv4_HEADER
LIST_ENTRY ReassemblyListHead
Definition: receive.c:15
KSPIN_LOCK ReassemblyListLock
Definition: receive.c:16
IP_ADDRESS SrcAddr
Definition: receive.h:37
IP_ADDRESS DstAddr
Definition: receive.h:38
IP_ADDRESS SrcAddr
Definition: ip.h:89
PVOID Header
Definition: ip.h:83
IP_ADDRESS DstAddr
Definition: ip.h:90

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
536
537 if (++CurrentIPDR->TimeoutCount == MAX_TIMEOUT_COUNT)
538 {
540 RemoveEntryList(CurrentEntry);
541 FreeIPDR(CurrentIPDR);
542 }
543 else
544 {
545 ASSERT(CurrentIPDR->TimeoutCount < MAX_TIMEOUT_COUNT);
547 }
548
549 CurrentEntry = NextEntry;
550 }
551
553}
VOID TcpipAcquireSpinLockAtDpcLevel(PKSPIN_LOCK SpinLock)
Definition: lock.c:22
VOID TcpipReleaseSpinLockFromDpcLevel(PKSPIN_LOCK SpinLock)
Definition: lock.c:30
#define ASSERT(a)
Definition: mode.c:44
#define MAX_TIMEOUT_COUNT
Definition: receive.h:13
KSPIN_LOCK Lock
Definition: receive.h:35

Referenced by IPTimeoutDpcFn().

◆ IPFreeReassemblyList()

VOID IPFreeReassemblyList ( VOID  )

Definition at line 485 of file receive.c.

490{
492 PLIST_ENTRY CurrentEntry, NextEntry;
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}

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 */
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}
#define MAX_TRACE
Definition: debug.h:16
UINT CopyPacketToBuffer(PUCHAR DstData, PNDIS_PACKET SrcPacket, UINT SrcOffset, UINT Length)
Definition: buffer.c:172
#define IP_ADDRESS_V6
Definition: ip.h:33
#define IP_ADDRESS_V4
Definition: ip.h:32
unsigned int UINT
Definition: ndis.h:50
_In_ UINT _In_ UINT _In_ PNDIS_PACKET _In_ UINT _Out_ PUINT BytesCopied
Definition: ndis.h:3171
VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket)
Definition: receive.c:555
OBJECT_FREE_ROUTINE Free
Definition: ip.h:78
UCHAR Type
Definition: ip.h:79
UINT Position
Definition: ip.h:87
PNDIS_PACKET NdisPacket
Definition: ip.h:88
char * PCHAR
Definition: typedefs.h:51
_Must_inspect_result_ _In_ WDFDEVICE _In_ LPCGUID _Out_ PINTERFACE _In_ USHORT _In_ USHORT Version
Definition: wdffdo.h:469
unsigned char UCHAR
Definition: xmlstorage.h:181

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

◆ 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 */
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}
#define WN2H(w)
Definition: addrconv.c:35
#define AddrInitIPv4(IPAddress, RawAddress)
Definition: address.h:16
#define MID_TRACE
Definition: debug.h:15
#define IPv4CorrectChecksum(Data, Count)
Definition: checksum.h:38
#define FALSE
Definition: types.h:117
#define IPv4_MAX_HEADER_SIZE
Definition: ip.h:68
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
VOID ProcessFragment(PIP_INTERFACE IF, PIP_PACKET IPPacket)
Definition: receive.c:271
BOOLEAN MappedHeader
Definition: ip.h:81
UINT HeaderSize
Definition: ip.h:84
UINT TotalSize
Definition: ip.h:86
uint32_t ULONG
Definition: typedefs.h:59

Referenced by IPReceive().

◆ ProcessFragment()

VOID ProcessFragment ( PIP_INTERFACE  IF,
PIP_PACKET  IPPacket 
)

Definition at line 271 of file receive.c.

283{
286 PLIST_ENTRY CurrentEntry;
287 PIPDATAGRAM_HOLE Hole, NewHole;
288 USHORT FragFirst;
289 USHORT FragLast;
290 BOOLEAN MoreFragments;
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 */
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}
unsigned char BOOLEAN
static const WCHAR Cleanup[]
Definition: register.c:80
#define IPv4_MF_MASK
Definition: ip.h:66
#define IPv4_FRAGOFS_MASK
Definition: ip.h:65
VOID IPDispatchProtocol(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
Definition: ip.c:142
PIP_PACKET IPInitializePacket(PIP_PACKET IPPacket, ULONG Type)
Definition: ip.c:92
VOID TcpipInterlockedInsertTailList(PLIST_ENTRY ListHead, PLIST_ENTRY Item, PKSPIN_LOCK Lock)
Definition: lock.c:34
VOID TcpipInitializeSpinLock(PKSPIN_LOCK SpinLock)
Definition: lock.c:14
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
struct _tagIPv4Header IPv4Header
@ Success
Definition: eventcreate.c:712
unsigned short USHORT
Definition: pedump.c:61
BOOLEAN ReassembleDatagram(PIP_PACKET IPPacket, PIPDATAGRAM_REASSEMBLY IPDR)
Definition: receive.c:185
PIPDATAGRAM_REASSEMBLY GetReassemblyInfo(PIP_PACKET IPPacket)
Definition: receive.c:141
PIPDATAGRAM_HOLE CreateHoleDescriptor(ULONG First, ULONG Last)
Definition: receive.c:21
#define DISPLAY_IP_PACKET(x)
Definition: routines.h:69
LIST_ENTRY ListEntry
Definition: receive.h:27
LIST_ENTRY ListEntry
Definition: receive.h:34
LIST_ENTRY ListEntry
Definition: receive.h:17
UINT Size
Definition: receive.h:22
UINT Offset
Definition: receive.h:21
UINT PacketOffset
Definition: receive.h:20
Definition: ip.h:77
BOOLEAN ReturnPacket
Definition: ip.h:82
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263

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}
#define PAGED_CODE()
#define TRUE
Definition: types.h:120
Definition: ip.h:23
PVOID Data
Definition: ip.h:85
void * PVOID
Definition: typedefs.h:50
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by ProcessFragment().

◆ RemoveIPDR()

VOID RemoveIPDR ( PIPDATAGRAM_REASSEMBLY  IPDR)

Definition at line 123 of file receive.c.

130{
132
133 TI_DbgPrint(DEBUG_IP, ("Removing IPDR at (0x%X).\n", IPDR));
134
138}

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