From patchwork Thu Mar 24 22:12:48 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Thibault X-Patchwork-Id: 8665061 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 6E9A19F36E for ; Thu, 24 Mar 2016 22:13:07 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3D03B202E9 for ; Thu, 24 Mar 2016 22:13:06 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BA910202E5 for ; Thu, 24 Mar 2016 22:13:04 +0000 (UTC) Received: from localhost ([::1]:53040 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ajDV2-0003wx-4f for patchwork-qemu-devel@patchwork.kernel.org; Thu, 24 Mar 2016 18:13:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47515) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ajDUt-0003wf-IG for qemu-devel@nongnu.org; Thu, 24 Mar 2016 18:12:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ajDUq-0002oO-8O for qemu-devel@nongnu.org; Thu, 24 Mar 2016 18:12:55 -0400 Received: from domu-toccata.ens-lyon.fr ([140.77.166.138]:57863 helo=sonata.ens-lyon.org) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ajDUp-0002ne-TD for qemu-devel@nongnu.org; Thu, 24 Mar 2016 18:12:52 -0400 Received: from localhost (localhost [127.0.0.1]) by sonata.ens-lyon.org (Postfix) with ESMTP id B13A520113; Thu, 24 Mar 2016 23:12:50 +0100 (CET) Received: from sonata.ens-lyon.org ([127.0.0.1]) by localhost (sonata.ens-lyon.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id UiEomaoeSlJs; Thu, 24 Mar 2016 23:12:50 +0100 (CET) Received: from var.youpi.perso.aquilenet.fr (LFbn-1-6757-94.w90-120.abo.wanadoo.fr [90.120.189.94]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sonata.ens-lyon.org (Postfix) with ESMTPSA id 799BC20111; Thu, 24 Mar 2016 23:12:50 +0100 (CET) Received: from samy by var.youpi.perso.aquilenet.fr with local (Exim 4.86_2) (envelope-from ) id 1ajDUn-0006TW-Ok; Thu, 24 Mar 2016 23:12:49 +0100 From: Samuel Thibault To: qemu-devel@nongnu.org Date: Thu, 24 Mar 2016 23:12:48 +0100 Message-Id: <1458857568-24854-1-git-send-email-samuel.thibault@ens-lyon.org> X-Mailer: git-send-email 2.8.0.rc3 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 140.77.166.138 Cc: thuth@redhat.com, jan.kiszka@siemens.com, jasowang@redhat.com, armbru@redhat.com, Samuel Thibault Subject: [Qemu-devel] [PATCHv2] slirp: Allow disabling IPv4 or IPv6 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add ipv4 and ipv6 boolean options, so the user can setup IPv4-only and IPv6-only network environments. Signed-off-by: Samuel Thibault --- Changes since previous versions: - Introduce boolean options ipv4 and ipv6 instead of net=none and ip6-net=none. - Rename ipv6 options to ipv6-foo instead of ip6-foo, to make it coherent with the new ipv6 option (itself coherent with the other ipv6 options) - Reject incoherent configuration (e.g. v4 address but v4 disabled) net/slirp.c | 35 +++++++++++++++++++++++++++-------- qapi-schema.json | 33 ++++++++++++++++++++++++--------- qemu-options.hx | 29 ++++++++++++++++++----------- 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, 99 insertions(+), 30 deletions(-) diff --git a/net/slirp.c b/net/slirp.c index 95239bc..b7978be 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 ipv4, const char *vnetwork, const char *vhost, + bool ipv6, 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,16 @@ static int net_slirp_init(NetClientState *peer, const char *model, char *end; struct slirp_config_str *config; + if (!ipv4 && (vnetwork || vhost || vnameserver)) + return -1; + + if (!ipv6 && (vprefix6 || vhost6 || vnameserver6)) + return -1; + + if (!ipv4 && !ipv6) + /* It doesn't make sense to disable both */ + return -1; + if (!tftp_export) { tftp_export = legacy_tftp_prefix; } @@ -308,8 +318,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, ipv4, net, mask, host, + ipv6, ip6_prefix, vprefix6_len, ip6_host, vhostname, tftp_export, bootfile, dhcp, dns, ip6_dns, dnssearch, s); QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry); @@ -812,10 +822,18 @@ int net_init_slirp(const NetClientOptions *opts, const char *name, int ret; const NetdevUserOptions *user; const char **dnssearch; + int ipv4 = 1, ipv6 = 1; assert(opts->type == NET_CLIENT_OPTIONS_KIND_USER); user = opts->u.user.data; + if ((user->has_ipv6 && user->ipv6 && !user->has_ipv4) + || (user->has_ipv4 && !user->ipv4)) + ipv4 = 0; + if ((user->has_ipv4 && user->ipv4 && !user->has_ipv6) + || (user->has_ipv6 && !user->ipv6)) + ipv6 = 0; + vnet = user->has_net ? g_strdup(user->net) : user->has_ip ? g_strdup_printf("%s/24", user->ip) : NULL; @@ -827,11 +845,12 @@ 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, - user->ip6_host, user->hostname, user->tftp, + ret = net_slirp_init(peer, "user", name, user->q_restrict, + ipv4, vnet, user->host, + ipv6, user->ipv6_prefix, user->ipv6_prefixlen, + user->ipv6_host, user->hostname, user->tftp, user->bootfile, user->dhcpstart, - user->dns, user->ip6_dns, user->smb, + user->dns, user->ipv6_dns, user->smb, user->smbserver, dnssearch); while (slirp_configs) { diff --git a/qapi-schema.json b/qapi-schema.json index 88f9b81..8a10beb 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2425,9 +2425,18 @@ # # @restrict: #optional isolate the guest from the host # +# @ipv4: #optional whether to support IPv4, default is to support both +# IPv4 and IPv6 (since 2.6) +# +# @ipv6: #optional whether to support IPv6, default is to support both +# IPv4 and IPv6 (since 2.6) +# # @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,13 +2452,17 @@ # @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) +# @ipv6-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) +# @ipv6-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) +# @ipv6-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) +# @ipv6-dns: #optional guest-visible IPv6 address of the virtual +# nameserver (since 2.6) # # @smb: #optional root directory of the built-in SMB server # @@ -2466,6 +2479,8 @@ 'data': { '*hostname': 'str', '*restrict': 'bool', + '*ipv4': 'bool', + '*ipv6': 'bool', '*ip': 'str', '*net': 'str', '*host': 'str', @@ -2474,10 +2489,10 @@ '*dhcpstart': 'str', '*dns': 'str', '*dnssearch': ['String'], - '*ip6-prefix': 'str', - '*ip6-prefixlen': 'int', - '*ip6-host': 'str', - '*ip6-dns': 'str', + '*ipv6-prefix': 'str', + '*ipv6-prefixlen': 'int', + '*ipv6-host': 'str', + '*ipv6-dns': 'str', '*smb': 'str', '*smbserver': 'str', '*hostfwd': ['String'], diff --git a/qemu-options.hx b/qemu-options.hx index 732ed8c..c3ce4ce 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1560,9 +1560,10 @@ 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" - " [,dns=addr][,ip6-dns=addr][,dnssearch=domain][,tftp=dir]\n" + "-netdev user,id=str[,ip4][,net=addr[/mask]][,host=addr]\n" + " [,ipv6][,ipv6-net=addr[/int]][,ipv6-host=addr]\n" + " [,restrict=on|off][,hostname=host][,dhcpstart=addr]\n" + " [,dns=addr][,ipv6-dns=addr][,dnssearch=domain][,tftp=dir]\n" " [,bootfile=f][,hostfwd=rule][,guestfwd=rule]" #ifndef _WIN32 "[,smb=dir[,smbserver=addr]]\n" @@ -1710,20 +1711,26 @@ Connect user mode stack to VLAN @var{n} (@var{n} = 0 is the default). @itemx name=@var{name} Assign symbolic name for use in monitor commands. +@option{ipv4} and @option{ipv6} specify that either IPv4 or IPv6 must +be enabled. If neither is specified both protocols are enabled. + @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. 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. @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. +@item ipv6-net=@var{addr}[/@var{int}] +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} +@item ipv6-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. @@ -1744,7 +1751,7 @@ 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} +@item ipv6-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. 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;