Index: trunk/src/VBox/Devices/Network/slirp/bootp.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/bootp.c	(revision 19309)
+++ trunk/src/VBox/Devices/Network/slirp/bootp.c	(revision 19313)
@@ -127,8 +127,16 @@
 }
 
+#ifndef VBOX_WITH_NAT_SERVICE
 static void bootp_reply(PNATState pData, struct bootp_t *bp)
+#else
+static void bootp_reply(PNATState pData, struct mbuf *m0)
+#endif
 {
     BOOTPClient *bc;
-    struct mbuf *m;
+    struct mbuf *m; /* XXX: @todo vasily - it'd be better to reuse this mbuf here */
+#ifdef VBOX_WITH_NAT_SERVICE
+    struct bootp_t *bp = mtod(m0, struct bootp_t *);
+    struct ethhdr *eh;
+#endif
     struct bootp_t *rbp;
     struct sockaddr_in saddr, daddr;
@@ -172,9 +180,15 @@
         return;
 
+#ifndef VBOX_WITH_NAT_SERVICE
     /* XXX: this is a hack to get the client mac address */
     memcpy(client_ethaddr, bp->bp_hwaddr, 6);
+#endif
 
     if ((m = m_get(pData)) == NULL)
         return;
+#ifdef VBOX_WITH_NAT_SERVICE
+    eh = mtod(m, struct ethhdr *);
+    memcpy(eh->h_source, bp->bp_hwaddr, ETH_ALEN); /* XXX: if_encap just swap source with dest*/
+#endif
     m->m_data += if_maxlinkhdr; /*reserve ether header */
     rbp = mtod(m, struct bootp_t *);
@@ -195,5 +209,9 @@
                 return;
             }
+#ifdef VBOX_WITH_NAT_SERVICE
+            memcpy(bc->macaddr, bp->bp_hwaddr, 6);
+#else
             memcpy(bc->macaddr, client_ethaddr, 6);
+#endif
         }
     }
@@ -215,5 +233,10 @@
 
     /* Address/port of the DHCP server. */
+#ifndef VBOX_WITH_NAT_SERVICE
     saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
+#else
+    saddr.sin_addr.s_addr = special_addr.s_addr;
+#endif
+
     saddr.sin_port = htons(BOOTP_SERVER);
 
@@ -350,4 +373,8 @@
 
     if (bp->bp_op == BOOTP_REQUEST)
+#ifndef VBOX_WITH_NAT_SERVICE
         bootp_reply(pData, bp);
-}
+#else
+        bootp_reply(pData, m);
+#endif
+}
Index: trunk/src/VBox/Devices/Network/slirp/ip_icmp.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/ip_icmp.c	(revision 19309)
+++ trunk/src/VBox/Devices/Network/slirp/ip_icmp.c	(revision 19313)
@@ -539,4 +539,10 @@
     {
         int new_m_size;
+#ifdef VBOX_WITH_NAT_SERVICE
+        struct ethhdr *eh, *eh0;
+        eh0 = (struct ethhdr *)msrc->m_dat;
+        eh = (struct ethhdr *)m->m_dat;
+        memcpy(eh->h_source, eh0->h_source, ETH_ALEN);
+#endif
         m->m_data += if_maxlinkhdr;
         new_m_size = sizeof(struct ip) + ICMP_MINLEN + msrc->m_len + ICMP_MAXDATALEN;
Index: trunk/src/VBox/Devices/Network/slirp/ip_output.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/ip_output.c	(revision 19309)
+++ trunk/src/VBox/Devices/Network/slirp/ip_output.c	(revision 19313)
@@ -63,4 +63,5 @@
     DEBUG_ARG("so = %lx", (long)so);
     DEBUG_ARG("m0 = %lx", (long)m0);
+    Assert(m->m_data == m->m_dat + if_maxlinkhdr);
 
 #if 0 /* We do no options */
@@ -103,4 +104,12 @@
         ip->ip_sum = cksum(m, hlen);
 
+#ifdef VBOX_WITH_NAT_SERVICE
+        {
+            struct ethhdr *eh, *eh0;
+            eh = (struct ethhdr *)m->m_dat;
+            eh0 = (struct ethhdr *)m0->m_dat;
+            memcpy(eh->h_source, eh0->h_source, ETH_ALEN);
+        }
+#endif
         if_output(pData, so, m);
         goto done;
@@ -137,4 +146,8 @@
         for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len)
         {
+#ifdef VBOX_WITH_NAT_SERVICE
+            struct ethhdr *eh0;
+            struct ethhdr *eh;
+#endif
             register struct ip *mhip;
             m = m_get(pData);
@@ -145,4 +158,9 @@
                 goto sendorfree;
             }
