Index: /trunk/src/VBox/Devices/Network/slirp/bootp.c
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/bootp.c	(revision 22663)
+++ /trunk/src/VBox/Devices/Network/slirp/bootp.c	(revision 22664)
@@ -24,6 +24,19 @@
 #include <slirp.h>
 
+/** Entry in the table of known DHCP clients. */
+typedef struct
+{
+    uint32_t xid;
+    bool allocated;
+    uint8_t macaddr[6];
+    struct in_addr addr;
+    int number;
+} BOOTPClient;
+/** Number of DHCP clients supported by NAT. */
+#define NB_ADDR     16
+
+#define bootp_clients ((BOOTPClient *)pData->pbootp_clients)
+
 /* XXX: only DHCP is supported */
-
 static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
 static void bootp_reply(PNATState pData, struct mbuf *m0, int off, uint16_t flags);
@@ -683,2 +696,63 @@
     }
 }
+
+int bootp_cache_lookup_ip_by_ether(PNATState pData,const uint8_t* ether, uint32_t *pip)
+{
+    int rc = 1;
+    uint32_t ip = INADDR_ANY; 
+    int i;
+    if (ether == NULL || pip == NULL)
+        goto done;
+    for (i = 0; i < NB_ADDR; i++)
+    {
+        if (   bootp_clients[i].allocated
+            && memcmp(bootp_clients[i].macaddr, ether, ETH_ALEN) == 0)
+        {
+            ip = bootp_clients[i].addr.s_addr;
+            rc = 0;
+            break;
+        }
+    }
+done:
+    *pip = ip;
+    return rc;
+}
+
+int bootp_cache_lookup_ether_by_ip(PNATState pData, uint32_t ip, uint8_t *ether)
+{
+    int rc = 1;
+    int i;
+    if (ether == NULL)
+        goto done;
+    for (i = 0; i < NB_ADDR; i++)
+    {
+        if (   bootp_clients[i].allocated
+            && ip == bootp_clients[i].addr.s_addr)
+        {
+            memcpy(ether, bootp_clients[i].macaddr, ETH_ALEN);
+            rc = 0;
+            break;
+        }
+    }
+done:
+    return rc;
+}
+
+/*
+ * Initialize dhcp server 
+ * @returns 0 - if initialization is ok, non-zero otherwise
+ */
+int bootp_dhcp_init(PNATState pData)
+{
+    int rc = 1;
+    pData->pbootp_clients = RTMemAllocZ(sizeof(BOOTPClient) * NB_ADDR);
+    if (pData->pbootp_clients != NULL)
+        rc = 0;
+    return rc;
+}
+
+int bootp_dhcp_fini(PNATState pData)
+{
+    if (pData->pbootp_clients != NULL)
+        RTMemFree(pData->pbootp_clients);
+}
Index: /trunk/src/VBox/Devices/Network/slirp/bootp.h
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/bootp.h	(revision 22663)
+++ /trunk/src/VBox/Devices/Network/slirp/bootp.h	(revision 22664)
@@ -115,13 +115,4 @@
 };
 
-/** Entry in the table of known DHCP clients. */
-typedef struct
-{
-    uint32_t xid;
-    bool allocated;
-    uint8_t macaddr[6];
-    struct in_addr addr;
-    int number;
-} BOOTPClient;
 
 #define DHCP_FLAGS_B (1<<15)
@@ -133,2 +124,6 @@
 
 void bootp_input(PNATState, struct mbuf *m);
+int bootp_cache_lookup_ip_by_ether(PNATState, const uint8_t *, uint32_t *);
+int bootp_cache_lookup_ether_by_ip(PNATState, uint32_t, uint8_t *);
+int bootp_dhcp_init(PNATState);
+int bootp_dhcp_fini(PNATState);
Index: /trunk/src/VBox/Devices/Network/slirp/ip_output.c
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/ip_output.c	(revision 22663)
+++ /trunk/src/VBox/Devices/Network/slirp/ip_output.c	(revision 22664)
@@ -46,29 +46,18 @@
 #include "alias.h"
 
-static const uint8_t* rt_lookup_in_cache(PNATState pData, uint32_t dst)
+static int rt_lookup_in_cache(PNATState pData, uint32_t dst, uint8_t *ether)
 {
-    int i;
-    struct arp_cache_entry *ac = NULL;
-   /* @todo (vasily) to quick ramp up on routing rails
-    * we use information from DHCP server leasings, this
-    * code couldn't detect any changes in network topology
-    * and should be borrowed from other places
-    */
-    LIST_FOREACH(ac, &pData->arp_cache, list)
-    {
-        if (ac->ip == dst)
-            return &ac->ether[0];
-    }
-    for (i = 0; i < NB_ADDR; i++)
-    {
-        if (   bootp_clients[i].allocated
-            && bootp_clients[i].addr.s_addr == dst)
-            return &bootp_clients[i].macaddr[0];
-    }
+    int rc = 1;
+    rc = slirp_arp_lookup_ether_by_ip(pData, dst, ether);
+    if (rc == 0)
+        return rc;
+    rc = bootp_cache_lookup_ether_by_ip(pData, dst, ether);
+    if (rc == 0)
+        return rc;
     /* 
      * no chance to send this packet, sorry, we will request ether address via ARP 
      */
     slirp_arp_who_has(pData, dst); 
-    return NULL; 
+    return rc; 
 }
 
