Index: /trunk/src/VBox/Devices/Network/slirp/socket.c
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/socket.c	(revision 27398)
+++ /trunk/src/VBox/Devices/Network/slirp/socket.c	(revision 27399)
@@ -1053,4 +1053,5 @@
     uint8_t proto;
     int type = 0;
+    int m_room;
 
     ip = (struct ip *)buff;
@@ -1105,5 +1106,13 @@
     original_hlen = ip->ip_hl << 2;
     /* saves original ip header and options */
-    memcpy(m->m_data + original_hlen, buff + hlen, len - hlen);
+    /* m_room space in the saved m buffer */
+    m_room = m->m_len + M_TRAILINGSPACE(m) - original_hlen;
+    if (m_room >= len - hlen)
+        memcpy(m->m_data + original_hlen, buff + hlen, len - hlen);
+    else 
+    {
+        m_inc(m, len); /*increase the room of the mbuf up to len*/
+        memcpy(m->m_data + original_hlen, buff + hlen, len - hlen);
+    }
 #ifndef VBOX_WITH_SLIRP_BSD_MBUF
     m->m_len = len - hlen + original_hlen;
@@ -1271,11 +1280,12 @@
     struct sockaddr_in addr;
     socklen_t addrlen = sizeof(struct sockaddr_in);
+    struct ip ip;
     char *buff;
     int len = 0;
-    int rc = 0;
-    static int signalled = 0;
-
-    rc = ioctlsocket(so->s, FIONREAD, &len);
-    if (   rc == -1
+
+    /* 1- step: read the ip header */
+    len = recvfrom(so->s, &ip, sizeof(struct ip), MSG_PEEK,
+                   (struct sockaddr *)&addr, &addrlen);
+    if (   len < 0
         && (   errno == EAGAIN
             || errno == EWOULDBLOCK
@@ -1283,30 +1293,13 @@
             || errno == ENOTCONN))
     {
+        Log(("sorecvfrom_icmp_unix: 1 - step can't read IP datagramm (would block)\n"));
         return;
     }
-    if (rc == -1 && signalled == 0)
-    {
-        signalled = 1;
-        LogRel(("NAT: fetching number of bits has been failed for ICMP socket (%d: %s)\n",
-            errno, strerror(errno)));
-        return;
-    }
-    len = (len != 0 && rc != -1 ? len : 1500);
-    buff = RTMemAlloc(len);
-    len = recvfrom(so->s, buff, len, 0,
-                   (struct sockaddr *)&addr, &addrlen);
-    /* XXX Check if reply is "correct"? */
-
-    if (len == -1 || len == 0)
+
+    if (   len < sizeof(struct ip)
+        || len < 0
+        || len == 0)
     {
         u_char code;
-        if (   len == -1
-            && (errno == EAGAIN
-            || errno == EWOULDBLOCK
-            || errno == EINPROGRESS
-            || errno == ENOTCONN))
-        {
-            return;
-        }
         code = ICMP_UNREACH_PORT;
 
@@ -1320,9 +1313,49 @@
         icmp_error(pData, so->so_m, ICMP_UNREACH, code, 0, strerror(errno));
         so->so_m = NULL;
-    }
-    else
-    {
-        send_icmp_to_guest(pData, buff, len, so, &addr);
-    }
+        Log(("sorecvfrom_icmp_unix: 1 - step can't read IP datagramm \n"));
+        return;
+    }
+    /* basic check of IP header */
+    if (   ip.ip_v != IPVERSION
+        || ip.ip_p != IPPROTO_ICMP)
+    {
+        Log(("sorecvfrom_icmp_unix: 1 - step IP isn't IPv4 \n"));
+        return;
+    }
+
+    len = RT_N2H_U16(ip.ip_len);
+    buff = RTMemAlloc(len);
+    if (buff == NULL)
+    {
+        Log(("sorecvfrom_icmp_unix: 1 - step can't allocate enought room for datagram\n"));
+        return;
+    }
+    /* 2 - step: we're reading rest of the datagramm to the buffer */
+    addrlen = sizeof(struct sockaddr_in);
+    memset(&addr, 0, addrlen);
+    len = recvfrom(so->s, buff, len, 0,
+                   (struct sockaddr *)&addr, &addrlen);
+    if (   len < 0
+        && (   errno == EAGAIN
+            || errno == EWOULDBLOCK
+            || errno == EINPROGRESS
+            || errno == ENOTCONN))
+    {
+        Log(("sorecvfrom_icmp_unix: 2 - step can't read IP body (would block expected:%d)\n", 
+            RT_N2H_U16(ip.ip_len)));
+        RTMemFree(buff);
+        return;
+    }
+    if (   len < 0 
+        || len < (RT_N2H_U16(ip.ip_len))
+        || len == 0)
+    {
+        Log(("sorecvfrom_icmp_unix: 2 - step read of the rest of datagramm is fallen (errno:%d, len:%d expected: %d)\n",
+             errno, len, (RT_N2H_U16(ip.ip_len) - sizeof(struct ip))));
+        RTMemFree(buff);
+        return;
+    }
+    /* len is modified in 2nd read, when the rest of the datagramm was read */
+    send_icmp_to_guest(pData, buff, len, so, &addr);
     RTMemFree(buff);
 }
