Index: trunk/src/VBox/Devices/Network/slirp/dnsproxy/dnsproxy.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/dnsproxy/dnsproxy.c	(revision 45323)
+++ trunk/src/VBox/Devices/Network/slirp/dnsproxy/dnsproxy.c	(revision 45324)
@@ -129,6 +129,7 @@
     /* be paranoid */
     AssertPtrReturnVoid(arg);
+    
     de = TAILQ_PREV(req->dns_server, dns_list_head, de_list);
-    /* here we should check if we reached the end of the DNS server list */
+    
     if (de == NULL)
     {
@@ -140,32 +141,14 @@
     else
     {
-        /* Note: so will be deleted after we create new one (so1)
-         * to make attempt on the next server.
-         */
         struct ip *ip;
         struct udphdr *udp;
         int iphlen;
-        struct socket *so1 = socreate();
         struct mbuf *m = NULL;
         char *data;
-
-        if (so1 == NULL)
-        {
-            LogRel(("NAT: can't create DNS socket\n"));
-            goto socket_clean_up;
-        }
-
-        if(udp_attach(pData, so1) == -1)
-        {
-            LogRel(("NAT: can't attach udp socket\n"));
-            sofree(pData, so1);
-            goto socket_clean_up;
-        }
-
+        
         m = slirpDnsMbufAlloc(pData);
         if (m == NULL)
         {
             LogRel(("NAT: Can't allocate mbuf\n"));
-            udp_detach(pData, so1);
             goto socket_clean_up;
         }
@@ -187,16 +170,15 @@
         udp->uh_dport = ntohs(53);
         udp->uh_sport = so->so_lport;
+
         memcpy(data, req->byte, req->nbyte); /* coping initial req */
 
-        so1->so_laddr = so->so_laddr;
-        so1->so_lport = so->so_lport;
-        so1->so_faddr = so->so_faddr;
-        so1->so_fport = so->so_fport;
-
+        /* req points to so->so_timeout_arg */
         req->dns_server = de;
-        so1->so_timeout_arg = req;
-        so1->so_timeout = timeout;
-
-        dnsproxy_query(pData, so1, m, iphlen);
+
+        /* expiration will be bumped in dnsproxy_query */
+        
+        dnsproxy_query(pData, so, m, iphlen);
+        /* should we free so->so_m ? */
+        return;
     }
  
@@ -263,17 +245,4 @@
         return;
     }
-#else
-    ip = mtod(m, struct ip *);
-    udp = (struct udphdr *)(m->m_data + iphlen);
-
-    fromaddr.sin_addr.s_addr = ip->ip_src.s_addr;
-    fromaddr.sin_port = udp->uh_sport;
-    fromaddr.sin_family = AF_INET;
-
-    iphlen += sizeof (struct udphdr);
-    byte = m->m_len - iphlen;  /* size of IP header + udp header size */
-    /* the validness of ip and udp header has been already checked so we shouldn't care if */
-    buf = m->m_data + iphlen;
-#endif
 
     /* check for minimum dns packet length */
@@ -284,5 +253,4 @@
     }
 