+#ifdef VBOX_WITH_NAT_SERVICE
+            eh0 = (struct ethhdr *)m0->m_dat; 
+            eh = (struct ethhdr *)m->m_dat;
+            memcpy(eh->h_source, eh0->h_source, ETH_ALEN);
+#endif
             m->m_data += if_maxlinkhdr;
             mhip = mtod(m, struct ip *);
Index: trunk/src/VBox/Devices/Network/slirp/libslirp.h
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/libslirp.h	(revision 19309)
+++ trunk/src/VBox/Devices/Network/slirp/libslirp.h	(revision 19313)
@@ -28,5 +28,9 @@
 #endif
 
+#ifndef VBOX_WITH_NAT_SERVICE
 int slirp_init(PNATState *, const char *, uint32_t, bool, void *);
+#else
+int slirp_init(PNATState *, uint32_t, uint32_t, bool, void *);
+#endif
 void slirp_register_timers(PNATState pData, PPDMDRVINS pDrvIns);
 void slirp_term(PNATState);
Index: trunk/src/VBox/Devices/Network/slirp/slirp.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 19309)
+++ trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 19313)
@@ -196,4 +196,14 @@
 };
 
+static const uint8_t broadcast_ethaddr[6] =
+{
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+static const uint8_t zerro_ethaddr[6] =
+{
+    0x0, 0x0, 0x0, 0x0, 0x0, 0x0
+};
+
 #ifdef RT_OS_WINDOWS
 # ifndef VBOX_WITH_MULTI_DNS
@@ -587,6 +597,11 @@
 }
 
+#ifndef VBOX_WITH_NAT_SERVICE
 int slirp_init(PNATState *ppData, const char *pszNetAddr, uint32_t u32Netmask,
                bool fPassDomain, void *pvUser)
+#else
+int slirp_init(PNATState *ppData, uint32_t u32NetAddr, uint32_t u32Netmask,
+               bool fPassDomain, void *pvUser)
+#endif
 {
     int fNATfailed = 0;
@@ -627,5 +642,9 @@
     m_init(pData);
 
+#ifndef VBOX_WITH_NAT_SERVICE
     inet_aton(pszNetAddr, &special_addr);
+#else
+    special_addr.s_addr = u32NetAddr;
+#endif
     alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
     /* @todo: add ability to configure this staff */
@@ -1366,4 +1385,5 @@
 }
 
+#ifndef VBOX_WITH_NAT_SERVICE
 #define ETH_ALEN        6
 #define ETH_HLEN        14
@@ -1379,4 +1399,5 @@
 };
 AssertCompileSize(struct ethhdr, 14);
+#endif
 
 struct arphdr
@@ -1407,10 +1428,20 @@
     struct ex_list *ex_ptr;
     uint32_t htip;
+    uint32_t tip;
     struct mbuf *mr;
     eh = mtod(m, struct ethhdr *);
     ah = (struct arphdr *)&eh[1];
     htip = ntohl(*(uint32_t*)ah->ar_tip);
+    tip = *(uint32_t*)ah->ar_tip;
 
     mr = m_get(pData);
