diff mbox

[PATCHv9,09/10] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses

Message ID b4a9c7d435d4cd750f6e4486d3f3d7014cfc85ab.1456168872.git.samuel.thibault@ens-lyon.org
State New
Headers show

Commit Message

Samuel Thibault Feb. 22, 2016, 7:28 p.m. UTC
From: Yann Bordenave <meow@meowstars.org>

This patch adds parameters to manage some new options in the qemu -net
command.
Slirp IPv6 address, network prefix, and DNS IPv6 address can be given in
argument to the qemu command.
Defaults parameters are respectively fec0::2, fec0::, /64 and fec0::3.

Signed-off-by: Yann Bordenave <meow@meowstars.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
---
 net/net.c        | 31 +++++++++++++++++++++++++
 net/slirp.c      | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 qapi-schema.json | 40 ++++++++++++++++++++------------
 qemu-options.hx  | 18 +++++++++++++--
 slirp/libslirp.h |  8 ++++---
 slirp/slirp.c    | 16 +++++++------
 6 files changed, 150 insertions(+), 32 deletions(-)

Comments

Thomas Huth Feb. 23, 2016, 8:27 a.m. UTC | #1
On 22.02.2016 20:28, Samuel Thibault wrote:
> From: Yann Bordenave <meow@meowstars.org>
> 
> This patch adds parameters to manage some new options in the qemu -net
> command.
> Slirp IPv6 address, network prefix, and DNS IPv6 address can be given in
> argument to the qemu command.
> Defaults parameters are respectively fec0::2, fec0::, /64 and fec0::3.
> 
> Signed-off-by: Yann Bordenave <meow@meowstars.org>
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> ---
>  net/net.c        | 31 +++++++++++++++++++++++++
>  net/slirp.c      | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  qapi-schema.json | 40 ++++++++++++++++++++------------
>  qemu-options.hx  | 18 +++++++++++++--
>  slirp/libslirp.h |  8 ++++---
>  slirp/slirp.c    | 16 +++++++------
>  6 files changed, 150 insertions(+), 32 deletions(-)
...
> diff --git a/net/slirp.c b/net/slirp.c
> index 6b51fbc..bd712bc 100644
> --- a/net/slirp.c
> +++ b/net/slirp.c
> @@ -36,6 +36,7 @@
>  #include "qemu/error-report.h"
>  #include "qemu/sockets.h"
>  #include "slirp/libslirp.h"
> +#include "slirp/ip6.h"
>  #include "sysemu/char.h"
>  
>  static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
> @@ -135,10 +136,13 @@ static NetClientInfo net_slirp_info = {
>  static int net_slirp_init(NetClientState *peer, const char *model,
>                            const char *name, int restricted,
>                            const char *vnetwork, const char *vhost,
> +                          const char *vprefix6, int vprefix6_len,
> +                          const char *vhost6,
>                            const char *vhostname, const char *tftp_export,
>                            const char *bootfile, const char *vdhcp_start,
> -                          const char *vnameserver, const char *smb_export,
> -                          const char *vsmbserver, const char **dnssearch)
> +                          const char *vnameserver, const char *vnameserver6,
> +                          const char *smb_export, const char *vsmbserver,
> +                          const char **dnssearch)
>  {
>      /* default settings according to historic slirp */
>      struct in_addr net  = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */
> @@ -146,6 +150,9 @@ static int net_slirp_init(NetClientState *peer, const char *model,
>      struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
>      struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
>      struct in_addr dns  = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
> +    struct in6_addr ip6_prefix;
> +    struct in6_addr ip6_host;
> +    struct in6_addr ip6_dns;
>  #ifndef _WIN32
>      struct in_addr smbsrv = { .s_addr = 0 };
>  #endif
> @@ -235,6 +242,52 @@ static int net_slirp_init(NetClientState *peer, const char *model,
>      }
>  #endif
>  
> +
> +    if (!vprefix6) {
> +        vprefix6 = "fec0::";
> +    }
> +    if (!inet_pton(AF_INET6, vprefix6, &ip6_prefix)) {
> +        return -1;
> +    }
> +
> +    if (!vprefix6_len) {
> +        vprefix6_len = 64;
> +    }
> +    if (vprefix6_len < 0 || vprefix6_len > 128) {
> +        return -1;
> +    }

I think you could also immediately check for vprefix6_len > 126 here
already, then you could drop the two checks for 126 below. A prefix that
is bigger than 126 does not make much sense anyway, so I think it should
be ok to always disallow this (especially since there will be at least
three hosts in this network - the host, the guest, and the DNS server).

> +    if (vhost6) {
> +        if (!inet_pton(AF_INET6, vhost6, &ip6_host)) {
> +            return -1;
> +        }
> +        if (!in6_equal_net(&ip6_prefix, &ip6_host, vprefix6_len)) {
> +            return -1;
> +        }
> +    } else {
> +        if (vprefix6_len > 126) {
> +            return -1;
> +        }
> +        ip6_host = ip6_prefix;
> +        ip6_host.s6_addr[15] |= 2;
> +    }
> +
> +    if (vnameserver6) {
> +        if (!inet_pton(AF_INET6, vnameserver6, &ip6_dns)) {
> +            return -1;
> +        }
> +        if (!in6_equal_net(&ip6_prefix, &ip6_dns, vprefix6_len)) {
> +            return -1;
> +        }
> +    } else {
> +        if (vprefix6_len > 126) {
> +            return -1;
> +        }
> +        ip6_dns = ip6_prefix;
> +        ip6_dns.s6_addr[15] |= 3;
> +    }

The other parts of the patch looks fine to me now.

 Thomas
Jason Wang March 7, 2016, 7:05 a.m. UTC | #2
On 02/23/2016 03:28 AM, Samuel Thibault wrote:
> From: Yann Bordenave <meow@meowstars.org>
>
> This patch adds parameters to manage some new options in the qemu -net
> command.
> Slirp IPv6 address, network prefix, and DNS IPv6 address can be given in
> argument to the qemu command.
> Defaults parameters are respectively fec0::2, fec0::, /64 and fec0::3.
>
> Signed-off-by: Yann Bordenave <meow@meowstars.org>
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> ---
>  net/net.c        | 31 +++++++++++++++++++++++++
>  net/slirp.c      | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  qapi-schema.json | 40 ++++++++++++++++++++------------
>  qemu-options.hx  | 18 +++++++++++++--
>  slirp/libslirp.h |  8 ++++---
>  slirp/slirp.c    | 16 +++++++------
>  6 files changed, 150 insertions(+), 32 deletions(-)
>
> diff --git a/net/net.c b/net/net.c
> index aebf753..d67904f 100644

[...]

>  
>      while (slirp_configs) {
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 8d04897..a62c2ec 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -2399,6 +2399,14 @@
>  # @dnssearch: #optional list of DNS suffixes to search, passed as DHCP option
>  #             to the guest
>  #
> +# @ip6-prefix: #optional IPv6 network prefix (default is fec0::) (since 2.6)
> +#
> +# @ip6-prefixlen: #optional IPv6 network prefix length (default is 64) (since 2.6)
> +#
> +# @ip6-host: #optional guest-visible IPv6 address of the host (since 2.6)
> +#
> +# @ip6-dns: #optional guest-visible IPv6 address of the virtual nameserver (since 2.6)
> +#
>  # @smb: #optional root directory of the built-in SMB server
>  #
>  # @smbserver: #optional IP address of the built-in SMB server
> @@ -2412,20 +2420,24 @@
>  ##
>  { 'struct': 'NetdevUserOptions',
>    'data': {
> -    '*hostname':  'str',
> -    '*restrict':  'bool',
> -    '*ip':        'str',
> -    '*net':       'str',
> -    '*host':      'str',
> -    '*tftp':      'str',
> -    '*bootfile':  'str',
> -    '*dhcpstart': 'str',
> -    '*dns':       'str',
> -    '*dnssearch': ['String'],
> -    '*smb':       'str',
> -    '*smbserver': 'str',
> -    '*hostfwd':   ['String'],
> -    '*guestfwd':  ['String'] } }
> +    '*hostname':        'str',
> +    '*restrict':        'bool',
> +    '*ip':              'str',
> +    '*net':             'str',
> +    '*host':            'str',
> +    '*tftp':            'str',
> +    '*bootfile':        'str',
> +    '*dhcpstart':       'str',
> +    '*dns':             'str',
> +    '*dnssearch':       ['String'],
> +    '*ip6-prefix':      'str',
> +    '*ip6-prefixlen':   'int',
> +    '*ip6-host':        'str',
> +    '*ip6-dns':         'str',
> +    '*smb':             'str',
> +    '*smbserver':       'str',
> +    '*hostfwd':         ['String'],
> +    '*guestfwd':        ['String'] } }

Please do unnecessary changes like this since it will cause extra effort
for git blame and other things.
Samuel Thibault March 7, 2016, 11:39 a.m. UTC | #3
Jason Wang, on Mon 07 Mar 2016 15:05:05 +0800, wrote:
> Please do unnecessary changes like this since it will cause extra effort
> for git blame and other things.

Which is exactly why we avoided to fix all the checkpatch warnings by
leaving existing non-qemu-style indentation.

Samuel
Samuel Thibault March 7, 2016, 11:41 a.m. UTC | #4
Jason Wang, on Mon 07 Mar 2016 15:05:05 +0800, wrote:
> Please do unnecessary changes like this since it will cause extra effort
> for git blame and other things.

Ok. I just do hope that no other reviewer will come and say that we
should fix the alignment of the parameters.

Samuel
Eric Blake March 7, 2016, 4:05 p.m. UTC | #5
On 03/07/2016 04:41 AM, Samuel Thibault wrote:
> Jason Wang, on Mon 07 Mar 2016 15:05:05 +0800, wrote:
>> Please do unnecessary changes like this since it will cause extra effort
>> for git blame and other things.
> 
> Ok. I just do hope that no other reviewer will come and say that we
> should fix the alignment of the parameters.

Alignment doesn't matter; in fact, most qapi .json files use
 'name': 'type

with a single space after : for every parameter, rather than trying to
align things.  It doesn't bother me either way (or I would have pointed
it out sooner), but reindenting is more churn than I would personally do.
diff mbox

