Author: jgardou
Date: Tue Nov 11 10:41:23 2014
New Revision: 65376
URL:
http://svn.reactos.org/svn/reactos?rev=65376&view=rev
Log:
[TCPIP]
- Properly return STATUS_BUFFER_OVERFLOW if the provided buffer is too small when
receiving a datagram.
- Do not skip the IP header for raw IP packets (application do in fact require it)
- Only pass ICMP echo reply packets to callers, the rest is processed by lwip.
'ping 127.0.0.1' now properly works.
Modified:
branches/tcpip_revolution/drivers/network/tcpip/address.c
branches/tcpip_revolution/drivers/network/tcpip/precomp.h
Modified: branches/tcpip_revolution/drivers/network/tcpip/address.c
URL:
http://svn.reactos.org/svn/reactos/branches/tcpip_revolution/drivers/networ…
==============================================================================
--- branches/tcpip_revolution/drivers/network/tcpip/address.c [iso-8859-1] (original)
+++ branches/tcpip_revolution/drivers/network/tcpip/address.c [iso-8859-1] Tue Nov 11
10:41:23 2014
@@ -48,13 +48,15 @@
ADDRESS_FILE* AddressFile,
struct pbuf *p,
ip_addr_t *addr,
- u16_t port,
- BOOLEAN MustFree)
+ u16_t port)
{
KIRQL OldIrql;
LIST_ENTRY* ListEntry;
RECEIVE_DATAGRAM_REQUEST* Request;
ip_addr_t RequestAddr;
+ BOOLEAN Result = FALSE;
+
+ NT_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
DPRINT1("Receiving datagram for addr 0x%08x on port %u.\n",
ip4_addr_get_u32(addr), port);
@@ -84,6 +86,7 @@
/* We found a request for this one */
IoSetCancelRoutine(Irp, NULL);
RemoveEntryList(&Request->ListEntry);
+ Result = TRUE;
KeReleaseSpinLockFromDpcLevel(&AddressFile->RequestLock);
IoReleaseCancelSpinLock(OldIrql);
@@ -94,7 +97,7 @@
p,
Request->Buffer,
Request->BufferLength,
- AddressFile->Protocol == IPPROTO_UDP ? 0 : IP_HLEN);
+ 0);
ReturnAddress = Request->ReturnInfo->RemoteAddress;
ReturnAddress->Address->AddressLength = TDI_ADDRESS_LENGTH_IP;
ReturnAddress->Address->AddressType = TDI_ADDRESS_TYPE_IP;
@@ -103,22 +106,24 @@
RtlZeroMemory(ReturnAddress->Address->Address->sin_zero,
sizeof(ReturnAddress->Address->Address->sin_zero));
- Irp->IoStatus.Status = STATUS_SUCCESS;
+ if (Request->BufferLength < p->tot_len)
+ Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
+ else
+ Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
ExFreePoolWithTag(Request, TAG_ADDRESS_FILE);
- pbuf_free(p);
-
- return TRUE;
+
+ /* Start again from the beginning */
+ IoAcquireCancelSpinLock(&OldIrql);
+ KeAcquireSpinLockAtDpcLevel(&AddressFile->RequestLock);
}
}
KeReleaseSpinLockFromDpcLevel(&AddressFile->RequestLock);
IoReleaseCancelSpinLock(OldIrql);
- if (MustFree)
- pbuf_free(p);
-
- return FALSE;
+
+ return Result;
}
static
@@ -132,7 +137,8 @@
{
UNREFERENCED_PARAMETER(pcb);
- ReceiveDatagram(arg, p, addr, port, TRUE);
+ ReceiveDatagram(arg, p, addr, port);
+ pbuf_free(p);
}
static
@@ -143,9 +149,41 @@
struct pbuf *p,
ip_addr_t *addr)
{
+ BOOLEAN Result;
+ ADDRESS_FILE* AddressFile = arg;
+
UNREFERENCED_PARAMETER(pcb);
- return ReceiveDatagram(arg, p, addr, 0, FALSE);
+ /* If this is for ICMP, only process the "echo received" packets.
+ * The rest is processed by lwip. */
+ if (AddressFile->Protocol == IPPROTO_ICMP)
+ {
+ /* See icmp_input */
+ s16_t hlen;
+ struct ip_hdr *iphdr;
+
+ iphdr = (struct ip_hdr *)p->payload;
+ hlen = IPH_HL(iphdr) * 4;
+
+ /* Adjust the pbuf to skip the IP header */
+ if (pbuf_header(p, -hlen))
+ return FALSE;
+
+ if (*((u8_t*)p->payload) != ICMP_ER)
+ {
+ pbuf_header(p, hlen);
+ return FALSE;
+ }
+
+ pbuf_header(p, hlen);
+ }
+
+ Result = ReceiveDatagram(arg, p, addr, 0);
+
+ if (Result)
+ pbuf_free(p);
+
+ return Result;
}
NTSTATUS
@@ -246,7 +284,7 @@
KeInitializeSpinLock(&AddressFile->RequestLock);
InitializeListHead(&AddressFile->RequestListHead);
- /* Give it an entity ID and open a PCB is needed. */
+ /* Give it an entity ID and open a PCB if needed. */
switch (Protocol)
{
case IPPROTO_TCP:
@@ -314,11 +352,18 @@
return STATUS_SUCCESS;
}
+ /* remove the lwip pcb */
+ if (AddressFile->Protocol == IPPROTO_UDP)
+ udp_remove(AddressFile->lwip_udp_pcb);
+ else if (AddressFile->Protocol != IPPROTO_TCP)
+ raw_remove(AddressFile->lwip_raw_pcb);
+
/* Remove from the list and free the structure */
RemoveEntryList(&AddressFile->ListEntry);
KeReleaseSpinLock(&AddressListLock, OldIrql);
RemoveEntityInstance(&AddressFile->Instance);
+
ExFreePoolWithTag(AddressFile, TAG_ADDRESS_FILE);
@@ -363,8 +408,8 @@
PIO_STACK_LOCATION IrpSp;
ADDRESS_FILE* AddressFile;
RECEIVE_DATAGRAM_REQUEST* Request;
+ LIST_ENTRY* ListEntry;
KIRQL OldIrql;
- LIST_ENTRY* ListEntry;
IoReleaseCancelSpinLock(Irp->CancelIrql);
@@ -448,6 +493,9 @@
if (!NT_SUCCESS(Status))
goto Failure;
}
+
+ DPRINT1("Queuing datagram receive on address 0x%08x, port %u.\n",
+ Request->RemoteAddress.in_addr, Request->RemoteAddress.sin_port);
/* Get the buffer */
Request->Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
@@ -535,6 +583,8 @@
Port = 0;
}
+ DPRINT1("Sending datagram to address 0x%08x, port %u\n",
ip4_addr_get_u32(&IpAddr), Port);
+
/* Get the buffer */
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
BufferLength = MmGetMdlByteCount(Irp->MdlAddress);
Modified: branches/tcpip_revolution/drivers/network/tcpip/precomp.h
URL:
http://svn.reactos.org/svn/reactos/branches/tcpip_revolution/drivers/networ…
==============================================================================
--- branches/tcpip_revolution/drivers/network/tcpip/precomp.h [iso-8859-1] (original)
+++ branches/tcpip_revolution/drivers/network/tcpip/precomp.h [iso-8859-1] Tue Nov 11
10:41:23 2014
@@ -18,10 +18,11 @@
#include <pseh/pseh2.h>
+#include <lwip/icmp.h>
#include <lwip/ip.h>
+#include <lwip/raw.h>
+#include <lwip/snmp.h>
#include <lwip/tcpip.h>
-#include <lwip/snmp.h>
-#include <lwip/raw.h>
#include <lwip/udp.h>
#include <netif/etharp.h>