slirp: Adding IPv6 address for DNS relay
authorGuillaume Subiron <maethor@subiron.org>
Tue, 15 Mar 2016 09:31:22 +0000 (10:31 +0100)
committerSamuel Thibault <samuel.thibault@ens-lyon.org>
Tue, 15 Mar 2016 09:35:22 +0000 (10:35 +0100)
This patch adds an IPv6 address to the DNS relay. in6_equal_dns() is
developed using this Slirp attribute.
sotranslate_in/out/accept() are also updated to manage the IPv6 case so the
guest can be able to join the host using one of the Slirp addresses.

For now this only points to localhost. Further development will be needed to
automatically fetch the IPv6 address from resolv.conf, and announce this via
RDNSS.

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
slirp/ip6.h
slirp/slirp.c
slirp/slirp.h
slirp/socket.c

index 731ee72d7748ecb6c460beea633753c38482135d..8ddfa242c4c21a1d6e776c1fb2e428bec77ed22e 100644 (file)
@@ -72,7 +72,11 @@ static inline bool in6_equal_mach(const struct in6_addr *a,
   || (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64)\
       && in6_equal_mach(a, &slirp->vhost_addr6, 64)))
 
-#define in6_equal_dns(a) 0
+#define in6_equal_dns(a)\
+    ((in6_equal_net(a, &slirp->vprefix_addr6, slirp->vprefix_len)\
+      && in6_equal_mach(a, &slirp->vnameserver_addr6, slirp->vprefix_len))\
+  || (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64)\
+      && in6_equal_mach(a, &slirp->vnameserver_addr6, 64)))
 
 #define in6_equal_host(a)\
     (in6_equal_router(a) || in6_equal_dns(a))
index 50b36f4126bfda5e423275d8e441d607cc6caa93..7a47bb60a95593ccca48aa742588b0430d9beca6 100644 (file)
@@ -231,10 +231,13 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
     slirp->vprefix_len = 64;
     slirp->vhost_addr6 = slirp->vprefix_addr6;
     slirp->vhost_addr6.s6_addr[15] = 0x2;
+    slirp->vnameserver_addr6 = slirp->vprefix_addr6;
+    slirp->vnameserver_addr6.s6_addr[15] = 0x3;
 #else
     inet_pton(AF_INET6, "fec0::0", &slirp->vprefix_addr6);
     slirp->vprefix_len = 64;
     inet_pton(AF_INET6, "fec0::2", &slirp->vhost_addr6);
+    inet_pton(AF_INET6, "fec0::3", &slirp->vnameserver_addr6);
 #endif
     if (vhostname) {
         pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
index 2850ef16650029f8312eff057496d355fcfbc3b9..71f243946149d7936e721626efee2801e0db56ef 100644 (file)
@@ -212,6 +212,7 @@ struct Slirp {
     struct in6_addr vhost_addr6;
     struct in_addr vdhcp_startaddr;
     struct in_addr vnameserver_addr;
+    struct in6_addr vnameserver_addr6;
 
     struct in_addr client_ipaddr;
     char client_hostname[33];
index 8df9252544d2f638caeca0d213261a75cef92155..b836c42b8e11953930b98e4af45c4544b0c706f7 100644 (file)
@@ -771,6 +771,7 @@ void sotranslate_out(struct socket *so, struct sockaddr_storage *addr)
 {
     Slirp *slirp = so->slirp;
     struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
 
     switch (addr->ss_family) {
     case AF_INET:
@@ -791,6 +792,19 @@ void sotranslate_out(struct socket *so, struct sockaddr_storage *addr)
             ntohs(sin->sin_port), inet_ntoa(sin->sin_addr)));
         break;
 
+    case AF_INET6:
+        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 */
+                    sin6->sin6_addr = in6addr_loopback;
+                /*}*/
+            } else {
+                sin6->sin6_addr = in6addr_loopback;
+            }
+        }
+        break;
+
     default:
         break;
     }
@@ -800,6 +814,7 @@ void sotranslate_in(struct socket *so, struct sockaddr_storage *addr)
 {
     Slirp *slirp = so->slirp;
     struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
 
     switch (addr->ss_family) {
     case AF_INET:
@@ -816,6 +831,16 @@ void sotranslate_in(struct socket *so, struct sockaddr_storage *addr)
         }
         break;
 
+    case AF_INET6:
+        if (in6_equal_net(&so->so_faddr6, &slirp->vprefix_addr6,
+                    slirp->vprefix_len)) {
+            if (in6_equal(&sin6->sin6_addr, &in6addr_loopback)
+                    || !in6_equal(&so->so_faddr6, &slirp->vhost_addr6)) {
+                sin6->sin6_addr = so->so_faddr6;
+            }
+        }
+        break;
+
     default:
         break;
     }
@@ -837,6 +862,13 @@ void sotranslate_accept(struct socket *so)
         }
         break;
 
+   case AF_INET6:
+        if (in6_equal(&so->so_faddr6, &in6addr_any) ||
+                in6_equal(&so->so_faddr6, &in6addr_loopback)) {
+           so->so_faddr6 = slirp->vhost_addr6;
+        }
+        break;
+
     default:
         break;
     }