@@ -88,5 +77,6 @@
     extern uint8_t zerro_ethaddr[ETH_ALEN];
     struct ethhdr *eh = NULL;
-    const uint8_t *eth_dst = NULL;
+    uint8_t eth_dst[ETH_ALEN];
+    int rc = 1;
 
     STAM_PROFILE_START(&pData->StatIP_output, a);
@@ -134,5 +124,14 @@
      eh = (struct ethhdr *)MBUF_HEAD(m);
      if (memcmp(eh->h_source, zerro_ethaddr, ETH_ALEN) == 0)
-         eth_dst = rt_lookup_in_cache(pData, ip->ip_dst.s_addr); 
+     {
+        rc = rt_lookup_in_cache(pData, ip->ip_dst.s_addr, eth_dst);
+        if (rc != 0)
+            goto bad;
+     }
+     else
+    {
+        memcpy(eth_dst, eh->h_source, ETH_ALEN);
+        rc = 0; /*some times we've already know where to send packet*/
+    }
 
     /*
@@ -145,14 +144,13 @@
         ip->ip_sum = 0;
         ip->ip_sum = cksum(m, hlen);
-        if (eth_dst != NULL) 
-            memcpy(eh->h_source, eth_dst, ETH_ALEN); 
-        {
-            int rc;
-            STAM_PROFILE_START(&pData->StatALIAS_output, a);
-            rc = LibAliasOut((m->m_la ? m->m_la : pData->proxy_alias), 
-                mtod(m, char *), m->m_len);
-            Log2(("NAT: LibAlias return %d\n", rc));
-            STAM_PROFILE_STOP(&pData->StatALIAS_output, a);
-        }
+    
+        Assert((rc == 0));
+        memcpy(eh->h_source, eth_dst, ETH_ALEN); 
+    
+        STAM_PROFILE_START(&pData->StatALIAS_output, a);
+        rc = LibAliasOut((m->m_la ? m->m_la : pData->proxy_alias), 
+            mtod(m, char *), m->m_len);
+        Log2(("NAT: LibAlias return %d\n", rc));
+        STAM_PROFILE_STOP(&pData->StatALIAS_output, a);
 
         if_output(pData, so, m);
@@ -203,7 +201,7 @@
             /* we've calculated eth_dst for first packet */
             eh = (struct ethhdr *)MBUF_HEAD(m);
-            if (eth_dst != NULL) {
-                memcpy(eh->h_source, eth_dst, ETH_ALEN); 
-            }
+            Assert((rc == 0));
+
+            memcpy(eh->h_source, eth_dst, ETH_ALEN); 
 
 #if 0 /* No options */
@@ -247,12 +245,10 @@
         ip->ip_sum = 0;
         ip->ip_sum = cksum(m, hlen);
-        {
-            int rc;
-            STAM_PROFILE_START(&pData->StatALIAS_output, a);
-            rc = LibAliasOut((m->m_la ? m->m_la : pData->proxy_alias), 
-                mtod(m, char *), m->m_len);
-            Log2(("NAT: LibAlias return %d\n", rc));
-            STAM_PROFILE_STOP(&pData->StatALIAS_output, a);
-        }
+
+        STAM_PROFILE_START(&pData->StatALIAS_output, a);
+        rc = LibAliasOut((m->m_la ? m->m_la : pData->proxy_alias), 
+            mtod(m, char *), m->m_len);
+        Log2(("NAT: LibAlias return %d\n", rc));
+        STAM_PROFILE_STOP(&pData->StatALIAS_output, a);
 
 sendorfree:
Index: /trunk/src/VBox/Devices/Network/slirp/slirp.c
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 22663)
+++ /trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 22664)
@@ -190,5 +190,5 @@
 
 static void activate_port_forwarding(PNATState, struct ethhdr *);
-static uint32_t find_guest_ip(PNATState, uint8_t *);
+static uint32_t find_guest_ip(PNATState, const uint8_t *);
 
 static const uint8_t special_ethaddr[6] =
@@ -515,4 +515,5 @@
     link_up = 1;
 
+    bootp_dhcp_init(pData);
     debug_init();
     if_init(pData);
@@ -649,4 +650,5 @@
         RTMemFree(ac);
     }
+    bootp_dhcp_fini(pData);
 #ifdef RT_OS_WINDOWS
     WSACleanup();
@@ -1532,18 +1534,18 @@
  * @todo  see rt_lookup_in_cache
  */
