All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCHv2 0/5] ipv4-only and ipv6-only support
@ 2016-03-30 22:58 Samuel Thibault
  2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 1/5] slirp: Allow disabling IPv4 or IPv6 Samuel Thibault
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Samuel Thibault @ 2016-03-30 22:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: thuth, jan.kiszka, jasowang, armbru, Samuel Thibault

Hello,

This series gathers the patches to enable ipv4-only and ipv6-only support: it
adds the discussed ipv4 and ipv6 options to select which is enabled, and adds
support for ipv6 dns translation.

Changes since previous submission:

- code layout
- cope with inet_ntop returning NULL
- move static variables to function using them.
- remove superfluous parenthesis.
- fix coding style
- explicit that qemu options can take ipv[46]=on|off

Samuel Thibault (5):
  slirp: Allow disabling IPv4 or IPv6
  slirp: Split get_dns_addr
  slirp: Add dns6 resolution
  slirp: Support link-local DNS addresses
  slirp: Add RDNSS advertisement

 net/slirp.c       |  36 ++++++++++++---
 qapi-schema.json  |   8 ++++
 qemu-options.hx   |   8 +++-
 slirp/ip6.h       |   9 ++++
 slirp/ip6_icmp.c  |  27 +++++++++--
 slirp/ip6_icmp.h  |  12 ++++-
 slirp/ip6_input.c |   5 +++
 slirp/ip_input.c  |   4 ++
 slirp/libslirp.h  |   4 +-
 slirp/slirp.c     | 132 ++++++++++++++++++++++++++++++++++++++++++------------
 slirp/slirp.h     |   2 +
 slirp/socket.c    |   4 +-
 12 files changed, 207 insertions(+), 44 deletions(-)

-- 
2.8.0.rc3

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCHv2 1/5] slirp: Allow disabling IPv4 or IPv6
  2016-03-30 22:58 [Qemu-devel] [PATCHv2 0/5] ipv4-only and ipv6-only support Samuel Thibault
@ 2016-03-30 22:58 ` Samuel Thibault
  2016-03-31  8:56   ` Thomas Huth
  2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 2/5] slirp: Split get_dns_addr Samuel Thibault
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Samuel Thibault @ 2016-03-30 22:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: thuth, jan.kiszka, jasowang, armbru, Samuel Thibault

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>

---

Changes since previous versions:

- fix coding style
- explicit that qemu options can take ipv[46]=on|off
---
 net/slirp.c       | 36 ++++++++++++++++++++++++++++++------
 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, 74 insertions(+), 10 deletions(-)

diff --git a/net/slirp.c b/net/slirp.c
index 791a8f7..31630f0 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -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,
diff --git a/qapi-schema.json b/qapi-schema.json
index e58f6a9..54634c4 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 a770086..789d9f6 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -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
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 3481fcc..cefb9dc 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -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:
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 1abbcc6..c99ebb9 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -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;
-- 
2.8.0.rc3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCHv2 2/5] slirp: Split get_dns_addr
  2016-03-30 22:58 [Qemu-devel] [PATCHv2 0/5] ipv4-only and ipv6-only support Samuel Thibault
  2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 1/5] slirp: Allow disabling IPv4 or IPv6 Samuel Thibault
