@@ -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))
@@ -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),
@@ -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];
@@ -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;
}