diff mbox

dns server not working in QEMU using usermode networking (SLIRP)

Message ID 20170429220156.bb4hdlsaf6zzqmtw@var.youpi.perso.aquilenet.fr
State New
Headers show

Commit Message

Samuel Thibault April 29, 2017, 10:01 p.m. UTC
FONNEMANN Mark, on sam. 29 avril 2017 20:06:09 +0000, wrote:
> [mfonnemann@localhost qemu]$ /usr/local/bin/qemu-system-i386 -display curses -readconfig qemu.cfg -D logfile

Ah, you are using curses... I've been putting logs onto stderr for
simplicity, not the proper qemu logs. Here is a fixed patch to get
output in the log.

Samuel

Comments

FONNEMANN Mark April 29, 2017, 11:15 p.m. UTC | #1
>Ah, you are using curses... I've been putting logs onto stderr for simplicity, not the proper qemu logs. Here is a fixed patch to get output in the log.

OK, I have an interesting development that I hope will shed some light on the problem.
This configuration works using a different image (nslookup succeeds and I can see your debug output):

[mfonnemann@desktopPC qemu]$ /usr/local/bin/qemu-system-i386 -display curses -readconfig works.cfg --enable-kvm
                   [mfonnemann@localhost ~]$ nslookup www.google.com
                   UDP packet for DNS server
                                            translating 302000a against ffffff 302000a
                                                                                      it's an alias
                                                                                                   it's DNS
                                                                                                           dns_addr is cached: 1020204
               got Server:conf entr10.0.2.3.1'
                   Address:        10.0.2.3#53

                   Non-authoritative answer:
                   Name:   www.google.com
                   Address: 172.217.10.68
 [mfonnemann@desktopPC qemu]$ cat works.cfg
[drive]
  format = "raw"
  file = "fc5.img"

[drive]
  format = "vhdx"
  file = "placeholder2.vhdx"

[drive]
  format = "raw"
  file = "swap_512m.img"

[drive]
  format = "vhdx"
  file = "placeholder.vhdx"

[machine]
  usb = "on"

[memory]
  size = "2G"

[smp-opts]
  cpus = "2"

But my original one still does not:

[mfonnemann@desktopPC qemu]$ /usr/local/bin/qemu-system-i386 -display curses -readconfig NG.cfg --enable-kvm
root@qemu:~# nslookup www.google.com
                   *** Unknown host

                   nslookup: www.google.com: Unknown host
                   root@qemu:~# 
[mfonnemann@desktopPC qemu]$ cat NG.cfg
[drive]
  format = "raw"
  file = "qemu_rootfs_512.img"

[drive]
  format = "raw"
  file = "placeholder2.vhdx"

[drive]
  format = "raw"
  file = "swap_512m.img"

[drive]
  format = "vhdx"
  file = "placeholder.vhdx"

[machine]
  usb = "on"
  initrd = "initrd-2.6.11.12.img.gz"
  kernel = "vmlinuz-2.6.11.12-vanilla.bz"
  append = "root=/dev/hda"

[memory]
  size = "2G"

[smp-opts]
  cpus = "2"

Both are using static IP addresses.

Mark.
Samuel Thibault April 30, 2017, 7:50 a.m. UTC | #2
FONNEMANN Mark, on sam. 29 avril 2017 23:15:08 +0000, wrote:
> [mfonnemann@desktopPC qemu]$ /usr/local/bin/qemu-system-i386 -display curses -readconfig NG.cfg --enable-kvm

Could you show us your NG.cfg, your guest /sbin/ifconfig and /sbin/route
output and /etc/resolv.conf content for that host?

Samuel
FONNEMANN Mark April 30, 2017, 12:42 p.m. UTC | #3
>Could you show us your NG.cfg, your guest /sbin/ifconfig and /sbin/route output and /etc/resolv.conf >content for that host?

[mfonnemann@desktopPC qemu]$ cat NG.cfg
[drive]
  format = "raw"
  file = "qemu_rootfs_512.img"

[drive]
  format = "raw"
  file = "placeholder2.vhdx"

[drive]
  format = "raw"
  file = "swap_512m.img"

[drive]
  format = "vhdx"
  file = "placeholder.vhdx"

[machine]
  usb = "on"
  initrd = "initrd-2.6.11.12.img.gz"
  kernel = "vmlinuz-2.6.11.12-vanilla.bz"
  append = "root=/dev/hda"

[memory]
  size = "2G"

[smp-opts]
  cpus = "2"

root@qemu:~# ifconfig
                   eth0      Link encap:Ethernet  HWaddr 52:54:00:12:34:56
                             inet addr:10.0.2.15  Bcast:10.255.255.255  Mask:255.255.255.0
                             UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
                             RX packets:0 errors:0 dropped:0 overruns:0 frame:0
                             TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
                             collisions:0 txqueuelen:1000
                             RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
                             Base address:0xc000 Memory:febc0000-febe0000

                   lo        Link encap:Local Loopback
                             inet addr:127.0.0.1  Mask:255.0.0.0
                             UP LOOPBACK RUNNING  MTU:16436  Metric:1
                             RX packets:0 errors:0 dropped:0 overruns:0 frame:0
                             TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
                             collisions:0 txqueuelen:0

                  root@qemu:~# route
UDP packet for DNS server
                                                              translating 302000a against ffffff 302000a
                                                                                                        it's an alias
                                                                                                                     it's DNS
      dns_addr is cached: 1020204
                                 got resolv.conf entry '4.2.2.1'
                   Kernel IP routing table                      
