Index: trunk/src/VBox/Devices/Network/DrvNAT.cpp
===================================================================
--- trunk/src/VBox/Devices/Network/DrvNAT.cpp	(revision 15889)
+++ trunk/src/VBox/Devices/Network/DrvNAT.cpp	(revision 15890)
@@ -102,7 +102,8 @@
     PDMQUEUEITEMCORE    Core;
     /** The buffer for output to guest. */
-    const uint8_t            *pu8Buf;
+    const uint8_t       *pu8Buf;
     /* size of buffer */
-    size_t             cb;
+    size_t              cb;
+    void                *mbuf;
 } DRVNATQUEUITEM, *PDRVNATQUEUITEM;
 
@@ -452,5 +453,9 @@
  * Function called by slirp to feed incoming data to the network port.
  */
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
+void slirp_output(void *pvUser, void *pvArg, const uint8_t *pu8Buf, int cb)
+#else
 void slirp_output(void *pvUser, const uint8_t *pu8Buf, int cb)
+#endif
 {
     PDRVNAT pThis = (PDRVNAT)pvUser;
@@ -476,4 +481,5 @@
         pItem->pu8Buf = pu8Buf;
         pItem->cb = cb;
+        pItem->mbuf = pvArg;
         Log2(("pItem:%p %.Rhxd\n", pItem, pItem->pu8Buf));
         PDMQueueInsert(pThis->pSendQueue, &pItem->Core);
@@ -496,4 +502,5 @@
     PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
     PDRVNATQUEUITEM pItem = (PDRVNATQUEUITEM)pItemCore;
+    PRTREQ pReq = NULL;
     Log(("drvNATQueueConsumer(pItem:%p, pu8Buf:%p, cb:%d)\n", pItem, pItem->pu8Buf, pItem->cb));
     Log2(("drvNATQueueConsumer: pu8Buf:\n%.Rhxd\n", pItem->pu8Buf));
@@ -502,6 +509,13 @@
         return false;
     rc = pThis->pPort->pfnReceive(pThis->pPort, pItem->pu8Buf, pItem->cb);
+
+    rc = RTReqAlloc(pThis->pReqQueue, &pReq, RTREQTYPE_INTERNAL);
+    AssertReleaseRC(rc);
+    pReq->u.Internal.pfn      = (PFNRT)slirp_post_sent;
+    pReq->u.Internal.cArgs    = 2;
+    pReq->u.Internal.aArgs[0] = (uintptr_t)pThis->pNATState;
+    pReq->u.Internal.aArgs[1] = (uintptr_t)pItem->mbuf;
+    pReq->fFlags              = RTREQFLAGS_VOID;
     AssertRC(rc);
-    RTMemFree((void *)pItem->pu8Buf); /* XXX: shouldn't free buffer here */
     return RT_SUCCESS(rc);
 }
Index: trunk/src/VBox/Devices/Network/slirp/bootp.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/bootp.c	(revision 15889)
+++ trunk/src/VBox/Devices/Network/slirp/bootp.c	(revision 15890)
@@ -166,8 +166,10 @@
     if ((m = m_get(pData)) == NULL)
         return;
-    m->m_data += if_maxlinkhdr;
-    rbp = (struct bootp_t *)m->m_data;
+    m->m_data += if_maxlinkhdr; /*reserve ether header */
+    rbp = mtod(m, struct bootp_t *);
+    memset(rbp, 0, sizeof(struct bootp_t));
+#ifndef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
     m->m_data += sizeof(struct udpiphdr);
-    memset(rbp, 0, sizeof(struct bootp_t));
+#endif
 
     if (dhcp_msg_type == DHCPDISCOVER)
@@ -310,4 +312,8 @@
              - sizeof(struct ip)
              - sizeof(struct udphdr);
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
+    m->m_data += sizeof(struct udphdr)
+             + sizeof(struct ip);
+#endif
     /* Reply to the broadcast address, as some clients perform paranoid checks. */
     daddr.sin_addr.s_addr = INADDR_BROADCAST;
