From patchwork Thu Mar 24 23:25:55 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Thibault X-Patchwork-Id: 8665481 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 87D35C0553 for ; Thu, 24 Mar 2016 23:27:17 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8A4DD202B8 for ; Thu, 24 Mar 2016 23:27:16 +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 629C820268 for ; Thu, 24 Mar 2016 23:27:15 +0000 (UTC) Received: from localhost ([::1]:53309 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ajEeo-00072n-Po for patchwork-qemu-devel@patchwork.kernel.org; Thu, 24 Mar 2016 19:27:14 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57365) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ajEdd-00056S-Pv for qemu-devel@nongnu.org; Thu, 24 Mar 2016 19:26:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ajEdb-00008j-7c for qemu-devel@nongnu.org; Thu, 24 Mar 2016 19:26:01 -0400 Received: from domu-toccata.ens-lyon.fr ([140.77.166.138]:58376 helo=sonata.ens-lyon.org) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ajEda-00008G-Sf for qemu-devel@nongnu.org; Thu, 24 Mar 2016 19:25:59 -0400 Received: from localhost (localhost [127.0.0.1]) by sonata.ens-lyon.org (Postfix) with ESMTP id 2FE4B2011C; Fri, 25 Mar 2016 00:25:57 +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 eDW3IhRInNXJ; Fri, 25 Mar 2016 00:25:57 +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 C763920113; Fri, 25 Mar 2016 00:25:56 +0100 (CET) Received: from samy by var.youpi.perso.aquilenet.fr with local (Exim 4.86_2) (envelope-from ) id 1ajEdX-0002ws-PX; Fri, 25 Mar 2016 00:25:55 +0100 From: Samuel Thibault To: qemu-devel@nongnu.org Date: Fri, 25 Mar 2016 00:25:55 +0100 Message-Id: <1458861955-11200-3-git-send-email-samuel.thibault@ens-lyon.org> X-Mailer: git-send-email 2.8.0.rc3 In-Reply-To: <1458861955-11200-1-git-send-email-samuel.thibault@ens-lyon.org> References: <1458861955-11200-1-git-send-email-samuel.thibault@ens-lyon.org> 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] [PATCHv3 2/2] 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. Also rename recently-added options to make the whole coherent before 2.6 gets released. 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 | 31 +++++++++++++++++++++++++------ qapi-schema.json | 8 ++++++++ qemu-options.hx | 8 ++++++-- 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, 69 insertions(+), 10 deletions(-) diff --git a/net/slirp.c b/net/slirp.c index 0013c27..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,8 +845,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->ipv6_prefix, user->ipv6_prefixlen, + 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->ipv6_dns, user->smb, diff --git a/qapi-schema.json b/qapi-schema.json index e1dd7e1..331997b 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2425,6 +2425,12 @@ # # @restrict: #optional isolate the guest from the host # +# @ipv4: #optional whether to support IPv4, default true for enabled +# (since 2.6) +# +# @ipv6: #optional whether to support IPv6, default true for enabled +# (since 2.6) +# # @ip: #optional legacy parameter, use net= instead # # @net: #optional IP network address that the guest will see, in the @@ -2473,6 +2479,8 @@ 'data': { '*hostname': 'str', '*restrict': 'bool', + '*ipv4': 'bool', + '*ipv6': 'bool', '*ip': 'str', '*net': 'str', '*host': 'str', diff --git a/qemu-options.hx b/qemu-options.hx index 5654ce3..25e4494 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][,ipv6-net=addr[/int]]\n" - " [,ipv6-host=addr][,restrict=on|off][,hostname=host][,dhcpstart=addr]\n" + "-netdev user,id=str[,ipv4][,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 @@ -1710,6 +1711,9 @@ 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 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 12f173d..ccbcc79 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;