- 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.

svn path=/trunk/; revision=54169
This commit is contained in:
Cameron Gutman 2011-10-17 00:38:46 +00:00
parent 9e9b67bc8f
commit fa391315db
2 changed files with 25 additions and 34 deletions

View file

@ -25,8 +25,8 @@ typedef struct IPFRAGMENT_CONTEXT {
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;

View file

@ -28,30 +28,14 @@ VOID IPSendComplete
*/
{
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 @@ NTSTATUS SendFragments(
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,20 +194,28 @@ NTSTATUS SendFragments(
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;
}
if (!NT_SUCCESS((NdisStatus = IPSendFragment(IFC->NdisPacket, NCE, IFC))))
while (PrepareNextFragment(IFC))
{
FreeNdisPacket(IFC->NdisPacket);
ExFreePoolWithTag(IFC, IFC_TAG);
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;
}
FreeNdisPacket(IFC->NdisPacket);
ExFreePoolWithTag(IFC, IFC_TAG);
Complete(Context, IPPacket->NdisPacket, NdisStatus);
return NdisStatus;
}