+#ifdef VBOX_WITH_NAT_SERVICE
+    reh = mtod(mr, struct ethhdr *);
+    memcpy(reh->h_source, eh->h_source, ETH_ALEN); /* XXX: if_encap will swap src and dst*/ 
+    Log4(("NAT: arp:[%hhx:%hhx:%hhx:%hhx:%hhx:%hhx]->[%hhx:%hhx:%hhx:%hhx:%hhx:%hhx]\n",
+        reh->h_source[0], reh->h_source[1], reh->h_source[2], reh->h_source[3], reh->h_source[4], reh->h_source[5], 
+        reh->h_dest[0], reh->h_dest[1], reh->h_dest[2], reh->h_dest[3], reh->h_dest[4], reh->h_dest[5]));
+    Log4(("NAT: arp: %R[IP4]\n", &tip));
+#endif
     mr->m_data += if_maxlinkhdr;
     mr->m_len = sizeof(struct arphdr);
@@ -1421,4 +1452,7 @@
     {
         case ARPOP_REQUEST:
+#ifdef VBOX_WITH_NAT_SERVICE
+            if (tip == special_addr.s_addr) goto arp_ok;
+#endif
             if ((htip & pData->netmask) == ntohl(special_addr.s_addr))
             {
@@ -1429,6 +1463,8 @@
                 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
                 {
-                    if ((htip & ~pData->netmask) == ex_ptr->ex_addr)
+                    if ((htip & ~pData->netmask) == ex_ptr->ex_addr) 
+                    {
                         goto arp_ok;
+                    }
                 }
                 return;
@@ -1467,4 +1503,5 @@
     int proto;
     static bool fWarnedIpv6;
+    struct ethhdr *eh = (struct ethhdr*)pkt;
 
     if (pkt_len < ETH_HLEN)
@@ -1473,4 +1510,13 @@
         return;
     }
+    Log4(("NAT: in:[%hhx:%hhx:%hhx:%hhx:%hhx:%hhx]->[%hhx:%hhx:%hhx:%hhx:%hhx:%hhx]\n",
+        eh->h_source[0], eh->h_source[1], eh->h_source[2], eh->h_source[3], eh->h_source[4], eh->h_source[5], 
+        eh->h_dest[0], eh->h_dest[1], eh->h_dest[2], eh->h_dest[3], eh->h_dest[4], eh->h_dest[5]));
+#ifdef VBOX_WITH_NAT_SERVICE
+    if (memcmp(eh->h_source, special_ethaddr, ETH_ALEN) == 0) 
+    {
+        goto drop;
+    }
+#endif
 
     m = m_get(pData);
@@ -1516,4 +1562,5 @@
             break;
     }
+    drop:
     RTMemFree((void *)pkt);
 }
@@ -1529,8 +1576,19 @@
     eh = mtod(m, struct ethhdr *);
 
+#ifndef VBOX_WITH_NAT_SERVICE
     memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
     memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
     /* XXX: not correct */
     eh->h_source[5] = CTL_ALIAS;
+#else
+    Assert((caddr_t)eh == (caddr_t)m->m_dat); 
+    if (memcmp(eh->h_source, special_ethaddr, ETH_ALEN) != 0) 
+    {
+        memcpy(eh->h_dest, eh->h_source, ETH_ALEN);
+        memcpy(eh->h_source, special_ethaddr, ETH_ALEN);
+        Assert(memcmp(eh->h_dest, special_ethaddr, ETH_ALEN) != 0);
+        Assert(memcmp(eh->h_dest, zerro_ethaddr, ETH_ALEN) != 0);
+    }
+#endif
     eh->h_proto = htons(eth_proto);
 #if 0
@@ -1571,5 +1629,7 @@
 void slirp_set_ethaddr(PNATState pData, const uint8_t *ethaddr)
 {
+#ifndef VBOX_WITH_NAT_SERVICE
     memcpy(client_ethaddr, ethaddr, ETH_ALEN);
+#endif
 }
 
