]> git.proxmox.com Git - mirror_qemu.git/commitdiff
slirp: Allow disabling IPv4 or IPv6
authorSamuel Thibault <samuel.thibault@ens-lyon.org>
Sun, 20 Mar 2016 11:29:54 +0000 (12:29 +0100)
committerSamuel Thibault <samuel.thibault@ens-lyon.org>
Fri, 1 Apr 2016 15:51:55 +0000 (17:51 +0200)
Add ipv4 and ipv6 boolean options, so the user can setup IPv4-only and
IPv6-only network environments.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
net/slirp.c
qapi-schema.json
qemu-options.hx
slirp/ip6_icmp.c
slirp/ip6_input.c
slirp/ip_input.c
slirp/libslirp.h
slirp/slirp.c
slirp/slirp.h

index 791a8f7b89d3256762812e24fff4902bf3a06f8c..31630f005ce78143055e3a2c1e14f6f51dae15b5 100644 (file)
@@ -136,8 +136,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,
@@ -165,6 +165,19 @@ 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;
     }
@@ -309,8 +322,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);
@@ -813,10 +826,20 @@ int net_init_slirp(const NetClientOptions *opts, const char *name,
     int ret;
     const NetdevUserOptions *user;
     const char **dnssearch;
+    bool ipv4 = true, ipv6 = true;
 
     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;
@@ -828,8 +851,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,
index e58f6a9a12984dce72f1cc7074d485c1a195df42..54634c473bd23b6bbcd1223aa65a2fc50c87a6c8 100644 (file)
 #
 # @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
   'data': {
     '*hostname':  'str',
     '*restrict':  'bool',
+    '*ipv4':      'bool',
+    '*ipv6':      'bool',
     '*ip':        'str',
     '*net':       'str',
     '*host':      'str',
index a770086f44a1ae258a899336d7847ccb9761aca8..789d9f681e2e92f155f28dd28a02e471e50606e0 100644 (file)
@@ -1551,8 +1551,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[=on|off]][,net=addr[/mask]][,host=addr]\n"
+    "         [,ipv6[=on|off]][,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
@@ -1701,6 +1702,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
index 9d61349c7d562fe213ec36bf0a7d5fe65db513e4..09571bcd6b7946a8d5d682fdfe0ed3f1bd773888 100644 (file)
@@ -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);
 }
index c0b11e73cd57b1391ba1fad59aa3f46c3184ce9d..ac2e3ea882a7b184e3156855a647c4c0c4c60208 100644 (file)
@@ -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);
index b464f6baf0a3946ebf52c1d97af4c56857e42b47..cdd54833a342e4146d6caa10f141451a2f2f4ec2 100644 (file)
@@ -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);
index c4b25c90e663e2112535c8e235069237c9b2501a..127aa41d40aa7a8ce39209801dc02b75c941e0ed 100644 (file)
@@ -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,
index 998f27876c4cbba6b335bbc557809deaa876a0ec..fef526c5ad5f84e773ed00d677003fb7ba181b5a 100644 (file)
@@ -200,8 +200,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,
@@ -216,6 +217,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);
@@ -694,6 +698,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:
index 1abbcc6c32420c786e884a4832077c0e4894ddb7..c99ebb96214ea3912b9cfd6da61a0431b595f0e8 100644 (file)
@@ -180,6 +180,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;