From c9d3965a64bfe74fe25b5a5168bb299936c77f56 Mon Sep 17 00:00:00 2001 From: Julian Kranz Date: Fri, 27 Jan 2012 18:40:48 +0100 Subject: [PATCH] --- --- src/client.c | 19 +++++++- src/common.h | 9 ++-- src/iodined.c | 120 +++++++++++++++++++++++++++++++++++++------------- 3 files changed, 110 insertions(+), 38 deletions(-) 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); }