Index: trunk/src/VBox/Devices/Network/slirp/slirp.h
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/slirp.h	(revision 19309)
+++ trunk/src/VBox/Devices/Network/slirp/slirp.h	(revision 19313)
@@ -356,3 +356,20 @@
 #define DO_ALIAS(paddr) do {} while (0)
 #endif
-#endif
+
+
+# ifdef VBOX_WITH_NAT_SERVICE
+#  define ETH_ALEN        6
+#  define ETH_HLEN        14
+
+#  define ARPOP_REQUEST   1               /* ARP request                  */
+#  define ARPOP_REPLY     2               /* ARP reply                    */
+
+struct ethhdr
+{
+    unsigned char   h_dest[ETH_ALEN];           /* destination eth addr */
+    unsigned char   h_source[ETH_ALEN];         /* source ether addr    */
+    unsigned short  h_proto;                    /* packet type ID field */
+};
+AssertCompileSize(struct ethhdr, 14);
+# endif
+#endif
Index: trunk/src/VBox/Devices/Network/slirp/slirp_state.h
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/slirp_state.h	(revision 19309)
+++ trunk/src/VBox/Devices/Network/slirp/slirp_state.h	(revision 19313)
@@ -126,5 +126,7 @@
     struct in_addr loopback_addr;
     uint32_t netmask;
+#ifndef VBOX_WITH_NAT_SERVICE
     uint8_t client_ethaddr[6];
+#endif
     struct ex_list *exec_list;
     char slirp_hostname[33];
Index: trunk/src/VBox/Devices/Network/slirp/socket.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/socket.c	(revision 19309)
+++ trunk/src/VBox/Devices/Network/slirp/socket.c	(revision 19313)
@@ -500,4 +500,5 @@
         /* A "normal" UDP packet */
         struct mbuf *m;
+        struct ethhdr *eh;
         size_t len;
         u_long n;
@@ -593,4 +594,15 @@
              * make it look like that's where it came from, done by udp_output
              */
+#ifdef VBOX_WITH_NAT_SERVICE
+            {
+                struct ethhdr *eh0;
+                struct ethhdr *eh;
+                Assert(so->so_m);
+                eh0 = (struct ethhdr *)so->so_m->m_dat;
+                eh = (struct ethhdr *)m->m_dat;
+
+                memcpy(eh->h_source, eh0->h_source, ETH_ALEN);
+            }
+#endif
             udp_output(pData, so, m, &addr);
             SOCKET_UNLOCK(so);
Index: trunk/src/VBox/Devices/Network/slirp/socket.h
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/socket.h	(revision 19309)
+++ trunk/src/VBox/Devices/Network/slirp/socket.h	(revision 19313)
@@ -82,4 +82,8 @@
     void (* so_timeout)(PNATState pData, struct socket *so, void *arg);
     void *so_timeout_arg;
+#endif
+#ifdef VBOX_WITH_NAT_SERVICE
+    /* storage of source ether address */
+    unsigned char so_ethaddr[6]; 
 #endif
 };
Index: trunk/src/VBox/Devices/Network/slirp/tcp_input.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/tcp_input.c	(revision 19309)
+++ trunk/src/VBox/Devices/Network/slirp/tcp_input.c	(revision 19313)
@@ -290,8 +290,15 @@
     {
         so = inso;
-
+        Log4(("NAT: tcp_input: %R[natsock]\n", so));
+        Assert(so->so_m);
         /* Re-set a few variables */
         tp = sototcpcb(so);
         m = so->so_m;
+#ifdef VBOX_WITH_NAT_SERVICE
+        {
+            struct ethhdr *eh = (struct ethhdr *)m->m_dat;
+            memcpy(so->so_ethaddr, eh->h_source, ETH_ALEN);
+        }
+#endif
         so->so_m = 0;
         ti = so->so_ti;
@@ -474,5 +481,12 @@
             goto dropwithreset;
         }
