From 2e6a5876d6793a51582f8b6a1416272d73191fcb Mon Sep 17 00:00:00 2001 From: Masaq- Date: Mon, 7 Nov 2016 11:47:20 +0000 Subject: [PATCH 1/2] add support for more query types: A6 AAAA DNAME PTR --- src/android_dns.h | 4 ++++ src/client.c | 33 +++++++++++++++++++++++++-------- src/dns.c | 22 +++++++++++++++++++--- src/iodine.c | 3 ++- src/server.c | 11 +++++++++-- src/windows.h | 4 ++++ 6 files changed, 63 insertions(+), 14 deletions(-) diff --git a/src/android_dns.h b/src/android_dns.h index 5a86e71..9252738 100644 --- a/src/android_dns.h +++ b/src/android_dns.h @@ -50,9 +50,13 @@ typedef struct { #define T_A 1 #define T_CNAME 5 #define T_NULL 10 +#define T_PTR 12 #define T_MX 15 #define T_TXT 16 +#define T_AAAA 28 #define T_SRV 33 +#define T_A6 38 +#define T_DNAME 39 #endif /* !C_IN */ diff --git a/src/client.c b/src/client.c index 4ca5f7d..322d8fd 100644 --- a/src/client.c +++ b/src/client.c @@ -78,6 +78,14 @@ client_set_qtype(char *qtype) this.do_qtype = T_SRV; else if (!strcasecmp(qtype, "TXT")) this.do_qtype = T_TXT; + else if (!strcasecmp(qtype, "PTR")) + this.do_qtype = T_PTR; + else if (!strcasecmp(qtype, "AAAA")) + this.do_qtype = T_AAAA; + else if (!strcasecmp(qtype, "A6")) + this.do_qtype = T_A6; + else if (!strcasecmp(qtype, "DNAME")) + this.do_qtype = T_DNAME; return (this.do_qtype == T_UNSET); } @@ -93,6 +101,10 @@ client_get_qtype() else if (this.do_qtype == T_MX) c = "MX"; else if (this.do_qtype == T_SRV) c = "SRV"; else if (this.do_qtype == T_TXT) c = "TXT"; + else if (this.do_qtype == T_PTR) c = "PTR"; + else if (this.do_qtype == T_AAAA) c = "AAAA"; + else if (this.do_qtype == T_A6) c = "A6"; + else if (this.do_qtype == T_DNAME) c = "DNAME"; return c; } @@ -724,7 +736,8 @@ read_dns_withq(uint8_t *buf, size_t buflen, struct query *q) if (rv <= 0) return rv; - if (q->type == T_CNAME || q->type == T_TXT) + if (q->type == T_CNAME || q->type == T_TXT || + q->type == T_PTR || q->type == T_A6 || q->type == T_DNAME) /* CNAME can also be returned from an A question */ { /* @@ -2113,13 +2126,17 @@ static int handshake_qtype_numcvt(int num) { switch (num) { - case 0: return T_NULL; - case 1: return T_PRIVATE; - case 2: return T_TXT; - case 3: return T_SRV; - case 4: return T_MX; - case 5: return T_CNAME; - case 6: return T_A; + case 0: return T_NULL; + case 1: return T_PRIVATE; + case 2: return T_TXT; + case 3: return T_SRV; + case 4: return T_MX; + case 5: return T_DNAME; + case 6: return T_PTR; + case 7: return T_CNAME; + case 8: return T_A6; + case 9: return T_AAAA; + case 10: return T_A; } return T_UNSET; } diff --git a/src/dns.c b/src/dns.c index e6a807e..b7fa269 100644 --- a/src/dns.c +++ b/src/dns.c @@ -90,7 +90,9 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_ /* Answer section */ - if (q->type == T_CNAME || q->type == T_A) { + if (q->type == T_CNAME || q->type == T_A || + q->type == T_PTR || q->type == T_AAAA || + q->type == T_A6 || q->type == T_DNAME) { /* data is expected to be like "Hblabla.host.name.com\0" */ char *startp; @@ -98,7 +100,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_ CHECKLEN(10); putshort(&p, name); - if (q->type == T_A) + if (q->type == T_A || q->type == T_AAAA) /* answer CNAME to A question */ putshort(&p, T_CNAME); else @@ -108,6 +110,10 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_ startp = p; p += 2; /* skip 2 bytes length */ + if (q->type == T_A6) { + CHECKLEN(1); + putbyte(&p, 128); + } putname(&p, buflen - (p - buf), data); CHECKLEN(0); namelen = p - startp; @@ -483,7 +489,9 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz rv = 0; } } - else if ((type == T_A || type == T_CNAME) && buf) { + else if ((type == T_A || type == T_CNAME || + type == T_PTR || type == T_AAAA || + type == T_A6 || type == T_DNAME) && buf) { /* Assume that first answer is what we wanted */ readname(packet, packetlen, &data, name, sizeof(name)); CHECKLEN(10); @@ -492,6 +500,14 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz readlong(packet, &data, &ttl); readshort(packet, &data, &rlen); + if (type == T_A6) { + unsigned char prefix; + CHECKLEN(1); + readdata(packet, &data, (char *) &prefix, 1); + if (prefix != 128) { + return 0; + } + } memset(name, 0, sizeof(name)); readname(packet, packetlen, &data, name, sizeof(name) - 1); name[sizeof(name)-1] = '\0'; diff --git a/src/iodine.c b/src/iodine.c index 3b79c9c..31a3224 100644 --- a/src/iodine.c +++ b/src/iodine.c @@ -246,7 +246,8 @@ help() fprintf(stderr, "iodine IP over DNS tunneling client\n"); print_usage(); fprintf(stderr, "\nOptions to try if connection doesn't work:\n"); - fprintf(stderr, " -T use DNS type: NULL, PRIVATE, TXT, SRV, MX, CNAME, A (default: autodetect)\n"); + fprintf(stderr, " -T use DNS type: NULL, PRIVATE, TXT, SRV, MX,\n"); + fprintf(stderr, " DNAME, PTR, CNAME, A6, AAAA, A (default: autodetect)\n"); fprintf(stderr, " -O use specific downstream encoding for queries: Base32, Base64, Base64u,\n"); fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n"); fprintf(stderr, " -I target interval between sending and receiving requests (default: 4 secs)\n"); diff --git a/src/server.c b/src/server.c index 5c4bc88..e8e5a3d 100644 --- a/src/server.c +++ b/src/server.c @@ -738,6 +738,10 @@ tunnel_dns(int dns_fd) case T_MX: case T_SRV: case T_TXT: + case T_PTR: + case T_AAAA: + case T_A6: + case T_DNAME: /* encoding is "transparent" here */ handle_null_request(dns_fd, &q, domain_len); break; @@ -1142,7 +1146,8 @@ write_dns(int fd, struct query *q, char *data, size_t datalen, char downenc) char buf[64*1024]; int len = 0; - if (q->type == T_CNAME || q->type == T_A) { + if (q->type == T_CNAME || q->type == T_A || + q->type == T_PTR || q->type == T_AAAA || q->type == T_A6 || q->type == T_DNAME) { char cnamebuf[1024]; /* max 255 */ write_dns_nameenc((uint8_t *)cnamebuf, sizeof(cnamebuf), (uint8_t *)data, datalen, downenc); @@ -1319,7 +1324,9 @@ handle_dns_downstream_codec_check(int dns_fd, struct query *q, uint8_t *domain, case 'V': if (q->type == T_TXT || q->type == T_SRV || q->type == T_MX || - q->type == T_CNAME || q->type == T_A) { + q->type == T_CNAME || q->type == T_A || + q->type == T_PTR || q->type == T_AAAA || + q->type == T_A6 || q->type == T_DNAME) { write_dns(dns_fd, q, datap, datalen, codec); return; } diff --git a/src/windows.h b/src/windows.h index 909e5f6..ae4446c 100644 --- a/src/windows.h +++ b/src/windows.h @@ -43,6 +43,10 @@ typedef unsigned int in_addr_t; #define T_MX DNS_TYPE_MX #define T_TXT DNS_TYPE_TXT #define T_SRV DNS_TYPE_SRV +#define T_PTR DNS_TYPE_PTR +#define T_AAAA DNS_TYPE_AAAA +#define T_A6 DNS_TYPE_A6 +#define T_DNAME DNS_TYPE_DNAME #define C_IN 1 From 458117c14cab7c8d12eca14396bf547516d42778 Mon Sep 17 00:00:00 2001 From: frekky Date: Fri, 9 Dec 2016 09:27:08 +0800 Subject: [PATCH 2/2] fixed write warning --- src/client.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/client.c b/src/client.c index 322d8fd..698eea2 100644 --- a/src/client.c +++ b/src/client.c @@ -1189,10 +1189,13 @@ tunnel_dns() } if (datalen) { - if (this.use_remote_forward) - write(STDOUT_FILENO, data, datalen); - else + if (this.use_remote_forward) { + if (write(STDOUT_FILENO, data, datalen) != datalen) { + warn("write_stdout != datalen"); + } + } else { write_tun(this.tun_fd, data, datalen); + } } }