@ 2016-03-30 22:58 ` Samuel Thibault
  2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 3/5] slirp: Add dns6 resolution Samuel Thibault
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Samuel Thibault @ 2016-03-30 22:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: thuth, jan.kiszka, jasowang, armbru, Samuel Thibault

Separate get_dns_addr into get_dns_addr_cached and get_dns_addr_resolv_conf
to make conversion to IPv6 easier.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>

---
Change since v1: remove superfluous parenthesis.
---
 slirp/slirp.c | 53 ++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 34 insertions(+), 19 deletions(-)

diff --git a/slirp/slirp.c b/slirp/slirp.c
index cefb9dc..4478a43 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -109,7 +109,28 @@ static void winsock_cleanup(void)
 
 static struct stat dns_addr_stat;
 
-int get_dns_addr(struct in_addr *pdns_addr)
+static int get_dns_addr_cached(struct in_addr *pdns_addr)
+{
+    struct stat old_stat;
+    if (curtime - dns_addr_time < TIMEOUT_DEFAULT) {
+        *pdns_addr = dns_addr;
+        return 0;
+    }
+    old_stat = dns_addr_stat;
+    if (stat("/etc/resolv.conf", &dns_addr_stat) != 0) {
+        return -1;
+    }
+    if (dns_addr_stat.st_dev == old_stat.st_dev
+        && dns_addr_stat.st_ino == old_stat.st_ino
+        && dns_addr_stat.st_size == old_stat.st_size
+        && dns_addr_stat.st_mtime == old_stat.st_mtime) {
+        *pdns_addr = dns_addr;
+        return 0;
+    }
+    return 1;
+}
+
+static int get_dns_addr_resolv_conf(struct in_addr *pdns_addr)
 {
     char buff[512];
     char buff2[257];
@@ -117,24 +138,6 @@ int get_dns_addr(struct in_addr *pdns_addr)
     int found = 0;
     struct in_addr tmp_addr;
 
-    if (dns_addr.s_addr != 0) {
-        struct stat old_stat;
-        if ((curtime - dns_addr_time) < TIMEOUT_DEFAULT) {
-            *pdns_addr = dns_addr;
-            return 0;
-        }
-        old_stat = dns_addr_stat;
-        if (stat("/etc/resolv.conf", &dns_addr_stat) != 0)
-            return -1;
-        if ((dns_addr_stat.st_dev == old_stat.st_dev)
-            && (dns_addr_stat.st_ino == old_stat.st_ino)
-            && (dns_addr_stat.st_size == old_stat.st_size)
-            && (dns_addr_stat.st_mtime == old_stat.st_mtime)) {
-            *pdns_addr = dns_addr;
-            return 0;
-        }
-    }
-
     f = fopen("/etc/resolv.conf", "r");
     if (!f)
         return -1;
@@ -174,6 +177,18 @@ int get_dns_addr(struct in_addr *pdns_addr)
     return 0;
 }
 
+int get_dns_addr(struct in_addr *pdns_addr)
+{
+    if (dns_addr.s_addr != 0) {
+        int ret;
+        ret = get_dns_addr_cached(pdns_addr);
+        if (ret <= 0) {
+            return ret;
+        }
+    }
+    return get_dns_addr_resolv_conf(pdns_addr);
+}
+
 #endif
 
 static void slirp_init_once(void)
-- 
2.8.0.rc3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCHv2 3/5] slirp: Add dns6 resolution
  2016-03-30 22:58 [Qemu-devel] [PATCHv2 0/5] ipv4-only and ipv6-only support Samuel Thibault
  2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 1/5] slirp: Allow disabling IPv4 or IPv6 Samuel Thibault
  2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 2/5] slirp: Split get_dns_addr Samuel Thibault
@ 2016-03-30 22:58 ` Samuel Thibault
  2016-03-31  9:04   ` Thomas Huth
  2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 4/5] slirp: Support link-local DNS addresses Samuel Thibault
  2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 5/5] slirp: Add RDNSS advertisement Samuel Thibault
  4 siblings, 1 reply; 9+ messages in thread
From: Samuel Thibault @ 2016-03-30 22:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: thuth, jan.kiszka, jasowang, armbru, Samuel Thibault

This makes get_dns_addr address family-agnostic, thus allowing to add the
IPv6 case.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>

---
Changes since v1:
- code layout
- cope with inet_ntop returning NULL
- move static variables to function using them.
---
 slirp/ip6.h      |  9 +++++++
 slirp/libslirp.h |  1 +
 slirp/slirp.c    | 79 ++++++++++++++++++++++++++++++++++++++++----------------
 slirp/socket.c   |  4 +--
 4 files changed, 69 insertions(+), 24 deletions(-)

diff --git a/slirp/ip6.h b/slirp/ip6.h
index 8ddfa24..da23de6 100644
--- a/slirp/ip6.h
+++ b/slirp/ip6.h
@@ -26,6 +26,12 @@
                         0x00, 0x00, 0x00, 0x00,\
                         0x00, 0x00, 0x00, 0x02 } }
 
+#define ZERO_ADDR  { .s6_addr = \
+                        { 0x00, 0x00, 0x00, 0x00,\
+                        0x00, 0x00, 0x00, 0x00,\
+                        0x00, 0x00, 0x00, 0x00,\
+                        0x00, 0x00, 0x00, 0x00 } }
+
 static inline bool in6_equal(const struct in6_addr *a, const struct in6_addr *b)
 {
     return memcmp(a, b, sizeof(*a)) == 0;
@@ -84,6 +90,9 @@ static inline bool in6_equal_mach(const struct in6_addr *a,
 #define in6_solicitednode_multicast(a)\
     (in6_equal_net(a, &(struct in6_addr)SOLICITED_NODE_PREFIX, 104))
 
+#define in6_zero(a)\
+    (in6_equal(a, &(struct in6_addr)ZERO_ADDR))
+
 /* Compute emulated host MAC address from its ipv6 address */
 static inline void in6_compute_ethaddr(struct in6_addr ip,
                                        uint8_t eth[ETH_ALEN])
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 127aa41..b0cfbc5 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -7,6 +7,7 @@ struct Slirp;
 typedef struct Slirp Slirp;
 
 int get_dns_addr(struct in_addr *pdns_addr);
+int get_dns6_addr(struct in6_addr *pdns6_addr);
 
 Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
                   struct in_addr vnetmask, struct in_addr vhost,
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 4478a43..c6bcc6e 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -46,7 +46,9 @@ static QTAILQ_HEAD(slirp_instances, Slirp) slirp_instances =
     QTAILQ_HEAD_INITIALIZER(slirp_instances);
 
 static struct in_addr dns_addr;
+static struct in6_addr dns6_addr;
 static u_int dns_addr_time;
+static u_int dns6_addr_time;
 
 #define TIMEOUT_FAST 2  /* milliseconds */
 #define TIMEOUT_SLOW 499  /* milliseconds */
@@ -100,6 +102,11 @@ int get_dns_addr(struct in_addr *pdns_addr)
     return 0;
 }
 
+int get_dns6_addr(struct in6_addr *pdns_addr6)
+{
+    return -1;
+}
+
 static void winsock_cleanup(void)
 {
     WSACleanup();
@@ -107,36 +114,37 @@ static void winsock_cleanup(void)
 
 #else
 
-static struct stat dns_addr_stat;
-
-static int get_dns_addr_cached(struct in_addr *pdns_addr)
+static int get_dns_addr_cached(void *pdns_addr, void *cached_addr,
+                               socklen_t addrlen,
+                               struct stat *cached_stat, u_int *cached_time)
 {
     struct stat old_stat;
-    if (curtime - dns_addr_time < TIMEOUT_DEFAULT) {
-        *pdns_addr = dns_addr;
+    if (curtime - *cached_time < TIMEOUT_DEFAULT) {
+        memcpy(pdns_addr, cached_addr, addrlen);
         return 0;
     }
-    old_stat = dns_addr_stat;
-    if (stat("/etc/resolv.conf", &dns_addr_stat) != 0) {
+    old_stat = *cached_stat;
+    if (stat("/etc/resolv.conf", cached_stat) != 0) {
         return -1;
     }
-    if (dns_addr_stat.st_dev == old_stat.st_dev
-        && dns_addr_stat.st_ino == old_stat.st_ino
-        && dns_addr_stat.st_size == old_stat.st_size
-        && dns_addr_stat.st_mtime == old_stat.st_mtime) {
-        *pdns_addr = dns_addr;
+    if (cached_stat->st_dev == old_stat.st_dev
+        && cached_stat->st_ino == old_stat.st_ino
+        && cached_stat->st_size == old_stat.st_size
+        && cached_stat->st_mtime == old_stat.st_mtime) {
+        memcpy(pdns_addr, cached_addr, addrlen);
         return 0;
     }
     return 1;
 }
 
-static int get_dns_addr_resolv_conf(struct in_addr *pdns_addr)
+static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr,
+                                    socklen_t addrlen, u_int *cached_time)
 {
     char buff[512];
     char buff2[257];
     FILE *f;
     int found = 0;
-    struct in_addr tmp_addr;
+    void *tmp_addr = alloca(addrlen);
 
     f = fopen("/etc/resolv.conf", "r");
     if (!f)
@@ -147,13 +155,14 @@ static int get_dns_addr_resolv_conf(struct in_addr *pdns_addr)
 #endif
     while (fgets(buff, 512, f) != NULL) {
         if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
-            if (!inet_aton(buff2, &tmp_addr))
+            if (!inet_pton(af, buff2, tmp_addr)) {
                 continue;
+            }
             /* If it's the first one, set it to dns_addr */
             if (!found) {
-                *pdns_addr = tmp_addr;
-                dns_addr = tmp_addr;
-                dns_addr_time = curtime;
+                memcpy(pdns_addr, tmp_addr, addrlen);
+                memcpy(cached_addr, tmp_addr, addrlen);
+                *cached_time = curtime;
             }
 #ifdef DEBUG
             else
@@ -166,8 +175,14 @@ static int get_dns_addr_resolv_conf(struct in_addr *pdns_addr)
                 break;
             }
 #ifdef DEBUG
-            else
-                fprintf(stderr, "%s", inet_ntoa(tmp_addr));
+            else {
+                char s[INET6_ADDRSTRLEN];
+                char *res = inet_ntop(af, tmp_addr, s, sizeof(s));
+                if (!res) {
+                    res = "(string conversion error)";
+                }
+                fprintf(stderr, "%s", res);
+            }
 #endif
         }
     }
@@ -179,14 +194,34 @@ static int get_dns_addr_resolv_conf(struct in_addr *pdns_addr)
 
 int get_dns_addr(struct in_addr *pdns_addr)
 {
+    static struct stat dns_addr_stat;
+
     if (dns_addr.s_addr != 0) {
         int ret;
-        ret = get_dns_addr_cached(pdns_addr);
+        ret = get_dns_addr_cached(pdns_addr, &dns_addr, sizeof(dns_addr),
+                                  &dns_addr_stat, &dns_addr_time);
+        if (ret <= 0) {
+            return ret;
+        }
+    }
+    return get_dns_addr_resolv_conf(AF_INET, pdns_addr, &dns_addr,
+                                    sizeof(dns_addr), &dns_addr_time);
+}
+
+int get_dns6_addr(struct in6_addr *pdns6_addr)
+{
+    static struct stat dns6_addr_stat;
+
+    if (!in6_zero(&dns6_addr)) {
+        int ret;
+        ret = get_dns_addr_cached(pdns6_addr, &dns6_addr, sizeof(dns6_addr),
+                                  &dns6_addr_stat, &dns6_addr_time);
         if (ret <= 0) {
             return ret;
         }
     }
-    return get_dns_addr_resolv_conf(pdns_addr);
+    return get_dns_addr_resolv_conf(AF_INET6, pdns6_addr, &dns6_addr,
+                                    sizeof(dns6_addr), &dns6_addr_time);
 }
 
 #endif
diff --git a/slirp/socket.c b/slirp/socket.c
index b836c42..653257d 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -796,9 +796,9 @@ void sotranslate_out(struct socket *so, struct sockaddr_storage *addr)
         if (in6_equal_net(&so->so_faddr6, &slirp->vprefix_addr6,
                     slirp->vprefix_len)) {
             if (in6_equal(&so->so_faddr6, &slirp->vnameserver_addr6)) {
-                /*if (get_dns_addr(&addr) < 0) {*/ /* TODO */
+                if (get_dns6_addr(&sin6->sin6_addr) < 0) {
                     sin6->sin6_addr = in6addr_loopback;
-                /*}*/
+                }
             } else {
                 sin6->sin6_addr = in6addr_loopback;
             }
-- 
2.8.0.rc3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCHv2 4/5] slirp: Support link-local DNS addresses
  2016-03-30 22:58 [Qemu-devel] [PATCHv2 0/5] ipv4-only and ipv6-only support Samuel Thibault
                   ` (2 preceding siblings ...)
  2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 3/5] slirp: Add dns6 resolution Samuel Thibault