Patch

diff --git a/net/net.c b/net/net.c
index aebf753..d67904f 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1060,6 +1060,37 @@  int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)
     int ret = -1;
 
     {
+        /* Parse convenience option format ip6-net=fec0::0[/64] */
+        const char *ip6_net = qemu_opt_get(opts, "ip6-net");
+
+        if (ip6_net) {
+            char buf[strlen(ip6_net) + 1];
+
+            if (get_str_sep(buf, sizeof(buf), &ip6_net, '/') < 0) {
+                /* Default 64bit prefix length.  */
+                qemu_opt_set(opts, "ip6-prefix", ip6_net, &error_abort);
+                qemu_opt_set_number(opts, "ip6-prefixlen", 64, &error_abort);
+            } else {
+                /* User-specified prefix length.  */
+                unsigned long len;
+                int err;
+
+                qemu_opt_set(opts, "ip6-prefix", buf, &error_abort);
+                err = qemu_strtoul(ip6_net, NULL, 10, &len);
+
+                if (err) {
+                    error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+                              "ip6-prefix", "a number");
+                } else {
+                    qemu_opt_set_number(opts, "ip6-prefixlen", len,
+                                        &error_abort);
+                }
+            }
+            qemu_opt_unset(opts, "ip6-net");
+        }
+    }
+
+    {
         OptsVisitor *ov = opts_visitor_new(opts);
 
         net_visit(opts_get_visitor(ov), is_netdev, &object, &err);
diff --git a/net/slirp.c b/net/slirp.c
index 6b51fbc..bd712bc 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -36,6 +36,7 @@ 
 #include "qemu/error-report.h"
 #include "qemu/sockets.h"
 #include "slirp/libslirp.h"
+#include "slirp/ip6.h"
 #include "sysemu/char.h"
 
 static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
@@ -135,10 +136,13 @@  static NetClientInfo net_slirp_info = {
 static int net_slirp_init(NetClientState *peer, const char *model,
                           const char *name, int restricted,
                           const char *vnetwork, const char *vhost,
+                          const char *vprefix6, int vprefix6_len,
+                          const char *vhost6,
                           const char *vhostname, const char *tftp_export,
                           const char *bootfile, const char *vdhcp_start,
-                          const char *vnameserver, const char *smb_export,
-                          const char *vsmbserver, const char **dnssearch)
+                          const char *vnameserver, const char *vnameserver6,
+                          const char *smb_export, const char *vsmbserver,
+                          const char **dnssearch)
 {
     /* default settings according to historic slirp */
     struct in_addr net  = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */
@@ -146,6 +150,9 @@  static int net_slirp_init(NetClientState *peer, const char *model,
     struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
     struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
     struct in_addr dns  = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
+    struct in6_addr ip6_prefix;
+    struct in6_addr ip6_host;
+    struct in6_addr ip6_dns;
 #ifndef _WIN32
     struct in_addr smbsrv = { .s_addr = 0 };
 #endif
@@ -235,6 +242,52 @@  static int net_slirp_init(NetClientState *peer, const char *model,
     }
 #endif
 
+
+    if (!vprefix6) {
+        vprefix6 = "fec0::";
+    }
+    if (!inet_pton(AF_INET6, vprefix6, &ip6_prefix)) {
+        return -1;
+    }
+
+    if (!vprefix6_len) {
+        vprefix6_len = 64;
+    }
+    if (vprefix6_len < 0 || vprefix6_len > 128) {
+        return -1;
+    }
+
+    if (vhost6) {
+        if (!inet_pton(AF_INET6, vhost6, &ip6_host)) {
+            return -1;
+        }
+        if (!in6_equal_net(&ip6_prefix, &ip6_host, vprefix6_len)) {
+            return -1;
+        }
+    } else {
+        if (vprefix6_len > 126) {
+            return -1;
+        }
+        ip6_host = ip6_prefix;
+        ip6_host.s6_addr[15] |= 2;
+    }
+
+    if (vnameserver6) {
+        if (!inet_pton(AF_INET6, vnameserver6, &ip6_dns)) {
+            return -1;
+        }
+        if (!in6_equal_net(&ip6_prefix, &ip6_dns, vprefix6_len)) {
+            return -1;
+        }
+    } else {
+        if (vprefix6_len > 126) {
+            return -1;
+        }
+        ip6_dns = ip6_prefix;
+        ip6_dns.s6_addr[15] |= 3;
+    }
+
+
     nc = qemu_new_net_client(&net_slirp_info, peer, model, name);
 
     snprintf(nc->info_str, sizeof(nc->info_str),
@@ -243,8 +296,10 @@  static int net_slirp_init(NetClientState *peer, const char *model,
 
     s = DO_UPCAST(SlirpState, nc, nc);
 
-    s->slirp = slirp_init(restricted, net, mask, host, vhostname,
-                          tftp_export, bootfile, dhcp, dns, dnssearch, s);
+    s->slirp = slirp_init(restricted, net, mask, host,
+                          ip6_prefix, vprefix6_len, ip6_host,
+                          vhostname, tftp_export, bootfile, dhcp,
+                          dns, ip6_dns, dnssearch, s);
     QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
 
     for (config = slirp_configs; config; config = config->next) {
@@ -761,8 +816,10 @@  int net_init_slirp(const NetClientOptions *opts, const char *name,
     net_init_slirp_configs(user->guestfwd, 0);
 
     ret = net_slirp_init(peer, "user", name, user->q_restrict, vnet,
-                         user->host, user->hostname, user->tftp,
-                         user->bootfile, user->dhcpstart, user->dns, user->smb,
+                         user->host, user->ip6_prefix, user->ip6_prefixlen,
+                         user->ip6_host, user->hostname, user->tftp,
+                         user->bootfile, user->dhcpstart,
+                         user->dns, user->ip6_dns, user->smb,
                          user->smbserver, dnssearch);
 
     while (slirp_configs) {
diff --git a/qapi-schema.json b/qapi-schema.json
index 8d04897..a62c2ec 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2399,6 +2399,14 @@ 
 # @dnssearch: #optional list of DNS suffixes to search, passed as DHCP option
 #             to the guest
 #
+# @ip6-prefix: #optional IPv6 network prefix (default is fec0::) (since 2.6)
+#
+# @ip6-prefixlen: #optional IPv6 network prefix length (default is 64) (since 2.6)
+#
+# @ip6-host: #optional guest-visible IPv6 address of the host (since 2.6)
+#
+# @ip6-dns: #optional guest-visible IPv6 address of the virtual nameserver (since 2.6)
+#
 # @smb: #optional root directory of the built-in SMB server
 #
 # @smbserver: #optional IP address of the built-in SMB server
@@ -2412,20 +2420,24 @@ 
 ##
 { 'struct': 'NetdevUserOptions',
   'data': {
-    '*hostname':  'str',
-    '*restrict':  'bool',
-    '*ip':        'str',
-    '*net':       'str',
-    '*host':      'str',
-    '*tftp':      'str',
-    '*bootfile':  'str',
-    '*dhcpstart': 'str',
-    '*dns':       'str',
-    '*dnssearch': ['String'],
-    '*smb':       'str',
-    '*smbserver': 'str',
-    '*hostfwd':   ['String'],
-    '*guestfwd':  ['String'] } }
+    '*hostname':        'str',
+    '*restrict':        'bool',
+    '*ip':              'str',
+    '*net':             'str',
+    '*host':            'str',
+    '*tftp':            'str',
+    '*bootfile':        'str',
+    '*dhcpstart':       'str',
+    '*dns':             'str',
+    '*dnssearch':       ['String'],
+    '*ip6-prefix':      'str',
+    '*ip6-prefixlen':   'int',
+    '*ip6-host':        'str',
+    '*ip6-dns':         'str',
+    '*smb':             'str',
+    '*smbserver':       'str',
+    '*hostfwd':         ['String'],
+    '*guestfwd':        ['String'] } }
 
 ##
 # @NetdevTapOptions
diff --git a/qemu-options.hx b/qemu-options.hx
index 2f0465e..a2c1214 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1546,8 +1546,9 @@  DEF("smb", HAS_ARG, QEMU_OPTION_smb, "", QEMU_ARCH_ALL)
 
 DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
 #ifdef CONFIG_SLIRP
-    "-netdev user,id=str[,net=addr[/mask]][,host=addr][,restrict=on|off]\n"
-    "         [,hostname=host][,dhcpstart=addr][,dns=addr][,dnssearch=domain][,tftp=dir]\n"
+    "-netdev user,id=str[,net=addr[/mask]][,host=addr][,ip6-net=addr[/int]]\n"
+    "         [,ip6-host=addr][,restrict=on|off][,hostname=host][,dhcpstart=addr]\n"
+    "         [,dns=addr][,ip6-dns=addr][,dnssearch=domain][,tftp=dir]\n"
     "         [,bootfile=f][,hostfwd=rule][,guestfwd=rule]"
 #ifndef _WIN32
                                              "[,smb=dir[,smbserver=addr]]\n"
@@ -1704,6 +1705,14 @@  either in the form a.b.c.d or as number of valid top-most bits. Default is
 Specify the guest-visible address of the host. Default is the 2nd IP in the
 guest network, i.e. x.x.x.2.
 
+@item ip6-net=@var{addr}[/@var{int}]
+Set IPv6 network address the guest will see. Optionally specify the prefix
+size, as number of valid top-most bits. Default is fec0::/64.
+
+@item ip6-host=@var{addr}
+Specify the guest-visible IPv6 address of the host. Default is the 2nd IPv6 in
+the guest network, i.e. xxxx::2.
+
 @item restrict=on|off
 If this option is enabled, the guest will be isolated, i.e. it will not be
 able to contact the host and no guest IP packets will be routed over the host
@@ -1721,6 +1730,11 @@  Specify the guest-visible address of the virtual nameserver. The address must
 be different from the host address. Default is the 3rd IP in the guest network,
 i.e. x.x.x.3.
 
+@item ip6-dns=@var{addr}
+Specify the guest-visible address of the IPv6 virtual nameserver. The address
+must be different from the host address. Default is the 3rd IP in the guest
+network, i.e. xxxx::3.
+
 @item dnssearch=@var{domain}
 Provides an entry for the domain-search list sent by the built-in
 DHCP server. More than one domain suffix can be transmitted by specifying
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 5bdcbd5..c4b25c9 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -10,9 +10,11 @@  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,
-                  const char *bootfile, struct in_addr vdhcp_start,
-                  struct in_addr vnameserver, const char **vdnssearch,
+                  struct in6_addr vprefix_addr6, uint8_t vprefix_len,
+                  struct in6_addr vhost6, const char *vhostname,
+                  const char *tftp_path, const char *bootfile,
+                  struct in_addr vdhcp_start, struct in_addr vnameserver,
+                  struct in6_addr vnameserver6, const char **vdnssearch,
                   void *opaque);
 void slirp_cleanup(Slirp *slirp);
 
diff --git a/slirp/slirp.c b/slirp/slirp.c
index a201a5a..9ccf415 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -201,9 +201,11 @@  static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
 
 Slirp *slirp_init(int restricted, struct in_addr vnetwork,
                   struct in_addr vnetmask, struct in_addr vhost,
-                  const char *vhostname, const char *tftp_path,
-                  const char *bootfile, struct in_addr vdhcp_start,
-                  struct in_addr vnameserver, const char **vdnssearch,
+                  struct in6_addr vprefix_addr6, uint8_t vprefix_len,
+                  struct in6_addr vhost6, const char *vhostname,
+                  const char *tftp_path, const char *bootfile,
+                  struct in_addr vdhcp_start, struct in_addr vnameserver,
+                  struct in6_addr vnameserver6, const char **vdnssearch,
                   void *opaque)
 {
     Slirp *slirp = g_malloc0(sizeof(Slirp));
@@ -223,9 +225,9 @@  Slirp *slirp_init(int restricted, struct in_addr vnetwork,
     slirp->vnetwork_addr = vnetwork;
     slirp->vnetwork_mask = vnetmask;
     slirp->vhost_addr = vhost;
-    inet_pton(AF_INET6, "fec0::0", &slirp->vprefix_addr6);
-    slirp->vprefix_len = 64;
-    inet_pton(AF_INET6, "fec0::2", &slirp->vhost_addr6);
+    slirp->vprefix_addr6 = vprefix_addr6;
+    slirp->vprefix_len = vprefix_len;
+    slirp->vhost_addr6 = vhost6;
     if (vhostname) {
         pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
                 vhostname);
@@ -234,7 +236,7 @@  Slirp *slirp_init(int restricted, struct in_addr vnetwork,
     slirp->bootp_filename = g_strdup(bootfile);
     slirp->vdhcp_startaddr = vdhcp_start;
     slirp->vnameserver_addr = vnameserver;
-    inet_pton(AF_INET6, "fec0::3", &slirp->vnameserver_addr6);
+    slirp->vnameserver_addr6 = vnameserver6;
 
     if (vdnssearch) {
         translate_dnssearch(slirp, vdnssearch);