Author: cgutman
Date: Mon Oct 17 00:38:46 2011
New Revision: 54169
URL:
http://svn.reactos.org/svn/reactos?rev=54169&view=rev
Log:
[TCPIP]
- Do not transmit fragments recursively since it can cause a kernel stack overflow with
large packets
- Big thanks to hto for his work on this bug which has eluded me since last year
See issue #5796 for more details.
Modified:
trunk/reactos/drivers/network/tcpip/include/transmit.h
trunk/reactos/lib/drivers/ip/network/transmit.c
Modified: trunk/reactos/drivers/network/tcpip/include/transmit.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/incl…
==============================================================================
--- trunk/reactos/drivers/network/tcpip/include/transmit.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/tcpip/include/transmit.h [iso-8859-1] Mon Oct 17
00:38:46 2011
@@ -25,8 +25,8 @@
UINT BytesLeft; /* Number of bytes left to send */
UINT PathMTU; /* Path Maximum Transmission Unit */
PNEIGHBOR_CACHE_ENTRY NCE; /* Pointer to NCE to use */
- PIP_TRANSMIT_COMPLETE Complete; /* Completion Routine */
- PVOID Context; /* Completion Context */
+ KEVENT Event; /* Signalled when the transmission is complete
*/
+ NDIS_STATUS Status; /* Status of the transmission */
} IPFRAGMENT_CONTEXT, *PIPFRAGMENT_CONTEXT;
Modified: trunk/reactos/lib/drivers/ip/network/transmit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/network/tra…
==============================================================================
--- trunk/reactos/lib/drivers/ip/network/transmit.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/ip/network/transmit.c [iso-8859-1] Mon Oct 17 00:38:46 2011
@@ -28,30 +28,14 @@
*/
{
PIPFRAGMENT_CONTEXT IFC = (PIPFRAGMENT_CONTEXT)Context;
- NTSTATUS Status;
TI_DbgPrint
(MAX_TRACE,
("Called. Context (0x%X) NdisPacket (0x%X) NdisStatus (0x%X)\n",
Context, NdisPacket, NdisStatus));
-
- if (NT_SUCCESS(NdisStatus) && PrepareNextFragment(IFC)) {
- /* A fragment was prepared for transmission, so send it */
- Status = IPSendFragment(IFC->NdisPacket, IFC->NCE, IFC);
- if (!NT_SUCCESS(Status))
- {
- FreeNdisPacket(IFC->NdisPacket);
- IFC->Complete(IFC->Context, IFC->Datagram, Status);
- ExFreePoolWithTag(IFC, IFC_TAG);
- }
- } else {
- TI_DbgPrint(MAX_TRACE, ("Calling completion handler.\n"));
-
- /* There are no more fragments to transmit, so call completion handler */
- FreeNdisPacket(IFC->NdisPacket);
- IFC->Complete(IFC->Context, IFC->Datagram, NdisStatus);
- ExFreePoolWithTag(IFC, IFC_TAG);
- }
+
+ IFC->Status = NdisStatus;
+ KeSetEvent(&IFC->Event, 0, FALSE);
}
NTSTATUS IPSendFragment(
@@ -202,8 +186,7 @@
IFC->Position = 0;
IFC->BytesLeft = IPPacket->TotalSize - IPPacket->HeaderSize;
IFC->Data = (PVOID)((ULONG_PTR)IFC->Header + IPPacket->HeaderSize);
- IFC->Complete = Complete;
- IFC->Context = Context;
+ KeInitializeEvent(&IFC->Event, NotificationEvent, FALSE);
TI_DbgPrint(MID_TRACE,("Copying header from %x to %x (%d)\n",
IPPacket->Header, IFC->Header,
@@ -211,19 +194,27 @@
RtlCopyMemory( IFC->Header, IPPacket->Header, IPPacket->HeaderSize );
- /* Prepare next fragment for transmission and send it */
-
- if (!PrepareNextFragment(IFC)) {
- FreeNdisPacket(IFC->NdisPacket);
- ExFreePoolWithTag(IFC, IFC_TAG);
- return NDIS_STATUS_FAILURE;
+ while (PrepareNextFragment(IFC))
+ {
+ NdisStatus = IPSendFragment(IFC->NdisPacket, NCE, IFC);
+ if (NT_SUCCESS(NdisStatus))
+ {
+ KeWaitForSingleObject(&IFC->Event,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ NdisStatus = IFC->Status;
+ }
+
+ if (!NT_SUCCESS(NdisStatus))
+ break;
}
- if (!NT_SUCCESS((NdisStatus = IPSendFragment(IFC->NdisPacket, NCE, IFC))))
- {
- FreeNdisPacket(IFC->NdisPacket);
- ExFreePoolWithTag(IFC, IFC_TAG);
- }
+ FreeNdisPacket(IFC->NdisPacket);
+ ExFreePoolWithTag(IFC, IFC_TAG);
+
+ Complete(Context, IPPacket->NdisPacket, NdisStatus);
return NdisStatus;
}