-#ifndef VBOX
     /* allocate new request */
     if ((req = calloc(1, sizeof(struct request))) == NULL) {
@@ -295,19 +263,104 @@
     memcpy(&req->client, &fromaddr, sizeof(struct sockaddr_in));
     memcpy(&req->clientid, &buf[0], 2);
-#else
-    /* allocate new request */
-    req = so->so_timeout_arg; /* in slirp we might re-send the query*/
-    if (req == NULL)
+
+    /* where is this query coming from? */
+    if (is_internal(pData, fromaddr.sin_addr)) {
+        req->recursion = RD(buf);
+        DPRINTF(("Internal query RD=%d\n", req->recursion));
+    } else {
+        /* no recursion for foreigners */
+        req->recursion = 0;
+        DPRINTF(("External query RD=%d\n", RD(buf)));
+    }
+
+    /* insert it into the hash table */
+    hash_add_request(pData, req);
+
+    /* overwrite the original query id */
+    memcpy(&buf[0], &req->id, 2);
+
+    if (req->recursion) {
+
+        /* recursive queries timeout in 90s */
+        event_set(&req->timeout, -1, 0, timeout, req);
+        tv.tv_sec=recursive_timeout; tv.tv_usec=0;
+        event_add(&req->timeout, &tv);
+
+        /* send it to our recursive server */
+        if ((byte = sendto(sock_answer, buf, (unsigned int)byte, 0,
+                    (struct sockaddr *)&recursive_addr,
+                    sizeof(struct sockaddr_in))) == -1) {
+            LogRel(("sendto failed: %s\n", strerror(errno)));
+            ++dropped_queries;
+            return;
+        }
+
+        ++recursive_queries;
+
+    } else {
+
+        /* authoritative queries timeout in 10s */
+        event_set(&req->timeout, -1, 0, timeout, req);
+        tv.tv_sec=authoritative_timeout; tv.tv_usec=0;
+        event_add(&req->timeout, &tv);
+
+        /* send it to our authoritative server */
+        if ((byte = sendto(sock_answer, buf, (unsigned int)byte, 0,
+                    (struct sockaddr *)&authoritative_addr,
+                    sizeof(struct sockaddr_in))) == -1) {
+            LogRel(("sendto failed: %s\n", strerror(errno)));
+            ++dropped_queries;
+            return;
+        }
+        ++authoritative_queries;
+    }
+
+#else /* VBOX */
+    AssertPtr(pData);
+    
+    /* m->m_data points to IP header */
+#if 0
+    /* XXX: for some reason it make gdb ill,
+     * it good to have this assert here with assumption above.
+     */
+    M_ASSERTPKTHDR(m);
+#endif
+
+    ip = mtod(m, struct ip *);
+    udp = (struct udphdr *)(m->m_data + iphlen);
+
+    fromaddr.sin_addr.s_addr = ip->ip_src.s_addr;
+    fromaddr.sin_port = udp->uh_sport;
+    fromaddr.sin_family = AF_INET;
+
+    /* iphlen equals to lenght of ip header */
+    Assert(iphlen == sizeof(struct ip));
+    iphlen += sizeof (struct udphdr);
+
+    byte = m->m_len - iphlen;
+    buf = m->m_data + iphlen;
+
+    /* check for minimum dns packet length */
+    if (byte < 12) {
+        LogRel(("query too short from %RTnaipv4\n", fromaddr.sin_addr));
+        ++dropped_queries;
+        return;
+    }
+
+
+    req = so->so_timeout_arg; 
+
+    if (!req)
     {
-        if ((req = RTMemAllocZ(sizeof(struct request) + byte)) == NULL) {
+
+        Assert(!so->so_timeout_arg);
+
+        if ((req = RTMemAllocZ(sizeof(struct request) + byte)) == NULL) 
+        {
             LogRel(("calloc failed\n"));
             ++dropped_queries;
             return;
         }
-    }
-
-    /* fill the request structure */
-    if (so->so_timeout_arg == NULL)
-    {
+
         req->id = QUERYID;
         memcpy(&req->client, &fromaddr, sizeof(struct sockaddr_in));
@@ -319,7 +372,7 @@
             RTMemFree(req);
             if (fail_counter == 0)
-                LogRel(("NAT/dnsproxy: Empty DNS entry (suppressed 100 times)\n"));
+              LogRel(("NAT/dnsproxy: Empty DNS entry (suppressed 100 times)\n"));
             else
-                fail_counter = (fail_counter == 100 ? 0 : fail_counter + 1);
+              fail_counter = (fail_counter == 100 ? 0 : fail_counter + 1);
             return;
 
@@ -333,89 +386,59 @@
     else
     {
-        retransmit = 1;
-    }
-#endif
-
-#ifndef VBOX
-    /* where is this query coming from? */
-    if (is_internal(pData, fromaddr.sin_addr)) {
-        req->recursion = RD(buf);
-        DPRINTF(("Internal query RD=%d\n", req->recursion));
-    } else {
-        /* no recursion for foreigners */
-        req->recursion = 0;
-        DPRINTF(("External query RD=%d\n", RD(buf)));
-    }
-
-    /* insert it into the hash table */
-    hash_add_request(pData, req);
-#else
+         retransmit = 1;
+    }
+
     req->recursion = 0;
+        
     DPRINTF(("External query RD=%d\n", RD(buf)));
+        
     if (retransmit == 0)
         hash_add_request(pData, req);
-#endif
+
 
     /* overwrite the original query id */
     memcpy(&buf[0], &req->id, 2);
 
-#ifndef VBOX
-    if (req->recursion) {
-
-        /* recursive queries timeout in 90s */
-        event_set(&req->timeout, -1, 0, timeout, req);
-        tv.tv_sec=recursive_timeout; tv.tv_usec=0;
-        event_add(&req->timeout, &tv);
-
-        /* send it to our recursive server */
-        if ((byte = sendto(sock_answer, buf, (unsigned int)byte, 0,
-                    (struct sockaddr *)&recursive_addr,
-                    sizeof(struct sockaddr_in))) == -1) {
-            LogRel(("sendto failed: %s\n", strerror(errno)));
-            ++dropped_queries;
-            return;
-        }
-
-        ++recursive_queries;
-
-    } else {
-
-        /* authoritative queries timeout in 10s */
-        event_set(&req->timeout, -1, 0, timeout, req);
-        tv.tv_sec=authoritative_timeout; tv.tv_usec=0;
-        event_add(&req->timeout, &tv);
-
-        /* send it to our authoritative server */
-        if ((byte = sendto(sock_answer, buf, (unsigned int)byte, 0,
-                    (struct sockaddr *)&authoritative_addr,
-                    sizeof(struct sockaddr_in))) == -1) {
-            LogRel(("sendto failed: %s\n", strerror(errno)));
-            ++dropped_queries;
-            return;
-        }
-
-#else
-        so->so_expire = curtime + recursive_timeout * 1000; /* let's slirp to care about expiration */
-        memset(&addr, 0, sizeof(struct sockaddr_in));
-        addr.sin_family = AF_INET;
-        addr.sin_addr.s_addr  = req->dns_server->de_addr.s_addr;
-        addr.sin_port = htons(53);
-        so->so_expire = curtime + recursive_timeout * 1000; /* let's slirp to care about expiration */
-        /* send it to our authoritative server */
-        Log2(("NAT: request will be sent to %RTnaipv4 on %R[natsock]\n", addr.sin_addr, so));
-        if ((byte = sendto(so->s, buf, (unsigned int)byte, 0,
-                    (struct sockaddr *)&addr,
-                    sizeof(struct sockaddr_in))) == -1) {
-            LogRel(("sendto failed: %s\n", strerror(errno)));
-            ++dropped_queries;
-            return;
-        }
-        so->so_state = SS_ISFCONNECTED; /* now it's selected */
-        Log2(("NAT: request was sent to %RTnaipv4 on %R[natsock]\n", addr.sin_addr, so));
-#endif
-        ++authoritative_queries;
-#ifndef VBOX
-    }
-#endif
+    /* let's slirp to care about expiration */
+    so->so_expire = curtime + recursive_timeout * 1000;
+ 
+    memset(&addr, 0, sizeof(struct sockaddr_in));
+    addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr  = req->dns_server->de_addr.s_addr;
+    addr.sin_port = htons(53);
+
+    /* send it to our authoritative server */
+    Log2(("NAT: request will be sent to %RTnaipv4 on %R[natsock]\n", addr.sin_addr, so));
+    
+    byte = sendto(so->s, buf, (unsigned int)byte, 0,
+                  (struct sockaddr *)&addr,
+                  sizeof(struct sockaddr_in));
+    if (byte == -1) 
+    {
+        /* XXX: is it really enough? */
+        LogRel(("sendto failed: %s\n", strerror(errno)));
+        ++dropped_queries;
+        return;
+    }
+
+    so->so_state = SS_ISFCONNECTED; /* now it's selected */
+    Log2(("NAT: request was sent to %RTnaipv4 on %R[natsock]\n", addr.sin_addr, so));
+
+    ++authoritative_queries;
+
+# if 0    
+    /* XXX: this stuff for _debugging_ only, 
+     * first enforce guest to send next request 
+     * and second for faster getting timeout callback 
+     * other option is adding couple entries in resolv.conf with 
+     * invalid nameservers.
+     *
+     * For testing purposes could be used 
+     * namebench -S -q 10000 -m random or -m chunk 
+     */
+    /* RTThreadSleep(3000); */
+    /* curtime += 300; */
+# endif
+#endif /* VBOX */
 }
 
@@ -451,11 +474,4 @@
         return;
     }