@ 2016-03-30 22:58 ` Samuel Thibault
  2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 5/5] slirp: Add RDNSS advertisement Samuel Thibault
  4 siblings, 0 replies; 9+ messages in thread
From: Samuel Thibault @ 2016-03-30 22:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: thuth, jan.kiszka, jasowang, armbru, Samuel Thibault

They look like fe80::%eth0

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
 slirp/libslirp.h |  2 +-
 slirp/slirp.c    | 26 ++++++++++++++++++++++----
 slirp/socket.c   |  2 +-
 3 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index b0cfbc5..81bd139 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -7,7 +7,7 @@ struct Slirp;
 typedef struct Slirp Slirp;
 
 int get_dns_addr(struct in_addr *pdns_addr);
-int get_dns6_addr(struct in6_addr *pdns6_addr);
+int get_dns6_addr(struct in6_addr *pdns6_addr, unsigned *scope_id);
 
 Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
                   struct in_addr vnetmask, struct in_addr vhost,
diff --git a/slirp/slirp.c b/slirp/slirp.c
index c6bcc6e..c00fa32 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -30,6 +30,10 @@
 #include "hw/hw.h"
 #include "qemu/cutils.h"
 
+#ifndef _WIN32
+#include <net/if.h>
+#endif
+
 /* host loopback address */
 struct in_addr loopback_addr;
 /* host loopback network mask */
@@ -138,13 +142,15 @@ static int get_dns_addr_cached(void *pdns_addr, void *cached_addr,
 }
 
 static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr,
-                                    socklen_t addrlen, u_int *cached_time)
+                                    socklen_t addrlen, unsigned *scope_id,
+                                    u_int *cached_time)
 {
     char buff[512];
     char buff2[257];
     FILE *f;
     int found = 0;
     void *tmp_addr = alloca(addrlen);
+    unsigned if_index;
 
     f = fopen("/etc/resolv.conf", "r");
     if (!f)
@@ -155,6 +161,14 @@ static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr,
 #endif
     while (fgets(buff, 512, f) != NULL) {
         if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
+            char *c = strchr(buff2, '%');
+            if (c) {
+                if_index = if_nametoindex(c + 1);
+                *c = '\0';
+            } else {
+                if_index = 0;
+            }
+
             if (!inet_pton(af, buff2, tmp_addr)) {
                 continue;
             }
@@ -162,6 +176,9 @@ static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr,
             if (!found) {
                 memcpy(pdns_addr, tmp_addr, addrlen);
                 memcpy(cached_addr, tmp_addr, addrlen);
+                if (scope_id) {
+                    *scope_id = if_index;
+                }
                 *cached_time = curtime;
             }
 #ifdef DEBUG
@@ -205,10 +222,10 @@ int get_dns_addr(struct in_addr *pdns_addr)
         }
     }
     return get_dns_addr_resolv_conf(AF_INET, pdns_addr, &dns_addr,
-                                    sizeof(dns_addr), &dns_addr_time);
+                                    sizeof(dns_addr), NULL, &dns_addr_time);
 }
 
-int get_dns6_addr(struct in6_addr *pdns6_addr)
+int get_dns6_addr(struct in6_addr *pdns6_addr, unsigned *scope_id)
 {
     static struct stat dns6_addr_stat;
 
@@ -221,7 +238,8 @@ int get_dns6_addr(struct in6_addr *pdns6_addr)
         }
     }
     return get_dns_addr_resolv_conf(AF_INET6, pdns6_addr, &dns6_addr,
-                                    sizeof(dns6_addr), &dns6_addr_time);
+                                    sizeof(dns6_addr),
+                                    scope_id, &dns6_addr_time);
 }
 
 #endif
diff --git a/slirp/socket.c b/slirp/socket.c
index 653257d..896c27e 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -796,7 +796,7 @@ void sotranslate_out(struct socket *so, struct sockaddr_storage *addr)
         if (in6_equal_net(&so->so_faddr6, &slirp->vprefix_addr6,
                     slirp->vprefix_len)) {
             if (in6_equal(&so->so_faddr6, &slirp->vnameserver_addr6)) {
-                if (get_dns6_addr(&sin6->sin6_addr) < 0) {
+                if (get_dns6_addr(&sin6->sin6_addr, &sin6->sin6_scope_id) < 0) {
                     sin6->sin6_addr = in6addr_loopback;
                 }
             } else {
-- 
2.8.0.rc3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCHv2 5/5] slirp: Add RDNSS advertisement
  2016-03-30 22:58 [Qemu-devel] [PATCHv2 0/5] ipv4-only and ipv6-only support Samuel Thibault
                   ` (3 preceding siblings ...)
  2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 4/5] slirp: Support link-local DNS addresses Samuel Thibault
