diff options
author | Ed Swierk <eswierk@aristanetworks.com> | 2009-08-20 19:00:31 -0700 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2009-08-27 20:46:58 -0500 |
commit | df7a86ed735eafefbd046c8cad7134652fe3f600 (patch) | |
tree | 585563918d17462f707cebdae337d5fcde45d927 /slirp/slirp.c | |
parent | ce0bd027df9c62766a5417521d0f08f27359d43f (diff) |
slirp: Read host DNS config on demand
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 at most 1 second to avoid unnecessary
overhead if name lookups occur in rapid succession. On non-Windows
hosts, /etc/resolv.conf is re-read only if the file has been replaced or
if its size or mtime has changed.
Signed-off-by: Ed Swierk <eswierk@aristanetworks.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'slirp/slirp.c')
-rw-r--r-- | slirp/slirp.c | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/slirp/slirp.c b/slirp/slirp.c index da04ad19c8..b5335a54ac 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -27,8 +27,6 @@ #include "slirp.h" #include "hw/hw.h" -/* host dns address */ -struct in_addr dns_addr; /* host loopback address */ struct in_addr loopback_addr; @@ -49,9 +47,12 @@ static int do_slowtimo; static 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; @@ -59,6 +60,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) < 1000) { + *pdns_addr = dns_addr; + return 0; + } + FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO)); BufLen = sizeof(FIXED_INFO); @@ -82,6 +88,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; @@ -96,7 +104,9 @@ static void winsock_cleanup(void) #else -static int get_dns_addr(struct in_addr *pdns_addr) +struct stat dns_addr_stat; + +int get_dns_addr(struct in_addr *pdns_addr) { char buff[512]; char buff2[257]; @@ -104,6 +114,24 @@ static int get_dns_addr(struct in_addr *pdns_addr) int found = 0; struct in_addr tmp_addr; + if (dns_addr.s_addr != 0) { + struct stat old_stat; + if ((curtime - dns_addr_time) < 1000) { + *pdns_addr = dns_addr; + return 0; + } + old_stat = dns_addr_stat; + if (stat("/etc/resolv.conf", &dns_addr_stat) != 0) + return -1; + if ((dns_addr_stat.st_dev == old_stat.st_dev) + && (dns_addr_stat.st_ino == old_stat.st_ino) + && (dns_addr_stat.st_size == old_stat.st_size) + && (dns_addr_stat.st_mtime == old_stat.st_mtime)) { + *pdns_addr = dns_addr; + return 0; + } + } + f = fopen("/etc/resolv.conf", "r"); if (!f) return -1; @@ -116,8 +144,11 @@ static int get_dns_addr(struct in_addr *pdns_addr) if (!inet_aton(buff2, &tmp_addr)) continue; /* 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(", "); @@ -160,11 +191,6 @@ static void slirp_init_once(void) #endif loopback_addr.s_addr = htonl(INADDR_LOOPBACK); - - /* 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); |