Index: trunk/src/VBox/Devices/Network/slirp/if.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/if.c	(revision 15889)
+++ trunk/src/VBox/Devices/Network/slirp/if.c	(revision 15890)
@@ -28,6 +28,11 @@
 if_init(PNATState pData)
 {
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
+    /* 14 for ethernet */
+    if_maxlinkhdr =  14;
+#else
     /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
-    if_maxlinkhdr = 2 + 14 + 40;
+    if_maxlinkhdr =  2 + 14 + 40;
+#endif
     if_queued = 0;
     if_thresh = 10;
@@ -224,8 +229,10 @@
         }
 
-        /* Encapsulate the packet for sending */
-        if_encap(pData, ETH_P_IP, (const uint8_t *)ifm->m_data, ifm->m_len);
-
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
+        if_encap(pData, ETH_P_IP, ifm);
+#else
+        if_encap(pData,  mtod(ifm, uint8_t *), ifm->m_len);
         m_free(pData, ifm);
+#endif
 
         if (!if_queued)
Index: trunk/src/VBox/Devices/Network/slirp/ip_icmp.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/ip_icmp.c	(revision 15889)
+++ trunk/src/VBox/Devices/Network/slirp/ip_icmp.c	(revision 15890)
@@ -521,4 +521,5 @@
     {
         int new_m_size;
+        m->m_data += if_maxlinkhdr;
         new_m_size = sizeof(struct ip) + ICMP_MINLEN + msrc->m_len + ICMP_MAXDATALEN;
         if (new_m_size>m->m_size)
Index: trunk/src/VBox/Devices/Network/slirp/libslirp.h
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/libslirp.h	(revision 15889)
+++ trunk/src/VBox/Devices/Network/slirp/libslirp.h	(revision 15890)
@@ -47,5 +47,10 @@
 /* you must provide the following functions: */
 int slirp_can_output(void * pvUser);
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
+void slirp_output(void * pvUser, void *pvArg, const uint8_t *pkt, int pkt_len);
+void slirp_post_sent(PNATState pData, void *pvArg);
+#else
 void slirp_output(void * pvUser, const uint8_t *pkt, int pkt_len);
+#endif
 
 int slirp_redir(PNATState pData, int is_udp, int host_port,
Index: trunk/src/VBox/Devices/Network/slirp/main.h
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/main.h	(revision 15889)
+++ trunk/src/VBox/Devices/Network/slirp/main.h	(revision 15890)
@@ -10,3 +10,7 @@
 #endif
 
-void if_encap(PNATState pData, uint16_t eth_proto, const uint8_t *ip_data, int ip_data_len);
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
+void if_encap(PNATState pData, uint16_t eth_proto, struct mbuf *m);
+#else
+void if_encap(PNATState pData, const uint8_t *ip_data, int ip_data_len);
+#endif
Index: trunk/src/VBox/Devices/Network/slirp/slirp.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 15889)
+++ trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 15890)
@@ -33,9 +33,13 @@
 # define DO_WIN_CHECK_FD_SET(so, events, fdset ) 0 /* specific for Windows Winsock API */
 
-# define ICMP_ENGAGE_EVENT(so, fdset)               \
+# ifndef RT_OS_WINDOWS
+#  define ICMP_ENGAGE_EVENT(so, fdset)               \
     do {                                             \
         if (pData->icmp_socket.s != -1)              \
             DO_ENGAGE_EVENT1((so), (fdset), ICMP);   \
     } while (0)
+# else /* !RT_OS_WINDOWS */
+#  define ICMP_ENGAGE_EVENT(so, fdset) do {} while(0)
+#endif /* RT_OS_WINDOWS */
 
 #else /* defined(VBOX_WITH_SIMPLIFIED_SLIRP_SYNC) && defined(RT_OS_WINDOWS) */