@ 2016-03-30 22:58 ` Samuel Thibault
  4 siblings, 0 replies; 9+ messages in thread
From: Samuel Thibault @ 2016-03-30 22:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: thuth, jan.kiszka, jasowang, armbru, Samuel Thibault

This adds the RDNSS option to IPv6 router advertisements, so that the guest
can autoconfigure the DNS server address.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
 slirp/ip6_icmp.c | 19 ++++++++++++++++---
 slirp/ip6_icmp.h | 12 ++++++++++--
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/slirp/ip6_icmp.c b/slirp/ip6_icmp.c
index 09571bc..74585d1 100644
--- a/slirp/ip6_icmp.c
+++ b/slirp/ip6_icmp.c
@@ -149,7 +149,8 @@ void ndp_send_ra(Slirp *slirp)
     rip->ip_nh = IPPROTO_ICMPV6;
     rip->ip_pl = htons(ICMP6_NDP_RA_MINLEN
                         + NDPOPT_LINKLAYER_LEN
-                        + NDPOPT_PREFIXINFO_LEN);
+                        + NDPOPT_PREFIXINFO_LEN
+                        + NDPOPT_RDNSS_LEN);
     t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl);
 
     /* Build ICMPv6 packet */
@@ -167,16 +168,16 @@ void ndp_send_ra(Slirp *slirp)
     ricmp->icmp6_nra.lifetime = htons(NDP_AdvDefaultLifetime);
     ricmp->icmp6_nra.reach_time = htonl(NDP_AdvReachableTime);
     ricmp->icmp6_nra.retrans_time = htonl(NDP_AdvRetransTime);
+    t->m_data += ICMP6_NDP_RA_MINLEN;
 
     /* Source link-layer address (NDP option) */
-    t->m_data += ICMP6_NDP_RA_MINLEN;
     struct ndpopt *opt = mtod(t, struct ndpopt *);
     opt->ndpopt_type = NDPOPT_LINKLAYER_SOURCE;
     opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8;
     in6_compute_ethaddr(rip->ip_src, opt->ndpopt_linklayer);
+    t->m_data += NDPOPT_LINKLAYER_LEN;
 
     /* Prefix information (NDP option) */
-    t->m_data += NDPOPT_LINKLAYER_LEN;
     struct ndpopt *opt2 = mtod(t, struct ndpopt *);
     opt2->ndpopt_type = NDPOPT_PREFIX_INFO;
     opt2->ndpopt_len = NDPOPT_PREFIXINFO_LEN / 8;
@@ -188,8 +189,20 @@ void ndp_send_ra(Slirp *slirp)
     opt2->ndpopt_prefixinfo.pref_lt = htonl(NDP_AdvPrefLifetime);
     opt2->ndpopt_prefixinfo.reserved2 = 0;
     opt2->ndpopt_prefixinfo.prefix = slirp->vprefix_addr6;
+    t->m_data += NDPOPT_PREFIXINFO_LEN;
+
+    /* Prefix information (NDP option) */
+    struct ndpopt *opt3 = mtod(t, struct ndpopt *);
+    opt3->ndpopt_type = NDPOPT_RDNSS;
+    opt3->ndpopt_len = NDPOPT_RDNSS_LEN / 8;
+    opt3->ndpopt_rdnss.reserved = 0;
+    opt3->ndpopt_rdnss.lifetime = htonl(2 * NDP_MaxRtrAdvInterval);
+    opt3->ndpopt_rdnss.addr = slirp->vnameserver_addr6;
+    t->m_data += NDPOPT_RDNSS_LEN;
 
     /* ICMPv6 Checksum */
+    t->m_data -= NDPOPT_RDNSS_LEN;
+    t->m_data -= NDPOPT_PREFIXINFO_LEN;
     t->m_data -= NDPOPT_LINKLAYER_LEN;
     t->m_data -= ICMP6_NDP_RA_MINLEN;
     t->m_data -= sizeof(struct ip6);
diff --git a/slirp/ip6_icmp.h b/slirp/ip6_icmp.h
index 9460bf8..2282d29 100644
--- a/slirp/ip6_icmp.h
+++ b/slirp/ip6_icmp.h
@@ -122,6 +122,7 @@ struct ndpopt {
     uint8_t     ndpopt_len;                     /* /!\ In units of 8 octets */
     union {
         unsigned char   linklayer_addr[6];      /* Source/Target Link-layer */
+#define ndpopt_linklayer ndpopt_body.linklayer_addr
         struct prefixinfo {                     /* Prefix Information */
             uint8_t     prefix_length;
 #ifdef HOST_WORDS_BIGENDIAN
@@ -134,19 +135,26 @@ struct ndpopt {
             uint32_t    reserved2;
             struct in6_addr prefix;
         } QEMU_PACKED prefixinfo;
-    } ndpopt_body;
-#define ndpopt_linklayer ndpopt_body.linklayer_addr
 #define ndpopt_prefixinfo ndpopt_body.prefixinfo
+        struct rdnss {
+            uint16_t reserved;
+            uint32_t lifetime;
+            struct in6_addr addr;
+        } QEMU_PACKED rdnss;
+#define ndpopt_rdnss ndpopt_body.rdnss
+    } ndpopt_body;
 } QEMU_PACKED;
 
 /* NDP options type */
 #define NDPOPT_LINKLAYER_SOURCE     1   /* Source Link-Layer Address */
 #define NDPOPT_LINKLAYER_TARGET     2   /* Target Link-Layer Address */
 #define NDPOPT_PREFIX_INFO          3   /* Prefix Information */
+#define NDPOPT_RDNSS                25  /* Recursive DNS Server Address */
 
 /* NDP options size, in octets. */
 #define NDPOPT_LINKLAYER_LEN    8
 #define NDPOPT_PREFIXINFO_LEN   32
+#define NDPOPT_RDNSS_LEN        24
 
 /*
  * Definition of type and code field values.
-- 
2.8.0.rc3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCHv2 1/5] slirp: Allow disabling IPv4 or IPv6
  2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 1/5] slirp: Allow disabling IPv4 or IPv6 Samuel Thibault
@ 2016-03-31  8:56   ` Thomas Huth
  0 siblings, 0 replies; 9+ messages in thread
