Index: /trunk/src/VBox/Devices/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Devices/Makefile.kmk	(revision 22842)
+++ /trunk/src/VBox/Devices/Makefile.kmk	(revision 22843)
@@ -757,4 +757,5 @@
 	Network/slirp/libalias/alias_proxy.c \
 	Network/slirp/libalias/alias_ftp.c \
+	Network/slirp/libalias/alias_dns.c \
 	Network/slirp/libalias/alias_nbt.c \
 	Network/slirp/libalias/alias_util.c
Index: /trunk/src/VBox/Devices/Network/slirp/ip_input.c
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/ip_input.c	(revision 22842)
+++ /trunk/src/VBox/Devices/Network/slirp/ip_input.c	(revision 22843)
@@ -66,4 +66,28 @@
 }
 
+static struct libalias *select_alias(PNATState pData, struct mbuf* m)
+{
+    struct libalias *la = pData->proxy_alias;
+    struct udphdr *udp = NULL;
+    struct ip *pip = NULL;
+
+    if (m->m_la)
+        return m->m_la;
+
+#if 0
+    pip = mtod(m, struct ip *);
+    if (pip->ip_p == IPPROTO_UDP) {
+        udp = (struct udphdr *)((uint8_t *)pip + (pip->ip_hl << 2));
+        if (   pip->ip_dst.s_addr == htonl(ntohl(special_addr.s_addr) | CTL_DNS) 
+            && htons(udp->uh_dport) == 53)
+        {
+            return pData->dns_alias;
+        }
+        /* here we can add catch for dhcp and tftp servers */
+    }
+#endif
+    return la;
+}
+
 /*
  * Ip input routine.  Checksum and byte swap header.  If fragmented
@@ -87,6 +111,5 @@
         int rc;
         STAM_PROFILE_START(&pData->StatALIAS_input, a);
-        rc = LibAliasIn(m->m_la ? m->m_la : pData->proxy_alias, mtod(m, char *), 
-            m->m_len);
+        rc = LibAliasIn(select_alias(pData, m), mtod(m, char *), m->m_len);
         STAM_PROFILE_STOP(&pData->StatALIAS_input, a);
         Log2(("NAT: LibAlias return %d\n", rc));
@@ -135,4 +158,5 @@
         goto bad;
     }
+
     NTOHS(ip->ip_id);
     NTOHS(ip->ip_off);
@@ -149,4 +173,5 @@
         goto bad;
     }
+
     /* Should drop packet if mbuf too long? hmmm... */
     if (m->m_len > ip->ip_len)