parsed 7fe2
                   Destination     Gateway         Genmask         Flags Metric Ref    
Use Iface '4.2.2.2'
                   10.0.2.0        *               255.255.255.0   U     0      0        0 eth0
                   default         10.0.2.2        0.0.0.0         UG    0      0        0 eth0

root@qemu:~# cat /etc/resolv.conf
                   nameserver 10.0.2.3

root@qemu:~# nslookup www.google.com
                   *** Unknown host

                   nslookup: www.google.com: Unknown host

HTH

It appears using the "route" command causes your DNS debug statements to print out but still nslookup does not work correctly.

mark.
Samuel Thibault April 30, 2017, 12:57 p.m. UTC | #4
FONNEMANN Mark, on dim. 30 avril 2017 12:42:41 +0000, wrote:
> root@qemu:~# nslookup www.google.com
>                    *** Unknown host
> 
>                    nslookup: www.google.com: Unknown host

Could you run tcpdump inside the guest so we are sure what the nslookup
call emits?

Samuel
FONNEMANN Mark May 5, 2017, 10:38 p.m. UTC | #5
>Could you run tcpdump inside the guest so we are sure what the nslookup call emits?

Is there another way to determine this info? My guest OS is an embedded system with BusyBox 1.25 and not much else.

Mark.
Thomas Huth May 8, 2017, 1:03 a.m. UTC | #6
On 06.05.2017 00:38, FONNEMANN Mark wrote:
>> Could you run tcpdump inside the guest so we are sure what the nslookup call emits?
> 
> Is there another way to determine this info? My guest OS is an embedded system with BusyBox 1.25 and not much else.

FWIW, QEMU also has a built-in packet-dump functionality. You can use it
like this:

qemu-system-xxx ... -netdev user,id=netuser \
   -object filter-dump,id=dump,netdev=netuser,file=/tmp/dump.dat \
   -device e1000,netdev=netuser,mac=00:11:22:33:44:55

Then run "wireshark -r /tmp/dump.dat" afterwards to have a look at the
packets.

 Thomas
diff mbox

Patch

--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -6,6 +6,7 @@ 
  */
 
 #include "qemu/osdep.h"
+#include "qemu/log.h"
 #include "qemu-common.h"
 #include "slirp.h"
 #include "ip_icmp.h"
@@ -814,11 +815,18 @@  void sotranslate_out(struct socket *so,
 
     switch (addr->ss_family) {
     case AF_INET:
+        qemu_log("translating %x against %x %x\n",
+                so->so_faddr.s_addr,
+                slirp->vnetwork_mask.s_addr,
+                slirp->vnameserver_addr.s_addr);
         if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
                 slirp->vnetwork_addr.s_addr) {
             /* It's an alias */
+            qemu_log("it's an alias\n");
             if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
+                qemu_log("it's DNS\n");
                 if (get_dns_addr(&sin->sin_addr) < 0) {
+                    qemu_log("didn't get DNS address");
                     sin->sin_addr = loopback_addr;
                 }
             } else {
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -39,6 +39,7 @@ 
  */
 
 #include "qemu/osdep.h"
+#include "qemu/log.h"
 #include "slirp.h"
 #include "ip_icmp.h"
 
@@ -133,6 +134,10 @@  udp_input(register struct mbuf *m, int i
 	lhost4->sin_addr = ip->ip_src;
 	lhost4->sin_port = uh->uh_sport;
 
+        if (ntohs(uh->uh_dport) == 53 &&
+            ip->ip_dst.s_addr == slirp->vnameserver_addr.s_addr)
+            qemu_log("UDP packet for DNS server\n");
+
         /*
          *  handle DHCP/BOOTP
          */
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -22,6 +22,7 @@ 
  * THE SOFTWARE.
  */
 #include "qemu/osdep.h"
+#include "qemu/log.h"
 #include "qemu-common.h"
 #include "qemu/timer.h"
 #include "qemu/error-report.h"
@@ -165,6 +166,7 @@  static int get_dns_addr_resolv_conf(int
 #endif
     while (fgets(buff, 512, f) != NULL) {
         if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
+            qemu_log("got resolv.conf entry '%s'\n", buff2);
             char *c = strchr(buff2, '%');
             if (c) {
                 if_index = if_nametoindex(c + 1);
@@ -174,10 +176,16 @@  static int get_dns_addr_resolv_conf(int
             }
 
             if (!inet_pton(af, buff2, tmp_addr)) {
+                qemu_log("couldn't parse it as %d\n", af);
                 continue;
             }
             /* If it's the first one, set it to dns_addr */
             if (!found) {
+                if (af == AF_INET)
+                {
+                    struct in_addr *in = tmp_addr;
+                    qemu_log("parsed %x\n", in->s_addr);
+                }
                 memcpy(pdns_addr, tmp_addr, addrlen);
                 memcpy(cached_addr, tmp_addr, addrlen);
                 if (scope_id) {
@@ -219,6 +227,7 @@  int get_dns_addr(struct in_addr *pdns_ad
 
     if (dns_addr.s_addr != 0) {
         int ret;
+        qemu_log("dns_addr is cached: %x\n", dns_addr.s_addr);
         ret = get_dns_addr_cached(pdns_addr, &dns_addr, sizeof(dns_addr),
                                   &dns_addr_stat, &dns_addr_time);
         if (ret <= 0) {