aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Subiron <maethor@subiron.org>2016-03-15 10:31:22 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2016-03-15 10:35:22 +0100
commit05061d8548598c92bda94de0c6159732e75da719 (patch)
treef9d78daeea7d03a31ef4bb0ff7fdb1f8494bade1
parent3feea4447f1b9b04816ee6977b5ecc0eb704e07a (diff)
slirp: Adding IPv6 address for DNS relay
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>
-rw-r--r--slirp/ip6.h6
-rw-r--r--slirp/slirp.c3
-rw-r--r--slirp/slirp.h1
-rw-r--r--slirp/socket.c32
4 files changed, 41 insertions, 1 deletions
diff --git a/slirp/ip6.h b/slirp/ip6.h
index 731ee72d77..8ddfa242c4 100644
--- a/slirp/ip6.h
+++ b/slirp/ip6.h
@@ -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))
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 50b36f4126..7a47bb60a9 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -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),
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 2850ef1665..71f2439461 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -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];
diff --git a/slirp/socket.c b/slirp/socket.c
index 8df9252544..b836c42b8e 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -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;
}