Commit a6cdb77f authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/thibault/tags/samuel-thibault' into staging



slirp: Adding IPv6 support to Qemu -net user mode

# gpg: Signature made Tue 15 Mar 2016 16:06:03 GMT using RSA key ID FB6B2F1D
# gpg: Good signature from "Samuel Thibault <samuel.thibault@gnu.org>"
# gpg:                 aka "Samuel Thibault <sthibault@debian.org>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@inria.fr>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@labri.fr>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@ens-lyon.org>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 900C B024 B679 31D4 0F82  304B D017 8C76 7D06 9EE6
#      Subkey fingerprint: F632 74CD C630 0873 CB3D  29D9 E3E5 1CE8 FB6B 2F1D

* remotes/thibault/tags/samuel-thibault:
  slirp: Add IPv6 support to the TFTP code
  qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses
  slirp: Adding IPv6 address for DNS relay
  slirp: Handle IPv6 in TCP functions
  slirp: Reindent after refactoring
  slirp: Generalizing and neutralizing various TCP functions before adding IPv6 stuff
  slirp: Factorizing tcpiphdr structure with an union
  slirp: Adding IPv6 UDP support
  slirp: Adding ICMPv6 error sending
  slirp: Fix ICMP error sending
  slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents a58a4cb1 fad7fb9c
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -1050,6 +1050,37 @@ int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)
    OptsVisitor *ov = opts_visitor_new(opts);
    Visitor *v = opts_get_visitor(ov);

    {
        /* 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");
        }
    }

    if (is_netdev) {
        visit_type_Netdev(v, NULL, (Netdev **)&object, &err);
    } else {
+75 −6
Original line number Diff line number Diff line
@@ -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,64 @@ static int net_slirp_init(NetClientState *peer, const char *model,
    }
#endif

#if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
    /* No inet_pton helper before Vista... */
    if (vprefix6) {
        /* Unsupported */
        return -1;
    }
    memset(&ip6_prefix, 0, sizeof(ip6_prefix));
    ip6_prefix.s6_addr[0] = 0xfe;
    ip6_prefix.s6_addr[1] = 0xc0;
#else
    if (!vprefix6) {
        vprefix6 = "fec0::";
    }
    if (!inet_pton(AF_INET6, vprefix6, &ip6_prefix)) {
        return -1;
    }
#endif

    if (!vprefix6_len) {
        vprefix6_len = 64;
    }
    if (vprefix6_len < 0 || vprefix6_len > 126) {
        return -1;
    }

    if (vhost6) {
#if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
        return -1;
#else
        if (!inet_pton(AF_INET6, vhost6, &ip6_host)) {
            return -1;
        }
        if (!in6_equal_net(&ip6_prefix, &ip6_host, vprefix6_len)) {
            return -1;
        }
#endif
    } else {
        ip6_host = ip6_prefix;
        ip6_host.s6_addr[15] |= 2;
    }

    if (vnameserver6) {
#if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
        return -1;
#else
        if (!inet_pton(AF_INET6, vnameserver6, &ip6_dns)) {
            return -1;
        }
        if (!in6_equal_net(&ip6_prefix, &ip6_dns, vprefix6_len)) {
            return -1;
        }
#endif
    } else {
        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 +308,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 +828,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) {
+12 −0
Original line number Diff line number Diff line
@@ -2451,6 +2451,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
@@ -2474,6 +2482,10 @@
    '*dhcpstart': 'str',
    '*dns':       'str',
    '*dnssearch': ['String'],
    '*ip6-prefix':      'str',
    '*ip6-prefixlen':   'int',
    '*ip6-host':        'str',
    '*ip6-dns':         'str',
    '*smb':       'str',
    '*smbserver': 'str',
    '*hostfwd':   ['String'],
+16 −2
Original line number Diff line number Diff line
@@ -1560,8 +1560,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"
@@ -1718,6 +1719,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
@@ -1735,6 +1744,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
+4 −2
Original line number Diff line number Diff line
common-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o dnssearch.o
common-obj-y = cksum.o if.o ip_icmp.o ip6_icmp.o ip6_input.o ip6_output.o \
               ip_input.o ip_output.o dnssearch.o
common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o
common-obj-y += tcp_subr.o tcp_timer.o udp.o udp6.o bootp.o tftp.o arp_table.o \
                ndp_table.o
Loading