Index: /trunk/src/VBox/Devices/Network/slirp/libalias/alias_dns.c
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/libalias/alias_dns.c	(revision 22843)
+++ /trunk/src/VBox/Devices/Network/slirp/libalias/alias_dns.c	(revision 22843)
@@ -0,0 +1,290 @@
+# include <netdb.h>
+# include <iprt/ctype.h>
+# include <iprt/assert.h>
+# include <slirp.h>
+# include "alias_local.h"
+# include "alias_mod.h"
+
+#define DNS_CONTROL_PORT_NUMBER 53
+/* see RFC 1035(4.1.1) */
+union dnsmsg_header
+{
+    struct {
+        uint16_t id;
+        uint16_t rd:1;
+        uint16_t tc:1;
+        uint16_t aa:1;
+        uint16_t opcode:4;
+        uint16_t qr:1;
+        uint16_t rcode:4;
+        uint16_t Z:3;
+        uint16_t ra:1;
+        uint16_t qdcount;
+        uint16_t ancount;
+        uint16_t nscount;
+        uint16_t arcount;
+    } X;
+    uint16_t raw[5];
+};
+struct dnsmsg_answer
+{
+    uint16_t name;
+    uint16_t type;
+    uint16_t class;
+    uint16_t ttl[2];
+    uint16_t rdata_len;
+    uint8_t rdata[1];  /*depends on value at rdata_len */
+};
+
+/* see RFC 1035(4.1) */
+static int dns_alias_handler(PNATState pData, int type);
+static void cstr2qstr(char *cstr, char *qstr);
+static void qstr2cstr(char *qstr, char *cstr);
+
+static int 
+fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
+{
+
+    if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL)
+        return (-1);
+    fprintf(stderr, "NAT:%s: ah(dport: %hd, sport: %hd) oaddr:%R[IP4] aaddr:%R[IP4]\n", 
+        __FUNCTION__, ntohs(*ah->dport), ntohs(*ah->sport),
+        &ah->oaddr, &ah->aaddr);
+    if (   (ntohs(*ah->dport) == DNS_CONTROL_PORT_NUMBER
+        || ntohs(*ah->sport) == DNS_CONTROL_PORT_NUMBER)
+        && (ah->oaddr->s_addr == htonl(ntohl(la->special_addr.s_addr)|CTL_DNS)))
+        return (0);
+    return (-1);
+}
+
+static doanswer(struct libalias *la, union dnsmsg_header *hdr,char *qname, struct ip *pip, struct hostent *h)
+{
+    int i;
+    if (h == NULL)
+    {
+        hdr->X.qr = 1; /*response*/
+        hdr->X.aa = 1;
+        hdr->X.rd = 1;
+        hdr->X.rcode = 3;
+    } 
+    else
+    {
+        /*!!! We need to be sure that */
+        struct mbuf *m = NULL;
+        char *query;
+        char *answers;
+        uint16_t off;
+        char **cstr;
+        char *c;
+        uint16_t packet_len = 0;
+        uint16_t addr_off = (uint16_t)~0;
+        
+        m = dtom(la->pData, hdr); 
+        Assert((m));
+        
+#if 0
+        /*here is no compressed names+answers + new query*/
+        m_inc(m, h->h_length * sizeof(struct dnsmsg_answer) + strlen(qname) + 2 * sizeof(uint16_t));
+#endif
+        packet_len = (pip->ip_hl << 2) + sizeof(struct udphdr) + sizeof(union dnsmsg_header) 
+            + strlen(qname) +  2 * sizeof(uint16_t); /* ip + udp + header + query */
+        fprintf(stderr,"got %d addresses for target:%s (m_len: %d)\n", h->h_length, h->h_name, m->m_len);
+        query = (char *)&hdr[1];
+
+        strcpy(query, qname);
+        query += strlen(qname);
+        query ++;
+        
+        *(uint16_t *)query = htons(1);
+        ((uint16_t *)query)[1] = htons(1);
+        answers = (char *)&((uint16_t *)query)[2];
+
+        off = (char *)&hdr[1] - (char *)hdr;
+        off |= (0x3 << 14);
+        /*add aliases */
+        cstr = h->h_aliases;
+        while(*cstr) 
+        {
+            uint16_t len;
+            struct dnsmsg_answer *ans = answers;
+            ans->name = htons(off);
+            ans->type = htons(5); /*CNAME*/
+            ans->class = htons(1);
+            *(uint32_t *)ans->ttl = htonl(3600); /* 1h */
+            c = (addr_off == (uint16_t)~0?h->h_name : *cstr);
+            len = strlen(c) + 2;
+            ans->rdata_len = htons(len);
+            ans->rdata[len - 1] = 0;
+            cstr2qstr(c, ans->rdata);
+            off = (char *)&ans->rdata - (char *)hdr;
+            off |= (0x3 << 14);
+            if (addr_off == (uint16_t)~0)
+                addr_off = off;
+            answers = (char *)&ans[1] + len - 2;  /* note: 1 symbol already counted */
+            packet_len += sizeof(struct dnsmsg_answer) + len - 2;
+            hdr->X.ancount++;
+            cstr++;
+        }
+        /*add addresses */
+
+        for(i = 0; i < h->h_length && h->h_addr_list[i] != NULL; ++i)
+        {
+            struct dnsmsg_answer *ans = answers;
+            
+            ans->name = htons(off);
+            ans->type = htons(1);
+            ans->class = htons(1);
+            *(uint32_t *)ans->ttl = htonl(3600); /* 1h */
+            ans->rdata_len = htons(4); /* IPv4 */
+            *(uint32_t *)ans->rdata = *(uint32_t *)h->h_addr_list[i];
+            answers = (char *)&ans[1] + 2;
+            packet_len += sizeof(struct dnsmsg_answer) + 3;
+            hdr->X.ancount++;
+        }
+        hdr->X.qr = 1; /*response*/
+        hdr->X.aa = 1;
+        hdr->X.rd = 1;
+        hdr->X.ra = 1;
+        hdr->X.rcode = 0;
+        HTONS(hdr->X.ancount);
+        /*don't forget update m_len*/
+        m->m_len = packet_len;
+        pip->ip_len = htons(m->m_len);
+    }
+}
+static int 
+protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah)
+{
+    int i;
+    /*Parse dns request */
+    char *qw_qname = NULL;
+    uint16_t *qw_qtype = NULL;
+    uint16_t *qw_qclass = NULL;
+    struct hostent *h = NULL;
+    char *cname[255]; /* ??? */
+
+    struct udphdr *udp = NULL;
+    union dnsmsg_header *hdr = NULL;
+    udp = ((char *)pip) + (pip->ip_hl << 2);
+    hdr = (union dnsmsg_header *)&udp[1];
+
+    if (hdr->X.qr == 1)
+        return 0; /* this is respose*/
+
+    qw_qname = (char *)&hdr[1];
+    Assert((ntohs(hdr->X.qdcount) == 1));
+
+    for (i = 0; i < ntohs(hdr->X.qdcount); ++i)
+    {
+        qw_qtype = (uint16_t *)(qw_qname + strlen(qw_qname) + 1);
+        qw_qclass = &qw_qtype[1];
+        fprintf(stderr, "qname:%s qtype:%hd qclass:%hd\n", 
+            qw_qname, ntohs(*qw_qtype), ntohs(*qw_qclass));
+    }
+    qstr2cstr(qw_qname, cname);
+    h = gethostbyname(cname);
+    fprintf(stderr, "cname:%s\n", cname);
+    doanswer(la, hdr, qw_qname, pip, h);
+    /*we've chenged size and conten of udp, to avoid double csum calcualtion 
+     *will assign to zero
+     */
+    udp->uh_sum = 0;
+    udp->uh_ulen = ntohs(htons(pip->ip_len) - (pip->ip_hl << 2));
+    pip->ip_sum = 0;
+    pip->ip_sum = LibAliasInternetChecksum(la, pip, pip->ip_hl << 2);
+    return (0);
+}
+/*
+ * qstr is z-string with -dot- replaced with \count to next -dot-
+ * e.g. ya.ru is \02ya\02ru
+ * Note: it's assumed that caller allocates buffer for cstr
+ */
+static void qstr2cstr(char *qname, char *cname)
+{
+    char *q = qname;
+    char *c = cname;
+    while(*q != 0)
+    {
+        if (isalpha(*q) || isdigit(*q))
+        {
+           *c = *q; 
+            c++;
+        }
+        else if (c != &cname[0])
+        {
+            *c = '.';
+            c++;
+        }
+        q++;
+    }
+    q = 0;
+}
+/*
+ *
+ */
+static void cstr2qstr(char *cstr, char *qstr)
+{
+    char *c, *pc, *q;
+    c = cstr;
+    q = qstr; 
+    while(*c != 0)
+    {
+        /* a the begining or at -dot- position */
+        if (*c == '.' || (c == cstr && q == qstr)) 
+        {
+            if (c != cstr) c++;
+            pc = index(c, '.');
+            *q = pc != NULL ? (pc - c) : strlen(c);
+            q++;
+            continue;
+        }
+        (*q) = (*c); /*direct copy*/
+        q++;
+        c++;
+    }
+    q = 0;
+}
+
+
+int
+dns_alias_load(PNATState pData)
+{
+    return dns_alias_handler(pData, MOD_LOAD);
+}
+
+int
+dns_alias_unload(PNATState pData)
+{
+    return dns_alias_handler(pData, MOD_UNLOAD);
+}
+
+#define handlers pData->dns_module
+static int
+dns_alias_handler(PNATState pData, int type)
+{
+    int error;
+    if (handlers == NULL)
+        handlers = RTMemAllocZ(2 * sizeof(struct proto_handler));
+    handlers[0].pri = 20;
+    handlers[0].dir = IN;
+    handlers[0].proto = UDP;
+    handlers[0].fingerprint = &fingerprint;
+    handlers[0].protohandler = &protohandler;
+    handlers[1].pri = EOH;
+
+    switch (type) {   
+    case MOD_LOAD:
+        error = 0;
+        LibAliasAttachHandlers(pData, handlers);
+        break;
+    case MOD_UNLOAD:
+        error = 0;
+        LibAliasDetachHandlers(pData, handlers);
+        RTMemFree(handlers);
+        handlers = NULL;
+        break;
+    default:
+        error = EINVAL;
+    }
+    return (error);
+}
Index: /trunk/src/VBox/Devices/Network/slirp/slirp.c
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 22842)
+++ /trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 22843)
@@ -207,4 +207,5 @@
 };
 