@@ -585,4 +589,5 @@
             if (so->so_state & SS_ISFCONNECTING)
             {
+                Log2(("connecting %R[natsock] engaged\n",so));
                 STAM_REL_COUNTER_INC(&pData->StatTCPHot);
                 TCP_ENGAGE_EVENT1(so, writefds);
@@ -808,4 +813,5 @@
                 if (so->so_state & SS_ISFCONNECTING)
                 {
+                    Log2(("connecting %R[natsock] catched\n", so));
                     /* Connected */
                     so->so_state &= ~SS_ISFCONNECTING;
@@ -960,15 +966,36 @@
 
 static
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
 void arp_input(PNATState pData, struct mbuf *m)
-{
-    struct ethhdr *eh = mtod(m, struct ethhdr *);
-    struct arphdr *ah = (struct arphdr *)&eh[1];
-    uint8_t arp_reply[sizeof(struct arphdr)];
+#else
+void arp_input(PNATState pData, const uint8_t *pkt, int pkt_len)
+#endif
+{
+    struct ethhdr *eh;
+    struct ethhdr *reh;
+    struct arphdr *ah;
     struct arphdr *rah;
     int ar_op;
     struct ex_list *ex_ptr;
-    uint32_t htip = ntohl(*(uint32_t*)ah->ar_tip);
-
-    rah = (struct arphdr *)arp_reply;
+    uint32_t htip;
+#ifndef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
+    uint8_t arp_reply[sizeof(struct arphdr) + ETH_HLEN];
+    eh = (struct ethhdr *)pkt;
+#else
+    struct mbuf *mr; 
+    eh = mtod(m, struct ethhdr *);
+#endif
+    ah = (struct arphdr *)&eh[1];
+    htip = ntohl(*(uint32_t*)ah->ar_tip);
+
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
+    mr = m_get(pData);
+    mr->m_data += if_maxlinkhdr;
+    mr->m_len = sizeof(struct arphdr);
+    rah = mtod(mr, struct arphdr *);
+#else
+    reh = (struct ethhdr *)arp_reply;
+    rah = (struct arphdr *)&reh[1];
+#endif
 
     ar_op = ntohs(ah->ar_op);
@@ -989,4 +1016,10 @@
         arp_ok:
 
+#ifndef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
+                memcpy(reh->h_dest, eh->h_source, ETH_ALEN);
+                memcpy(reh->h_source, &special_addr, ETH_ALEN);
+                reh->h_source[5] = ah->ar_tip[3];
+                reh->h_proto = htons(ETH_P_ARP);
+#endif
                 rah->ar_hrd = htons(1);
                 rah->ar_pro = htons(ETH_P_IP);
@@ -995,4 +1028,5 @@
                 rah->ar_op = htons(ARPOP_REPLY);
                 memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN);
+
                 switch (htip & ~pData->netmask) 
                 {
@@ -1008,5 +1042,5 @@
                 memcpy(rah->ar_tip, ah->ar_sip, 4);
 #ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
-                if_encap(pData, ETH_P_ARP, arp_reply, sizeof(struct arphdr));
+                if_encap(pData, ETH_P_ARP, mr);
                 m_free(pData, m);
 #else
@@ -1038,10 +1072,10 @@
     /* Note: we add to align the IP header */
 
-    if (M_FREEROOM(m) < pkt_len)
-    {
-       m_inc(m, pkt_len);
-    }
-    m->m_len = pkt_len;
-    memcpy(m->m_data, pkt, pkt_len);
+    if (M_FREEROOM(m) < pkt_len + 2)
+    {
+       m_inc(m, pkt_len + 2);
+    }
+    m->m_len = pkt_len + 2;
+    memcpy(m->m_data + 2, pkt, pkt_len);
 
     proto = ntohs(*(uint16_t *)(pkt + 12));
@@ -1049,5 +1083,10 @@
     {
         case ETH_P_ARP:
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
             arp_input(pData, m);
+#else
+            arp_input(pData, pkt, pkt_len);
+            m_free(pData, m);
+#endif
             break;
         case ETH_P_IP:
@@ -1055,6 +1094,6 @@
              * the first outgoing connection gets an incorrect timestamp. */
             updtime(pData);
-            m->m_data += ETH_HLEN;
-            m->m_len -= ETH_HLEN;
+            m->m_data += ETH_HLEN + 2;
+            m->m_len -= ETH_HLEN + 2;
             ip_input(pData, m);
             break;
@@ -1067,12 +1106,15 @@
 
 /* output the IP packet to the ethernet device */
-void if_encap(PNATState pData, uint16_t eth_proto, const uint8_t *ip_data, int ip_data_len)
-{
 #ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
-    uint8_t *buf = RTMemAlloc(1600); /* XXX:temporal solution */
-    struct ethhdr *eh = (struct ethhdr *)buf;
-
-    if (ip_data_len + ETH_HLEN > 1600)
-        return;
+void if_encap(PNATState pData, uint16_t eth_proto, struct mbuf *m)
+#else
+void if_encap(PNATState pData, uint8_t *ip_data, int ip_data_len)
+#endif
+{
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
+    struct ethhdr *eh;
+    m->m_data -= if_maxlinkhdr;
+    m->m_len += ETH_HLEN;
+    eh = mtod(m, struct ethhdr *);
 #else
     uint8_t buf[1600]; 
@@ -1081,4 +1123,6 @@
     if (ip_data_len + ETH_HLEN > sizeof(buf))
         return;
+    
+    memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
 #endif
 
@@ -1088,7 +1132,11 @@
     /* XXX: not correct */
     eh->h_source[5] = CTL_ALIAS;
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
     eh->h_proto = htons(eth_proto);
-    memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
+    slirp_output(pData->pvUser, m, mtod(m, uint8_t *), m->m_len);
+#else
+    eh->h_proto = htons(ETH_P_IP);
     slirp_output(pData->pvUser, buf, ip_data_len + ETH_HLEN);
+#endif
 }
 
@@ -1145,2 +1193,13 @@
     return 0;
 }
+
+/*
+ * this function called from NAT thread
+ */
+void slirp_post_sent(PNATState pData, void *pvArg)
+{
+    struct socket *so = 0; 
+    struct tcpcb *tp = 0;
+    struct mbuf *m = (struct mbuf *)pvArg;
+    m_free(pData, m); 
+}
Index: trunk/src/VBox/Devices/Network/slirp/socket.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/socket.c	(revision 15889)
+++ trunk/src/VBox/Devices/Network/slirp/socket.c	(revision 15890)
@@ -461,4 +461,8 @@
             return;
         m->m_data += if_maxlinkhdr;
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
+        m->m_data += sizeof(struct udphdr) 
+                    + sizeof(struct ip); /*XXX: no options atm*/
+#endif
 
         /*
Index: trunk/src/VBox/Devices/Network/slirp/tcp_input.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/tcp_input.c	(revision 15889)
+++ trunk/src/VBox/Devices/Network/slirp/tcp_input.c	(revision 15890)
@@ -323,4 +323,5 @@
     {
         tcpstat.tcps_rcvbadsum++;
+        Log2(("checksum is invalid => drop\n"));
         goto drop;
     }
@@ -335,4 +336,5 @@
     {
         tcpstat.tcps_rcvbadoff++;
+        Log2(("ti_off(tlen(%d)<%d<(tcphdr(%d))) is invalid =>drop\n", tlen, off, sizeof(struct tcphdr)));
         goto drop;
     }
@@ -447,6 +449,9 @@
      * or something else, we nuke it.
      */
-    if (so->so_state & SS_ISFCONNECTING)
+    if (so->so_state & SS_ISFCONNECTING) 
+    {
+        Log2(("so_state(%x) of %R[natsock] is still connecting =>drop\n", so->so_state, so));
         goto drop;
+    }
 
     tp = sototcpcb(so);
@@ -456,5 +461,8 @@
         goto dropwithreset;
     if (tp->t_state == TCPS_CLOSED)
+    {
+        Log2(("t_state(%x) is closed =>drop\n", tp->t_state));
         goto drop;
+    }
 
     /* Unscale the window into a 32-bit value. */
@@ -654,10 +662,15 @@
         case TCPS_LISTEN:
         {
-            if (tiflags & TH_RST)
+            if (tiflags & TH_RST) {
+                Log2(("RST(%x) is on listen =>drop\n", tiflags));
                 goto drop;
+            }
             if (tiflags & TH_ACK)
                 goto dropwithreset;
-            if ((tiflags & TH_SYN) == 0)
+            if ((tiflags & TH_SYN) == 0) 
+            {
+                Log2(("SYN(%x) is off on listen =>drop\n", tiflags));
                 goto drop;
+            }
 
             /*
@@ -768,9 +781,13 @@
                 if (tiflags & TH_ACK)
                     tp = tcp_drop(pData, tp,0); /* XXX Check t_softerror! */
+                Log2(("RST(%x) is on SYN_SENT =>drop\n", tiflags));
                 goto drop;
             }
 
-            if ((tiflags & TH_SYN) == 0)
+            if ((tiflags & TH_SYN) == 0) 
+            {
+                Log2(("SYN(%x) bit is off on SYN_SENT =>drop\n", tiflags));
                 goto drop;
+            }
             if (tiflags & TH_ACK)
             {
@@ -1020,4 +1037,5 @@
 /*              so->so_error = ECONNRESET; */
 close:
+                Log2(("closing...=>drop\n", tp->t_state)); 
                 tp->t_state = TCPS_CLOSED;
                 tcpstat.tcps_drops++;
@@ -1028,4 +1046,5 @@
             case TCPS_LAST_ACK:
             case TCPS_TIME_WAIT:
+                Log2(("t_state is (%x) sort of close =>drop\n", tp->t_state)); 
                 tp = tcp_close(pData, tp);
                 goto drop;
@@ -1045,6 +1064,9 @@
      * If the ACK bit is off we drop the segment and return.
      */
-    if ((tiflags & TH_ACK) == 0)
+    if ((tiflags & TH_ACK) == 0) 
+    {
+        Log2(("ACK(%x) bit is off =>drop\n", tiflags)); 
         goto drop;
+    }
 
     /*
@@ -1154,4 +1176,5 @@
                         if (SEQ_GT(onxt, tp->snd_nxt))
                             tp->snd_nxt = onxt;
+                        Log2(("t_dupacks(%d) == tcprexmtthresh(%d)=>drop\n", tp->t_dupacks, tcprexmtthresh));
                         goto drop;
                     }
@@ -1160,4 +1183,5 @@
                         tp->snd_cwnd += tp->t_maxseg;
                         (void) tcp_output(pData, tp);
+                        Log2(("t_dupacks(%d) > tcprexmtthresh(%d)=>drop\n", tp->t_dupacks, tcprexmtthresh));
                         goto drop;
                     }
@@ -1305,4 +1329,5 @@
                     if (ourfinisacked)
                     {
+                        Log2(("ourfinisacked=>drop\n"));
                         tp = tcp_close(pData, tp);
                         goto drop;
@@ -1528,4 +1553,5 @@
 
 dropafterack:
+    Log2(("drop after ack\n"));
     /*
      * Generate an ACK dropping incoming segment if it occupies
@@ -1541,4 +1567,5 @@
 dropwithreset:
     /* reuses m if m!=NULL, m_free() unnecessary */
+    Log2(("drop with reset\n"));
     if (tiflags & TH_ACK)
         tcp_respond(pData, tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
@@ -1556,4 +1583,5 @@
      * Drop space held by incoming segment and return.
      */
+    Log2(("drop\n"));
     m_free(pData, m);
 
Index: trunk/src/VBox/Devices/Network/slirp/tcp_output.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/tcp_output.c	(revision 15889)
+++ trunk/src/VBox/Devices/Network/slirp/tcp_output.c	(revision 15890)
@@ -428,4 +428,8 @@
         }
         m->m_data += if_maxlinkhdr;
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
+        m->m_data += sizeof(struct ip) 
+            + sizeof(struct tcphdr);
+#endif
         m->m_len = hdrlen;
     }
