diff --git a/src/client.c b/src/client.c
index 43adde6..72f8ca8 100644
--- a/src/client.c
+++ b/src/client.c
@@ -158,7 +158,7 @@ client_get_conn()
 }
 
 void
-client_set_nameserver(const char *cp, int port) 
+client_set_nameserver(const char *cp, int port)
 {
 #ifdef ANDROID
 	struct addrinfo hints, *result, *p;
@@ -1687,6 +1687,9 @@ handshake_raw_udp(int dns_fd, int seed)
 	int len;
 	unsigned remoteaddr = 0;
 	struct in_addr server;
+#ifdef LINUX
+	struct in6_addr server6;
+#endif
 
 	fprintf(stderr, "Testing raw UDP data to the server (skip with -r)");
 	for (i=0; running && i<3 ;i++) {
@@ -1708,6 +1711,15 @@ handshake_raw_udp(int dns_fd, int seed)
 				server.s_addr = ntohl(remoteaddr);
 				break;
 			}
+#ifdef LINUX
+			if (len == 17 && in[0] == 'I') {
+				/* Received IP address */
+				int i;
+				for (i = 0; i < sizeof(struct in6_addr); ++i)
+					server6.__in6_u.__u6_addr8[i] = in[i + 1];
+				break;
+			}
+#endif
 		/*XXX END adjust indent 1 tab back*/
 
 		fprintf(stderr, ".");
@@ -1732,7 +1744,10 @@ handshake_raw_udp(int dns_fd, int seed)
 
 	raw_serv6.sin6_family = AF_INET6;
 	raw_serv6.sin6_port = htons(53);
-	inet_pton(AF_INET6, "2001:470:0:473::473", &(raw_serv6.sin6_addr));
+	raw_serv6.sin6_addr = server6;
+	//	inet_pton(AF_INET6, "2001:470:0:473::473", &(raw_serv6.sin6_addr));
+
+	ipv6_print(&server6, 00);
 
 	/* do login against port 53 on remote server 
 	 * based on the old seed. If reply received,
diff --git a/src/common.h b/src/common.h
index 5bc10fd..71b4948 100644
--- a/src/common.h
+++ b/src/common.h
@@ -94,11 +94,10 @@ struct query {
 	unsigned short type;
 	unsigned short rcode;
 	unsigned short id;
-//	union {
-//		struct in_addr v4;
-//		struct in6_addr v6;
-//	} destination;
-	struct in_addr destination;
+	union {
+		struct in_addr v4;
+		struct in6_addr v6;
+	} destination;
 	union {
 		struct sockaddr v4;
 		struct sockaddr_in6 v6;
diff --git a/src/iodined.c b/src/iodined.c
index 40ad2e8..070bf8f 100644
--- a/src/iodined.c
+++ b/src/iodined.c
@@ -873,31 +873,61 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
 		return;
 	} else if(in[0] == 'I' || in[0] == 'i') {
 		/* Request for IP number */
-		in_addr_t replyaddr;
-		unsigned addr;
-		char reply[5];
+		int i;
 
-		userid = b32_8to5(in[1]);
-		if (check_user_and_ip(userid, q) != 0) {
-			write_dns(dns_fd, q, "BADIP", 5, 'T');
-			return; /* illegal id */
-		}
+#ifdef LINUX
+		if (v6_listen) {
+			struct in6_addr replyaddr;
+			char reply[sizeof(struct in6_addr) + 1];
 
-		if (ns_ip != INADDR_ANY) {
-			/* If set, use assigned external ip (-n option) */
-			replyaddr = ns_ip;
+			userid = b32_8to5(in[1]);
+			if (check_user_and_ip(userid, q) != 0) {
+				write_dns(dns_fd, q, "BADIP", 5, 'T');
+				return; /* illegal id */
+			}
+
+			if (memcmp(&ns_ip6, &in6addr_any, sizeof(struct in6_addr))) {
+				/* If set, use assigned external ip (-n option) */
+				memcpy(&replyaddr, &ns_ip6, sizeof(struct in6_addr));
+			} else {
+				/* otherwise return destination ip from packet */
+				memcpy(&replyaddr, &q->destination.v6, sizeof(struct in6_addr));
+			}
+
+			reply[0] = 'I';
+			for(i = 0; i < sizeof(struct in6_addr); i++)
+				reply[i + 1] = replyaddr.__in6_u.__u6_addr8[i];
+			write_dns(dns_fd, q, reply, sizeof(reply), 'T');
 		} else {
-			/* otherwise return destination ip from packet */
-			memcpy(&replyaddr, &q->destination.s_addr, sizeof(in_addr_t));
-		}
+#endif
+			in_addr_t replyaddr;
+			unsigned addr;
+			char reply[5];
 
-		addr = htonl(replyaddr);
-		reply[0] = 'I';
-		reply[1] = (addr >> 24) & 0xFF;
-		reply[2] = (addr >> 16) & 0xFF;
-		reply[3] = (addr >>  8) & 0xFF;
-		reply[4] = (addr >>  0) & 0xFF;
-		write_dns(dns_fd, q, reply, sizeof(reply), 'T');
+			userid = b32_8to5(in[1]);
+			if (check_user_and_ip(userid, q) != 0) {
+				write_dns(dns_fd, q, "BADIP", 5, 'T');
+				return; /* illegal id */
+			}
+
+			if (ns_ip != INADDR_ANY) {
+				/* If set, use assigned external ip (-n option) */
+				replyaddr = ns_ip;
+			} else {
+				/* otherwise return destination ip from packet */
+				memcpy(&replyaddr, &q->destination.v4.s_addr, sizeof(in_addr_t));
+			}
+
+			addr = htonl(replyaddr);
+			reply[0] = 'I';
+			reply[1] = (addr >> 24) & 0xFF;
+			reply[2] = (addr >> 16) & 0xFF;
+			reply[3] = (addr >> 8) & 0xFF;
+			reply[4] = (addr >> 0) & 0xFF;
+			write_dns(dns_fd, q, reply, sizeof(reply), 'T');
+#ifdef LINUX
+		}
+#endif
 	} else if(in[0] == 'Z' || in[0] == 'z') {
 		/* Check for case conservation and chars not allowed according to RFC */
 
@@ -1492,10 +1522,16 @@ handle_ns_request(int dns_fd, struct query *q)
 	char buf[64*1024];
 	int len;
 
+#ifdef LINUX
+	if (v6_listen) {
+		if(memcmp(&ns_ip6, &in6addr_any, sizeof(struct in6_addr)))
+			memcpy(&q->destination.v6, &ns_ip6, sizeof(struct in6_addr));
+	} else
+#endif
 	if (ns_ip != INADDR_ANY) {
 		/* If ns_ip set, overwrite destination addr with it.
 		 * Destination addr will be sent as additional record (A, IN) */
-		memcpy(&q->destination.s_addr, &ns_ip, sizeof(in_addr_t));
+		memcpy(&q->destination.v4.s_addr, &ns_ip, sizeof(in_addr_t));
 	}
 
 	len = dns_encode_ns_response(buf, sizeof(buf), q, topdomain);
@@ -1522,15 +1558,30 @@ handle_a_request(int dns_fd, struct query *q, int fakeip)
 	char buf[64*1024];
 	int len;
 
-	if (fakeip) {
-		in_addr_t ip = inet_addr("127.0.0.1");
-		memcpy(&q->destination.s_addr, &ip, sizeof(in_addr_t));
-
-	} else if (ns_ip != INADDR_ANY) {
-		/* If ns_ip set, overwrite destination addr with it.
-		 * Destination addr will be sent as additional record (A, IN) */
-		memcpy(&q->destination.s_addr, &ns_ip, sizeof(in_addr_t));
+#ifdef LINUX
+	if (v6_listen) {
+		if (fakeip)
+			memcpy(&q->destination.v6, &in6addr_loopback, sizeof(in_addr_t));
+		else if (memcmp(&ns_ip6, &in6addr_any, sizeof(struct in6_addr))) {
+			/* If ns_ip set, overwrite destination addr with it.
+			 * Destination addr will be sent as additional record (A, IN) */
+			memcpy(&q->destination.v4.s_addr, &ns_ip6, sizeof(struct in6_addr));
+		}
 	}
+#endif
+	else {
+		if (fakeip) {
+			in_addr_t ip = inet_addr("127.0.0.1");
+			memcpy(&q->destination.v4.s_addr, &ip, sizeof(in_addr_t));
+		} else if (ns_ip != INADDR_ANY) {
+			/* If ns_ip set, overwrite destination addr with it.
+			 * Destination addr will be sent as additional record (A, IN) */
+			memcpy(&q->destination.v4.s_addr, &ns_ip, sizeof(in_addr_t));
+		}
+#ifdef LINUX
+	}
+#endif
+
 
 	len = dns_encode_a_response(buf, sizeof(buf), q);
 	if (len < 1) {
@@ -2051,7 +2102,14 @@ read_dns(int fd, int tun_fd, struct query *q) /* FIXME: tun_fd is because of raw
 			if (cmsg->cmsg_level == IPPROTO_IP &&
 				cmsg->cmsg_type == DSTADDR_SOCKOPT) {
 
-				q->destination = *dstaddr(cmsg);
+				q->destination.v4 = *dstaddr(cmsg);
+				break;//	printf("write_dns()\n");
+				//	ipv6_print(&q->from.v6, 44);
+			}
+			if (cmsg->cmsg_level == IPPROTO_IPV6 &&
+				cmsg->cmsg_type == DSTADDR_SOCKOPT) {
+
+				memcpy(&q->destination.v6, dstaddr(cmsg), sizeof(struct in6_addr));
 				break;//	printf("write_dns()\n");
 				//	ipv6_print(&q->from.v6, 44);
 			}