+
 #ifdef RT_OS_WINDOWS
 static int get_dns_addr_domain(PNATState pData, bool fVerbose,
@@ -340,4 +341,5 @@
     int found = 0;
     struct in_addr tmp_addr;
+    int nameservers = 0;
 
 #ifdef RT_OS_OS2
@@ -441,4 +443,27 @@
 
 #endif
+
+static void alias_init(PNATState pData, struct libalias **pla, int la_flags, struct in_addr addr)
+{
+        int flags = 0;
+        struct libalias *la;
+        la = LibAliasInit(pData, NULL);
+        if (la == NULL)
+        {
+            LogRel(("NAT: LibAlias default rule wasn't initialized\n"));
+            AssertMsgFailed(("NAT: LibAlias default rule wasn't initialized\n"));
+        }
+        flags = LibAliasSetMode(la, 0, 0);
+#ifndef NO_FW_PUNCH
+        flags |= PKT_ALIAS_PUNCH_FW;
+#endif
+#ifdef DEBUG
+        flags |= PKT_ALIAS_LOG; /* set logging */
+#endif
+        flags |= la_flags;
+        flags = LibAliasSetMode(la, flags, ~0);
+        LibAliasSetAddress(la, addr);
+        *pla = la;
+}
 
 static int slirp_init_dns_list(PNATState pData)
@@ -539,5 +564,5 @@
 
     /* set default addresses */
-    inet_aton("127.0.0.1", &loopback_addr);
+    loopback_addr.s_addr = INADDR_LOOPBACK;
     if (slirp_init_dns_list(pData) < 0)
         fNATfailed = 1;
@@ -547,22 +572,16 @@
     getouraddr(pData);
     {
-        int flags = 0;
         struct in_addr proxy_addr;
-        pData->proxy_alias = LibAliasInit(pData, NULL);
-        if (pData->proxy_alias == NULL)
-        {
-            LogRel(("NAT: LibAlias default rule wasn't initialized\n"));
-            AssertMsgFailed(("NAT: LibAlias default rule wasn't initialized\n"));
-        }
-        flags = LibAliasSetMode(pData->proxy_alias, 0, 0);
-#ifndef NO_FW_PUNCH
-        flags |= PKT_ALIAS_PUNCH_FW;
-#endif
-        flags |= PKT_ALIAS_LOG; /* set logging */
-        flags = LibAliasSetMode(pData->proxy_alias, flags, ~0);
         proxy_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
-        LibAliasSetAddress(pData->proxy_alias, proxy_addr);
+        alias_init(pData, &pData->proxy_alias, 0, proxy_addr);
+
+#if 0
+        proxy_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
+        alias_init(pData, &pData->dns_alias, PKT_ALIAS_REVERSE, proxy_addr);
+#endif
+
         ftp_alias_load(pData);
         nbt_alias_load(pData);
+        dns_alias_load(pData);
     }
     return fNATfailed ? VINF_NAT_DNS : VINF_SUCCESS;
@@ -643,4 +662,5 @@
     ftp_alias_unload(pData);
     nbt_alias_unload(pData);
+    dns_alias_unload(pData);
     while(!LIST_EMPTY(&instancehead)) 
     {
@@ -1637,12 +1657,8 @@
         psin = (struct sockaddr_in *)&sa;
 
-        lib = LibAliasInit(pData, NULL);
-        flags = LibAliasSetMode(lib, 0, 0);
-        flags |= PKT_ALIAS_LOG; /* set logging */
-        flags |= PKT_ALIAS_REVERSE; /* set logging */
-        flags = LibAliasSetMode(lib, flags, ~0);
 
         alias.s_addr =  htonl(ntohl(guest_addr) | CTL_ALIAS);
-        link = LibAliasRedirectPort(lib, psin->sin_addr, htons(rule->host_port),
+        alias_init(pData, &so->so_la, PKT_ALIAS_REVERSE, alias);
+        link = LibAliasRedirectPort(so->so_la, psin->sin_addr, htons(rule->host_port),
             alias, htons(rule->guest_port),
             special_addr,  -1, /* not very clear for now*/
@@ -1654,5 +1670,4 @@
             goto remove_port_forwarding;
         }
-        so->so_la = lib;
         rule->activated = 1;
         continue;
Index: /trunk/src/VBox/Devices/Network/slirp/slirp.h
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/slirp.h	(revision 22842)
+++ /trunk/src/VBox/Devices/Network/slirp/slirp.h	(revision 22843)
@@ -388,5 +388,5 @@
     RTStrPrintfV(buffer, 1024, format, args);
 
-#if defined(DEBUG_vvl) && 0
+#if defined(DEBUG_vvl)
     LogRel(("NAT:ALIAS: %s\n", buffer));
 #else
@@ -415,5 +415,6 @@
 int nbt_alias_load(PNATState);
 int nbt_alias_unload(PNATState);
-
+int dns_alias_load(PNATState);
+int dns_alias_unload(PNATState);
 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 *);
Index: /trunk/src/VBox/Devices/Network/slirp/slirp_state.h
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/slirp_state.h	(revision 22842)
+++ /trunk/src/VBox/Devices/Network/slirp/slirp_state.h	(revision 22843)
@@ -249,4 +249,5 @@
     LIST_HEAD(RT_NOTHING, libalias) instancehead;
     struct libalias *proxy_alias;
+    struct libalias *dns_alias;
     LIST_HEAD(handler_chain, proto_handler) handler_chain;
     struct port_forward_rule_list port_forward_rule_head;
@@ -256,4 +257,5 @@
     struct proto_handler *ftp_module;
     struct proto_handler *nbt_module;
+    struct proto_handler *dns_module;
 
 #define PROFILE_COUNTER(name, dsc)     STAMPROFILE Stat ## name
Index: /trunk/src/VBox/Devices/Network/slirp/udp.c
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/udp.c	(revision 22842)
+++ /trunk/src/VBox/Devices/Network/slirp/udp.c	(revision 22843)
@@ -107,4 +107,6 @@
      */
     len = ntohs((u_int16_t)uh->uh_ulen);
+    Assert((ip->ip_len == len));
+    Assert((ip->ip_len + iphlen == m->m_len));
 
     if (ip->ip_len != len)
@@ -159,4 +161,19 @@
     }
 
+    if (   ntohs(uh->uh_dport) == 53
+        && CTL_CHECK(ntohl(ip->ip_dst.s_addr), CTL_DNS))
+    {
+        struct sockaddr_in dst, src;
+        src.sin_addr.s_addr = ip->ip_dst.s_addr;
+        src.sin_port = uh->uh_dport;
+        dst.sin_addr.s_addr = ip->ip_src.s_addr;
+        dst.sin_port = uh->uh_sport;
+        /* udp_output2 will do opposite operations on mbuf*/
+        
+        m->m_data += sizeof(struct udpiphdr);
+        m->m_len -= sizeof(struct udpiphdr);
+        udp_output2(pData, NULL, m, &src, &dst, IPTOS_LOWDELAY);
+        goto bad;
+    }
     /*
      *  handle TFTP
@@ -234,4 +251,5 @@
      * DNS proxy
      */
+#if 0
     if (   (ip->ip_dst.s_addr == htonl(ntohl(special_addr.s_addr) | CTL_DNS))
         && (ntohs(uh->uh_dport) == 53)) 
@@ -240,4 +258,5 @@
         goto bad; /* it isn't bad, probably better to add additional label done for boot/tftf :)  */
     }
+#endif
 
     iphlen += sizeof(struct udphdr);
