Make net=none disable IPv4 and ip6-net=none disable IPv6, so the user can setup IPv4-only and IPv6-only network environments.
Signed-off-by: Samuel Thibault <samuel.thiba...@ens-lyon.org> --- net/slirp.c | 19 +++++++++++++------ qapi-schema.json | 15 +++++++++++++-- qemu-options.hx | 19 ++++++++++++------- slirp/ip6_icmp.c | 8 ++++++++ slirp/ip6_input.c | 5 +++++ slirp/ip_input.c | 4 ++++ slirp/libslirp.h | 3 ++- slirp/slirp.c | 10 +++++++++- slirp/slirp.h | 2 ++ 9 files changed, 68 insertions(+), 17 deletions(-) diff --git a/net/slirp.c b/net/slirp.c index 95239bc..4c9319e 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -135,8 +135,8 @@ 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, + bool ip4, const char *vnetwork, const char *vhost, + bool ip6, const char *vprefix6, int vprefix6_len, const char *vhost6, const char *vhostname, const char *tftp_export, const char *bootfile, const char *vdhcp_start, @@ -164,6 +164,12 @@ static int net_slirp_init(NetClientState *peer, const char *model, char *end; struct slirp_config_str *config; + if (!ip4 && !ip6) { + /* Enable both by default */ + ip4 = 1; + ip6 = 1; + } + if (!tftp_export) { tftp_export = legacy_tftp_prefix; } @@ -308,8 +314,8 @@ static int net_slirp_init(NetClientState *peer, const char *model, s = DO_UPCAST(SlirpState, nc, nc); - s->slirp = slirp_init(restricted, net, mask, host, - ip6_prefix, vprefix6_len, ip6_host, + s->slirp = slirp_init(restricted, ip4, net, mask, host, + ip6, ip6_prefix, vprefix6_len, ip6_host, vhostname, tftp_export, bootfile, dhcp, dns, ip6_dns, dnssearch, s); QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry); @@ -827,8 +833,9 @@ int net_init_slirp(const NetClientOptions *opts, const char *name, net_init_slirp_configs(user->hostfwd, SLIRP_CFG_HOSTFWD); net_init_slirp_configs(user->guestfwd, 0); - ret = net_slirp_init(peer, "user", name, user->q_restrict, vnet, - user->host, user->ip6_prefix, user->ip6_prefixlen, + ret = net_slirp_init(peer, "user", name, user->q_restrict, + user->ip4, vnet, user->host, + user->ip6, user->ip6_prefix, user->ip6_prefixlen, user->ip6_host, user->hostname, user->tftp, user->bootfile, user->dhcpstart, user->dns, user->ip6_dns, user->smb, diff --git a/qapi-schema.json b/qapi-schema.json index 88f9b81..0b693ec 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2425,9 +2425,16 @@ # # @restrict: #optional isolate the guest from the host # +# @ip4: #optional whether to support IPv4, default is to support both IPv4 and IPv6. +# +# @ip6: #optional whether to support IPv6, default is to support both IPv4 and IPv6. +# # @ip: #optional legacy parameter, use net= instead # -# @net: #optional IP address and optional netmask +# @net: #optional IP network address that the guest will see, in the +# form addr[/netmask] (default is 10.0.2.0/24). The netmask is optional, +# and can be either in the form a.b.c.d or as a number of valid top-most +# bits. # # @host: #optional guest-visible address of the host # @@ -2443,7 +2450,9 @@ # @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-prefix: #optional IPv6 network prefix (default is fec0::) (since +# 2.6). The network prefix is given in the usual hexadecimal IPv6 +# address notation. # # @ip6-prefixlen: #optional IPv6 network prefix length (default is 64) (since 2.6) # @@ -2466,6 +2475,8 @@ 'data': { '*hostname': 'str', '*restrict': 'bool', + '*ip4': 'bool', + '*ip6': 'bool', '*ip': 'str', '*net': 'str', '*host': 'str', diff --git a/qemu-options.hx b/qemu-options.hx index 732ed8c..cc43c32 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -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][,ip6-net=addr[/int]]\n" - " [,ip6-host=addr][,restrict=on|off][,hostname=host][,dhcpstart=addr]\n" + "-netdev user,id=str[,ip4][,net=addr[/mask]][,host=addr]\n" + " [,ip6][,ip6-net=addr[/int]][,ip6-host=addr]\n" + " [,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 @@ -1711,17 +1712,21 @@ Connect user mode stack to VLAN @var{n} (@var{n} = 0 is the default). Assign symbolic name for use in monitor commands. @item net=@var{addr}[/@var{mask}] -Set IP network address the guest will see. Optionally specify the netmask, -either in the form a.b.c.d or as number of valid top-most bits. Default is -10.0.2.0/24. +Set IP network address the guest will see or 'none'. Default is +10.0.2.0/24. The netmask is optional, and can be either in the form +a.b.c.d or as number of valid top-most bits. 'none' disables IPv4 +completely. @item host=@var{addr} 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. +Set IPv6 network address the guest will see or 'none' (default is +fec0::/64). The network prefix is given in the usual hexadecimal IPv6 +address notation. The prefix size is optional, and is given as the +number of valid top-most bits (default is 64). 'none' disables IPv6 +completely. @item ip6-host=@var{addr} Specify the guest-visible IPv6 address of the host. Default is the 2nd IPv6 in diff --git a/slirp/ip6_icmp.c b/slirp/ip6_icmp.c index 9d61349..09571bc 100644 --- a/slirp/ip6_icmp.c +++ b/slirp/ip6_icmp.c @@ -24,6 +24,10 @@ static void ra_timer_handler(void *opaque) void icmp6_init(Slirp *slirp) { + if (!slirp->in6_enabled) { + return; + } + slirp->ra_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, ra_timer_handler, slirp); timer_mod(slirp->ra_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + NDP_Interval); @@ -31,6 +35,10 @@ void icmp6_init(Slirp *slirp) void icmp6_cleanup(Slirp *slirp) { + if (!slirp->in6_enabled) { + return; + } + timer_del(slirp->ra_timer); timer_free(slirp->ra_timer); } diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c index c0b11e7..ac2e3ea 100644 --- a/slirp/ip6_input.c +++ b/slirp/ip6_input.c @@ -24,6 +24,11 @@ void ip6_cleanup(Slirp *slirp) void ip6_input(struct mbuf *m) { struct ip6 *ip6; + Slirp *slirp = m->slirp; + + if (!slirp->in6_enabled) { + goto bad; + } DEBUG_CALL("ip6_input"); DEBUG_ARG("m = %lx", (long)m); diff --git a/slirp/ip_input.c b/slirp/ip_input.c index b464f6b..cdd5483 100644 --- a/slirp/ip_input.c +++ b/slirp/ip_input.c @@ -80,6 +80,10 @@ ip_input(struct mbuf *m) register struct ip *ip; int hlen; + if (!slirp->in_enabled) { + goto bad; + } + DEBUG_CALL("ip_input"); DEBUG_ARG("m = %p", m); DEBUG_ARG("m_len = %d", m->m_len); diff --git a/slirp/libslirp.h b/slirp/libslirp.h index c4b25c9..127aa41 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -8,8 +8,9 @@ typedef struct Slirp Slirp; int get_dns_addr(struct in_addr *pdns_addr); -Slirp *slirp_init(int restricted, struct in_addr vnetwork, +Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork, struct in_addr vnetmask, struct in_addr vhost, + bool in6_enabled, struct in6_addr vprefix_addr6, uint8_t vprefix_len, struct in6_addr vhost6, const char *vhostname, const char *tftp_path, const char *bootfile, diff --git a/slirp/slirp.c b/slirp/slirp.c index 9ccf415..6256c89 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -199,8 +199,9 @@ static void slirp_init_once(void) static void slirp_state_save(QEMUFile *f, void *opaque); static int slirp_state_load(QEMUFile *f, void *opaque, int version_id); -Slirp *slirp_init(int restricted, struct in_addr vnetwork, +Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork, struct in_addr vnetmask, struct in_addr vhost, + bool in6_enabled, struct in6_addr vprefix_addr6, uint8_t vprefix_len, struct in6_addr vhost6, const char *vhostname, const char *tftp_path, const char *bootfile, @@ -215,6 +216,9 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, slirp->grand = g_rand_new(); slirp->restricted = restricted; + slirp->in_enabled = in_enabled; + slirp->in6_enabled = in6_enabled; + if_init(slirp); ip_init(slirp); ip6_init(slirp); @@ -693,6 +697,10 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) int ar_op; struct ex_list *ex_ptr; + if (!slirp->in_enabled) { + return; + } + ar_op = ntohs(ah->ar_op); switch(ar_op) { case ARPOP_REQUEST: diff --git a/slirp/slirp.h b/slirp/slirp.h index 9ad88e7..0b84027 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -179,6 +179,8 @@ struct Slirp { u_int last_slowtimo; bool do_slowtimo; + bool in_enabled, in6_enabled; + /* virtual network configuration */ struct in_addr vnetwork_addr; struct in_addr vnetwork_mask; -- 2.8.0.rc3