From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MThlV-0002Ep-KR for qemu-devel@nongnu.org; Wed, 22 Jul 2009 15:46:13 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MThlR-0002An-JL for qemu-devel@nongnu.org; Wed, 22 Jul 2009 15:46:13 -0400 Received: from [199.232.76.173] (port=32805 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MThlQ-0002AX-M6 for qemu-devel@nongnu.org; Wed, 22 Jul 2009 15:46:09 -0400 Received: from mail-px0-f201.google.com ([209.85.216.201]:35404) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MThlQ-0005YF-4g for qemu-devel@nongnu.org; Wed, 22 Jul 2009 15:46:08 -0400 Received: by pxi39 with SMTP id 39so282227pxi.4 for ; Wed, 22 Jul 2009 12:46:06 -0700 (PDT) From: Ed Swierk In-Reply-To: <4A67610F.5090204@web.de> References: <1248285441.30567.12.camel@localhost.localdomain> <4A67610F.5090204@web.de> Content-Type: text/plain Date: Wed, 22 Jul 2009 12:45:57 -0700 Message-Id: <1248291957.3841.10.camel@localhost.localdomain> Mime-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] Re: [PATCH] slirp: Read host DNS config on demand List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Jan Kiszka Cc: qemu-devel@nongnu.org On Wed, 2009-07-22 at 20:57 +0200, Jan Kiszka wrote: > Nice. I noticed this, too, and shortly thought about some possible > fixes. Don't know why I dropped it again. Anyway, your approach looks > straightforward. Please rebase over git head, and I will happily test > and ack it! FYI there are two other things that tend to break on laptops especially: - If the system clock jumps backwards, functions that rely on gettimeofday() for computing a time interval get confused. gettimeofday() should be replaced with clock_gettime(CLOCK_MONOTONIC). Hopefully all Unixy platforms support it? - Storing the address of some random host interface in our_addr is bad for the same reason as storing the address of the DNS server. Fortunately most references to our_addr are in dead code, and the remaining ones are questionable. Anyway, here's the updated patch for the DNS issue. - Currently the qemu user-mode networking stack reads the host DNS configuration (/etc/resolv.conf or the Windows equivalent) only once when qemu starts. This causes name lookups in the guest to fail if the host is moved to a different network from which the original DNS servers are unreachable, a common occurrence when the host is a laptop. This patch changes the slirp code to read the host DNS configuration on demand, caching the results for 10 seconds to avoid unnecessary overhead if name lookups occur in rapid succession. Signed-off-by: Ed Swierk --- diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c index 95a4b39..751a8e2 100644 --- a/slirp/ip_icmp.c +++ b/slirp/ip_icmp.c @@ -127,7 +127,8 @@ icmp_input(struct mbuf *m, int hlen) slirp->vnetwork_addr.s_addr) { /* It's an alias */ if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { - addr.sin_addr = dns_addr; + if (get_dns_addr(&addr.sin_addr) < 0) + addr.sin_addr = loopback_addr; } else { addr.sin_addr = loopback_addr; } diff --git a/slirp/libslirp.h b/slirp/libslirp.h index 3bcc392..4b00a97 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -8,6 +8,8 @@ struct Slirp; typedef struct Slirp Slirp; +int get_dns_addr(struct in_addr *pdns_addr); + Slirp *slirp_init(int restricted, struct in_addr vnetwork, struct in_addr vnetmask, struct in_addr vhost, const char *vhostname, const char *tftp_path, diff --git a/slirp/main.h b/slirp/main.h index 28d92d8..e87b068 100644 --- a/slirp/main.h +++ b/slirp/main.h @@ -32,7 +32,6 @@ extern u_int curtime; extern fd_set *global_readfds, *global_writefds, *global_xfds; extern struct in_addr our_addr; extern struct in_addr loopback_addr; -extern struct in_addr dns_addr; extern char *username; extern char *socket_path; extern int towrite_max; diff --git a/slirp/slirp.c b/slirp/slirp.c index 0ce62a3..4bc8a9d 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -28,8 +28,6 @@ /* host address */ struct in_addr our_addr; -/* host dns address */ -struct in_addr dns_addr; /* host loopback address */ struct in_addr loopback_addr; @@ -50,9 +48,12 @@ static int do_slowtimo; TAILQ_HEAD(slirp_instances, Slirp) slirp_instances = TAILQ_HEAD_INITIALIZER(slirp_instances); +struct in_addr dns_addr = { 0 }; +u_int dns_addr_time = 0; + #ifdef _WIN32 -static int get_dns_addr(struct in_addr *pdns_addr) +int get_dns_addr(struct in_addr *pdns_addr) { FIXED_INFO *FixedInfo=NULL; ULONG BufLen; @@ -60,6 +61,11 @@ static int get_dns_addr(struct in_addr *pdns_addr) IP_ADDR_STRING *pIPAddr; struct in_addr tmp_addr; + if (dns_addr.s_addr != 0 && (curtime - dns_addr_time) < 10000) { + *pdns_addr = dns_addr; + return 0; + } + FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO)); BufLen = sizeof(FIXED_INFO); @@ -83,6 +89,8 @@ static int get_dns_addr(struct in_addr *pdns_addr) pIPAddr = &(FixedInfo->DnsServerList); inet_aton(pIPAddr->IpAddress.String, &tmp_addr); *pdns_addr = tmp_addr; + dns_addr = tmp_addr; + dns_addr_time = curtime; if (FixedInfo) { GlobalFree(FixedInfo); FixedInfo = NULL; @@ -97,7 +105,7 @@ static void winsock_cleanup(void) #else -static int get_dns_addr(struct in_addr *pdns_addr) +int get_dns_addr(struct in_addr *pdns_addr) { char buff[512]; char buff2[257]; @@ -105,6 +113,11 @@ static int get_dns_addr(struct in_addr *pdns_addr) int found = 0; struct in_addr tmp_addr; + if (dns_addr.s_addr != 0 && (curtime - dns_addr_time) < 10000) { + *pdns_addr = dns_addr; + return 0; + } + f = fopen("/etc/resolv.conf", "r"); if (!f) return -1; @@ -119,8 +132,11 @@ static int get_dns_addr(struct in_addr *pdns_addr) if (tmp_addr.s_addr == loopback_addr.s_addr) tmp_addr = our_addr; /* If it's the first one, set it to dns_addr */ - if (!found) + if (!found) { *pdns_addr = tmp_addr; + dns_addr = tmp_addr; + dns_addr_time = curtime; + } #ifdef DEBUG else lprint(", "); @@ -176,11 +192,6 @@ static void slirp_init_once(void) if (our_addr.s_addr == 0) { our_addr = loopback_addr; } - - /* FIXME: This address may change during runtime */ - if (get_dns_addr(&dns_addr) < 0) { - dns_addr = loopback_addr; - } } static void slirp_state_save(QEMUFile *f, void *opaque); diff --git a/slirp/socket.c b/slirp/socket.c index d8fbe89..207109c 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -552,7 +552,8 @@ sosendto(struct socket *so, struct mbuf *m) slirp->vnetwork_addr.s_addr) { /* It's an alias */ if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { - addr.sin_addr = dns_addr; + if (get_dns_addr(&addr.sin_addr) < 0) + addr.sin_addr = loopback_addr; } else { addr.sin_addr = loopback_addr; } diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index 51b3834..0417345 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -340,7 +340,8 @@ int tcp_fconnect(struct socket *so) slirp->vnetwork_addr.s_addr) { /* It's an alias */ if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { - addr.sin_addr = dns_addr; + if (get_dns_addr(&addr.sin_addr) < 0) + addr.sin_addr = loopback_addr; } else { addr.sin_addr = loopback_addr; }