-#else
-    char *buf;
-    int byte;
-    struct request *query = NULL;
-    byte = m->m_len;
-    buf = mtod(m, char *);
-#endif
 
     /* check for minimum dns packet length */
@@ -467,16 +483,4 @@
 
     /* find corresponding query */
-#ifdef VBOX
-    if ((query = hash_find_request(pData, *((unsigned short *)buf))) == NULL) {
-        ++late_answers;
-        /* Probably, this request wasn't serviced by
-         * dnsproxy so we won't care about it here*/
-        so->so_expire = curtime + SO_EXPIREFAST;
-        Log2(("NAT: query wasn't found\n"));
-        return;
-    }
-    so->so_timeout = NULL;
-    so->so_timeout_arg = NULL;
-#else
     if ((query = hash_find_request(pData, *((unsigned short *)&buf))) == NULL) {
         ++late_answers;
@@ -484,5 +488,5 @@
     }
     event_del(&query->timeout);
-#endif
+
     hash_remove_request(pData, query);
 
@@ -490,7 +494,4 @@
     memcpy(&buf[0], &query->clientid, 2);
 
-#ifndef VBOX
-    /* Slirp: will send mbuf to guest by itself */
-    /* send answer back to querying host */
     if (sendto(sock_query, buf, (unsigned int)byte, 0,
                 (struct sockaddr *)&query->client,
@@ -498,18 +499,73 @@
         LogRel(("sendto failed: %s\n", strerror(errno)));
         ++dropped_answers;
-    } else
+    } 
+    else
         ++answered_queries;
 
     free(query);