-static uint32_t find_guest_ip(PNATState pData, uint8_t *eth_addr)
+static uint32_t find_guest_ip(PNATState pData, const uint8_t *eth_addr)
 {
     int i;
+    uint32_t ip = INADDR_ANY;
+    if (eth_addr == NULL)
+        goto done;
     if (memcmp(eth_addr, zerro_ethaddr, ETH_ALEN) == 0
         || memcmp(eth_addr, broadcast_ethaddr, ETH_ALEN) == 0)
         goto done;
-    for (i = 0; i < NB_ADDR; i++)
-    {
-        if (   bootp_clients[i].allocated
-            && memcmp(bootp_clients[i].macaddr, eth_addr, ETH_ALEN) == 0)
-            return bootp_clients[i].addr.s_addr;
-    }
+    if(slirp_arp_lookup_ip_by_ether(pData, eth_addr, &ip) == 0)
+        goto done;
+    bootp_cache_lookup_ip_by_ether(pData, eth_addr, &ip);
 done:
-    return INADDR_ANY;
+    return ip;
 }
 
@@ -1827,4 +1829,55 @@
     _8K_1M_CHECK_ARG("TCP_SNDSPACE", kilobytes);
     tcp_sndspace = kilobytes * _1K;
+}
+
+/*
+ * Looking for Ether by ip in ARP-cache
+ * Note: it´s responsible of caller to allocate buffer for result
+ * @returns 0 - if found, 1 - otherwise
+ */
+int slirp_arp_lookup_ether_by_ip(PNATState pData, uint32_t ip, uint8_t *ether)
+{
+    struct arp_cache_entry *ac = NULL;
+    int rc = 1;
+    if (ether == NULL)
+        return rc;
+
+    if (LIST_EMPTY(&pData->arp_cache))
+        return rc;
+
+    LIST_FOREACH(ac, &pData->arp_cache, list)
+    {
+        if (ac->ip == ip)
+        {
+            memcpy(ether, ac->ether, ETH_ALEN);
+            rc = 0;
+            return rc;
+        }
+    }
+    return rc;
+}
+
+/*
+ * Looking for IP by Ether in ARP-cache
+ * Note: it´s responsible of caller to allocate buffer for result
+ * @returns 0 - if found, 1 - otherwise
+ */
+int slirp_arp_lookup_ip_by_ether(PNATState pData, const uint8_t *ether, uint32_t *ip)
+{
+    struct arp_cache_entry *ac = NULL;
+    int rc = 1;
+    *ip = INADDR_ANY;
+    if (LIST_EMPTY(&pData->arp_cache))
+        return rc;
+    LIST_FOREACH(ac, &pData->arp_cache, list)
+    {
+        if (memcmp(ether, ac->ether, ETH_ALEN))
+        {
+            *ip = ac->ip;
+            rc = 0;
+            return rc;
+        }
+    }
+    return rc;
 }
 
Index: /trunk/src/VBox/Devices/Network/slirp/slirp.h
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/slirp.h	(revision 22663)
+++ /trunk/src/VBox/Devices/Network/slirp/slirp.h	(revision 22664)
@@ -415,4 +415,7 @@
 int nbt_alias_load(PNATState);
 int nbt_alias_unload(PNATState);
-#endif
-
+
+int slirp_arp_lookup_ip_by_ether(PNATState, const uint8_t *, uint32_t *);
+int slirp_arp_lookup_ether_by_ip(PNATState, uint32_t, uint8_t *);
+#endif
+
Index: /trunk/src/VBox/Devices/Network/slirp/slirp_state.h
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/slirp_state.h	(revision 22663)
+++ /trunk/src/VBox/Devices/Network/slirp/slirp_state.h	(revision 22664)
@@ -30,6 +30,4 @@
 #include "dnsproxy/dnsproxy.h"
 
-/** Number of DHCP clients supported by NAT. */
-#define NB_ADDR     16
 
 /** Where to start DHCP IP number allocation. */
@@ -100,5 +98,5 @@
 {
     /* Stuff from boot.c */
-    BOOTPClient bootp_clients[NB_ADDR];
+    void *pbootp_clients;
     const char *bootp_filename;
     /* Stuff from if.c */
@@ -306,5 +304,4 @@
 
 #define bootp_filename pData->bootp_filename
-#define bootp_clients pData->bootp_clients
 
 #define if_mtu pData->if_mtu
Index: /trunk/src/VBox/Devices/Network/slirp/tcp_output.c
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/tcp_output.c	(revision 22663)
+++ /trunk/src/VBox/Devices/Network/slirp/tcp_output.c	(revision 22664)
@@ -589,16 +589,4 @@
                          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
         if(so->so_la != NULL)
             m->m_la = so->so_la;
Index: /trunk/src/VBox/Devices/Network/slirp/tcp_subr.c
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/tcp_subr.c	(revision 22663)
+++ /trunk/src/VBox/Devices/Network/slirp/tcp_subr.c	(revision 22664)
@@ -124,13 +124,4 @@
         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;
