diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-03-15 17:09:52 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-03-15 17:09:52 +0000 |
commit | a6cdb77f816961f929d7934643febd2852230135 (patch) | |
tree | 927a63ea0415115f37de4822fd6f192e28d7df81 /net | |
parent | a58a4cb18725117bf69e6bee0a753c8b73b09667 (diff) | |
parent | fad7fb9ccd8013ea03c8c7a8f491c395e786dae6 (diff) | |
download | qemu-a6cdb77f816961f929d7934643febd2852230135.tar.gz qemu-a6cdb77f816961f929d7934643febd2852230135.tar.bz2 qemu-a6cdb77f816961f929d7934643febd2852230135.zip |
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: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/net.c | 31 | ||||
-rw-r--r-- | net/slirp.c | 81 |
2 files changed, 106 insertions, 6 deletions
@@ -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 { diff --git a/net/slirp.c b/net/slirp.c index 6b51fbc306..9954160de3 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,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) { |