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/network... ============================================================================== --- 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/network... ============================================================================== --- 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>