-#else
+#else /* VBOX */
+
+    char *buf = NULL;
+    int byte = 0;
+    struct request *query = NULL;
+
+    AssertPtr(pData);
+    
+    /* XXX: mbuf->data points to ??? */
+    byte = m->m_len;
+    buf = mtod(m, char *);
+
+    /* check for minimum dns packet length */
+    if (byte < 12) {
+        LogRel(("answer too short\n"));
+        ++dropped_answers;
+        return;
+    }
+
+    query = hash_find_request(pData, *((unsigned short *)buf));
+
+    /* find corresponding query */
+    if (query == NULL) 
+    {
+        /* XXX: if we haven't found anything for this request ... 
+         * What we are expecting later?
+         */
+        ++late_answers;
+        so->so_expire = curtime + SO_EXPIREFAST;
+        Log2(("NAT: query wasn't found\n"));
+        return;
+    }
+
+    so->so_timeout = NULL;
+    so->so_timeout_arg = NULL;
+
+    hash_remove_request(pData, query);
+
+    /* restore original query id */
+    memcpy(&buf[0], &query->clientid, 2);
+
     ++answered_queries;
 
     RTMemFree(query);
-#endif
+#endif /* VBOX */
 }
 
+
+#ifdef VBOX
+int
+dnsproxy_init(PNATState pData)
+{
+    /* globals initialization */
+    authoritative_port = 53;
+    authoritative_timeout = 10;
+    recursive_port = 53;
+    recursive_timeout = 2;
+    stats_timeout = 3600;
+    dns_port = 53;
+    return 0;
+}
+#else /* !VBOX */
 /* main -- dnsproxy main function
  */
-#ifndef VBOX
 int
 main(int argc, char *argv[])
@@ -671,16 +727,3 @@
 
 }
-#else
-int
-dnsproxy_init(PNATState pData)
-{
-    /* globals initialization */
-    authoritative_port = 53;
-    authoritative_timeout = 10;
-    recursive_port = 53;
-    recursive_timeout = 2;
-    stats_timeout = 3600;
-    dns_port = 53;
-    return 0;
-}
-#endif
+#endif