-        
+#ifdef VBOX_WITH_NAT_SERVICE
+        Assert(m);
+        so->so_m = m; /* save the initial packet */
+        {
+            struct ethhdr *eh0;
+            eh0 = (struct ethhdr *)m->m_dat;
+        }
+#endif        
         SOCKET_LOCK(so); 
         sbreserve(&so->so_snd, tcp_sndspace);
@@ -776,4 +790,11 @@
                  * succeeded or not.  So we must time it out.
                  */
+#ifdef VBOX_WITH_NAT_SERVICE
+                Assert(m);
+                {
+                    struct ethhdr *eh0;
+                    eh0 = (struct ethhdr *)m->m_dat;
+                }
+#endif
                 so->so_m = m;
                 so->so_ti = ti;
Index: trunk/src/VBox/Devices/Network/slirp/tcp_output.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/tcp_output.c	(revision 19309)
+++ trunk/src/VBox/Devices/Network/slirp/tcp_output.c	(revision 19313)
@@ -378,4 +378,19 @@
             goto out;
         }
+#ifdef VBOX_WITH_NAT_SERVICE
+        {
+            struct ethhdr *eh, *eh0;
+            eh = (struct ethhdr *)m->m_dat;
+            if (so->so_m)
+            {
+                eh0 = (struct ethhdr *)so->so_m->m_dat;
+                memcpy(eh->h_source, eh0->h_source, ETH_ALEN);
+            }
+            else 
+            {
+                memcpy(eh->h_source, so->so_ethaddr, ETH_ALEN);
+            }
+        }
+#endif
         m->m_data += if_maxlinkhdr;
         m->m_len = hdrlen;
@@ -427,7 +442,17 @@
             goto out;
         }
+#ifdef VBOX_WITH_NAT_SERVICE
+        {
+            struct ethhdr *eh;
+            eh = (struct ethhdr *)m->m_dat;
+            memcpy(eh->h_source, so->so_ethaddr, ETH_ALEN);
+        }
+#endif
         m->m_data += if_maxlinkhdr;
+#ifndef VBOX_WITH_NAT_SERVICE
+        /* XXX: it's shouldn't be here at all need to be deleted */
         m->m_data += sizeof(struct ip) 
                    + sizeof(struct tcphdr);
+#endif
         m->m_len = hdrlen;
     }
@@ -577,4 +602,5 @@
      * the template, but need a way to checksum without them.
      */
+    Assert(m->m_len == (hdrlen + len));
     m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
 
@@ -589,4 +615,16 @@
         error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
                          so->so_options & SO_DONTROUTE, 0);
+#endif
+#ifdef VBOX_WITH_NAT_SERVICE
+        {
+            struct ethhdr *eh0, *eh;
+            eh = (struct ethhdr *)m->m_dat;
+
+            if (so->so_m != NULL)
+            {
+                eh0 = (struct ethhdr *)so->so_m->m_dat;
+                memcpy(eh->h_source, eh0->h_source, ETH_ALEN);
+            }
+        }
 #endif
         error = ip_output(pData, so, m);
Index: trunk/src/VBox/Devices/Network/slirp/tcp_subr.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/tcp_subr.c	(revision 19309)
+++ trunk/src/VBox/Devices/Network/slirp/tcp_subr.c	(revision 19313)
@@ -124,4 +124,13 @@
         if ((m = m_get(pData)) == NULL)
             return;
+#ifdef VBOX_WITH_NAT_SERVICE
+        {
+            struct ethhdr *eh0, *eh;
+            Assert(tp->t_socket->so_m);
+            eh0 = (struct ethhdr *)tp->t_socket->so_m->m_dat;
+            eh = (struct ethhdr *)m->m_dat;
+            memcpy(eh->h_source, eh0->h_source, ETH_ALEN);
+        }
+#endif
 #ifdef TCP_COMPAT_42
         tlen = 1;