From: Thomas Huth @ 2016-03-31  8:56 UTC (permalink / raw)
  To: Samuel Thibault, qemu-devel; +Cc: jan.kiszka, jasowang, armbru

On 31.03.2016 00:58, Samuel Thibault wrote:
> 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>
> 
> ---
> 
> Changes since previous versions:
> 
> - fix coding style
> - explicit that qemu options can take ipv[46]=on|off
> ---
>  net/slirp.c       | 36 ++++++++++++++++++++++++++++++------
>  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, 74 insertions(+), 10 deletions(-)

Reviewed-by: Thomas Huth <thuth@redhat.com>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCHv2 3/5] slirp: Add dns6 resolution
  2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 3/5] slirp: Add dns6 resolution Samuel Thibault
@ 2016-03-31  9:04   ` Thomas Huth
  2016-03-31  9:20     ` Samuel Thibault
  0 siblings, 1 reply; 9+ messages in thread
From: Thomas Huth @ 2016-03-31  9:04 UTC (permalink / raw)
  To: Samuel Thibault, qemu-devel; +Cc: jan.kiszka, jasowang, armbru

On 31.03.2016 00:58, Samuel Thibault wrote:
> This makes get_dns_addr address family-agnostic, thus allowing to add the
> IPv6 case.
> 
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> 
> ---
> Changes since v1:
> - code layout
> - cope with inet_ntop returning NULL
> - move static variables to function using them.
> ---
>  slirp/ip6.h      |  9 +++++++
>  slirp/libslirp.h |  1 +
>  slirp/slirp.c    | 79 ++++++++++++++++++++++++++++++++++++++++----------------
>  slirp/socket.c   |  4 +--
>  4 files changed, 69 insertions(+), 24 deletions(-)

