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/tcpip/address.c?rev=65376&r1=65375&r2=65376&view=diff
==============================================================================
--- 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/tcpip/precomp.h?rev=65376&r1=65375&r2=65376&view=diff
==============================================================================
--- 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>
 


Reply via email to