qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses
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> Reviewed-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
parent
05061d8548
commit
7aac531ef2
31
net/net.c
31
net/net.c
@ -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 {
|
||||
|
81
net/slirp.c
81
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) {
|
||||
|
@ -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'],
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,22 +225,9 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
|
||||
slirp->vnetwork_addr = vnetwork;
|
||||
slirp->vnetwork_mask = vnetmask;
|
||||
slirp->vhost_addr = vhost;
|
||||
#if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
|
||||
/* No inet_pton helper... */
|
||||
memset(&slirp->vprefix_addr6, 0, sizeof(slirp->vprefix_addr6));
|
||||
slirp->vprefix_addr6.s6_addr[0] = 0xfe;
|
||||
slirp->vprefix_addr6.s6_addr[1] = 0xc0;
|
||||
slirp->vprefix_len = 64;
|
||||
slirp->vhost_addr6 = slirp->vprefix_addr6;
|
||||
slirp->vhost_addr6.s6_addr[15] = 0x2;
|
||||
slirp->vnameserver_addr6 = slirp->vprefix_addr6;
|
||||
slirp->vnameserver_addr6.s6_addr[15] = 0x3;
|
||||
#else
|
||||
inet_pton(AF_INET6, "fec0::0", &slirp->vprefix_addr6);
|
||||
slirp->vprefix_len = 64;
|
||||
inet_pton(AF_INET6, "fec0::2", &slirp->vhost_addr6);
|
||||
inet_pton(AF_INET6, "fec0::3", &slirp->vnameserver_addr6);
|
||||
#endif
|
||||
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);
|
||||
@ -247,6 +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;
|
||||
slirp->vnameserver_addr6 = vnameserver6;
|
||||
|
||||
if (vdnssearch) {
|
||||
translate_dnssearch(slirp, vdnssearch);
|
||||
|
Loading…
Reference in New Issue
Block a user