Reviewed-by: Thomas Huth <thuth@redhat.com>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCHv2 3/5] slirp: Add dns6 resolution
  2016-03-31  9:04   ` Thomas Huth
@ 2016-03-31  9:20     ` Samuel Thibault
  0 siblings, 0 replies; 9+ messages in thread
From: Samuel Thibault @ 2016-03-31  9:20 UTC (permalink / raw)
  To: Thomas Huth; +Cc: jan.kiszka, jasowang, qemu-devel, armbru

Hello,

Thanks for the reviews!

Samuel

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-03-31  9:21 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-30 22:58 [Qemu-devel] [PATCHv2 0/5] ipv4-only and ipv6-only support Samuel Thibault
2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 1/5] slirp: Allow disabling IPv4 or IPv6 Samuel Thibault
2016-03-31  8:56   ` Thomas Huth
2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 2/5] slirp: Split get_dns_addr Samuel Thibault
2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 3/5] slirp: Add dns6 resolution Samuel Thibault
2016-03-31  9:04   ` Thomas Huth
2016-03-31  9:20     ` Samuel Thibault
2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 4/5] slirp: Support link-local DNS addresses Samuel Thibault
2016-03-30 22:58 ` [Qemu-devel] [PATCHv2 5/5] slirp: Add RDNSS advertisement Samuel Thibault

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.