aboutsummaryrefslogtreecommitdiff
path: root/query.c
diff options
context:
space:
mode:
authorHenryk Plötz <henryk@ploetzli.ch>2014-10-03 20:04:14 +0200
committerHenryk Plötz <henryk@ploetzli.ch>2014-10-03 20:04:14 +0200
commitc44d8b51ffb5a413f8bbdbd9991bbc573853e397 (patch)
treee7f2e644de620879f610c909c405cbc4e44d6062 /query.c
parent0e5b2871ca6456b01d4bf037a6e68badf1ff1a41 (diff)
downloadtinydnssec-c44d8b51ffb5a413f8bbdbd9991bbc573853e397.tar.gz
tinydnssec-c44d8b51ffb5a413f8bbdbd9991bbc573853e397.tar.bz2
Apply patch djbdns-1.05-test27.diff.bz2
Source was http://www.fefe.de/dns/djbdns-1.05-test27.diff.bz2, SHA1 f0380ec1866f49c0bcf6369a923ac0a4a5095da8
Diffstat (limited to 'query.c')
-rw-r--r--query.c287
1 files changed, 261 insertions, 26 deletions
diff --git a/query.c b/query.c
index 46cdc00..d61b20c 100644
--- a/query.c
+++ b/query.c
@@ -12,6 +12,9 @@
#include "alloc.h"
#include "response.h"
#include "query.h"
+#include "ip6.h"
+
+extern stralloc ignoreip;
static int flagforwardonly = 0;
@@ -110,7 +113,7 @@ static int rqa(struct query *z)
return 1;
}
-static int globalip(char *d,char ip[4])
+static int globalip(char *d,char ip[16])
{
if (dns_domain_equal(d,"\011localhost\0")) {
byte_copy(ip,4,"\177\0\0\1");
@@ -165,7 +168,7 @@ static int doit(struct query *z,int state)
char *buf;
unsigned int len;
const char *whichserver;
- char header[12];
+ char header[24];
char misc[20];
unsigned int rcode;
unsigned int posanswers;
@@ -193,6 +196,7 @@ static int doit(struct query *z,int state)
int k;
int p;
int q;
+ unsigned int ii;
errno = error_io;
if (state == 1) goto HAVEPACKET;
@@ -205,14 +209,15 @@ static int doit(struct query *z,int state)
NEWNAME:
if (++z->loop == 100) goto DIE;
d = z->name[z->level];
- dtype = z->level ? DNS_T_A : z->type;
+ dtype = z->level ? (z->ipv6[z->level] ? DNS_T_AAAA : DNS_T_A) : z->type;
dlen = dns_domain_length(d);
if (globalip(d,misc)) {
if (z->level) {
- for (k = 0;k < 64;k += 4)
- if (byte_equal(z->servers[z->level - 1] + k,4,"\0\0\0\0")) {
- byte_copy(z->servers[z->level - 1] + k,4,misc);
+ for (k = 0;k < 256;k += 16)
+ if (byte_equal(z->servers[z->level - 1] + k,16,V6any)) {
+ byte_copy(z->servers[z->level - 1] + k,12,V4mappedprefix);
+ byte_copy(z->servers[z->level - 1] + k + 12,4,misc);
break;
}
goto LOWERLEVEL;
@@ -227,6 +232,158 @@ static int doit(struct query *z,int state)
return 1;
}
+ if (dns_domain_equal(d,"\0011\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\003ip6\003int\0")) {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_PTR,dtype)) {
+ if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
+ if (!response_addname("\016ipv6-localhost\0")) goto DIE;
+ if (!response_addname("\015ipv6-loopback\0")) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\001e\001f\003ip6\003int\0")) {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_PTR,dtype)) {
+ if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
+ if (!response_addname("\015ipv6-localnet\0")) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\001f\001f\003ip6\003int\0")) {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_PTR,dtype)) {
+ if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
+ if (!response_addname("\020ipv6-mcastprefix\0")) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\0011\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0012\0010\001f\001f\003ip6\003int\0")) {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_PTR,dtype)) {
+ if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
+ if (!response_addname("\015ipv6-allnodes\0")) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\0012\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0012\0010\001f\001f\003ip6\003int\0")) {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_PTR,dtype)) {
+ if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
+ if (!response_addname("\017ipv6-allrouters\0")) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\0011\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0012\0010\001f\001f\003ip6\003int\0")) {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_PTR,dtype)) {
+ if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
+ if (!response_addname("\015ipv6-allhosts\0")) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\016ipv6-localhost\0") ||
+ dns_domain_equal(d,"\015ipv6-loopback\0"))
+ {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_AAAA,dtype)) {
+ if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE;
+ if (!response_addbytes("\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001",16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\015ipv6-localnet\0"))
+ {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_AAAA,dtype)) {
+ if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE;
+ if (!response_addbytes("\376\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\020ipv6-mcastprefix\0"))
+ {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_AAAA,dtype)) {
+ if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE;
+ if (!response_addbytes("\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\15ipv6-allnodes\0"))
+ {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_AAAA,dtype)) {
+ if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE;
+ if (!response_addbytes("\377\002\000\000\000\000\000\000\000\000\000\000\000\000\000\001",16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\17ipv6-allrouters\0"))
+ {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_AAAA,dtype)) {
+ if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE;
+ if (!response_addbytes("\377\002\000\000\000\000\000\000\000\000\000\000\000\000\000\002",16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\15ipv6-allhosts\0"))
+ {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_AAAA,dtype)) {
+ if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE;
+ if (!response_addbytes("\377\002\000\000\000\000\000\000\000\000\000\000\000\000\000\003",16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
if (dns_domain_equal(d,"\0011\0010\0010\003127\7in-addr\4arpa\0")) {
if (z->level) goto LOWERLEVEL;
if (!rqa(z)) goto DIE;
@@ -322,13 +479,18 @@ static int doit(struct query *z,int state)
if (typematch(DNS_T_A,dtype)) {
byte_copy(key,2,DNS_T_A);
cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
+ if (cached && !cachedlen && z->level) { /* if we were looking the A record up to find an NS, try IPv6 too */
+ z->ipv6[z->level]=1;
+ goto NEWNAME;
+ }
if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
if (z->level) {
log_cachedanswer(d,DNS_T_A);
while (cachedlen >= 4) {
- for (k = 0;k < 64;k += 4)
- if (byte_equal(z->servers[z->level - 1] + k,4,"\0\0\0\0")) {
- byte_copy(z->servers[z->level - 1] + k,4,cached);
+ for (k = 0;k < 256;k += 16)
+ if (byte_equal(z->servers[z->level - 1] + k,16,V6any)) {
+ byte_copy(z->servers[z->level - 1] + k,12,V4mappedprefix);
+ byte_copy(z->servers[z->level - 1] + k + 12,4,cached);
break;
}
cached += 4;
@@ -351,7 +513,39 @@ static int doit(struct query *z,int state)
}
}
- if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_CNAME,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype)) {
+ if (typematch(DNS_T_AAAA,dtype)) {
+ byte_copy(key,2,DNS_T_AAAA);
+ cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
+ if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
+ if (z->level) {
+ log_cachedanswer(d,DNS_T_AAAA);
+ while (cachedlen >= 16) {
+ for (k = 0;k < 256;k += 16)
+ if (byte_equal(z->servers[z->level - 1] + k,16,V6any)) {
+ byte_copy(z->servers[z->level - 1] + k,16,cached);
+ break;
+ }
+ cached += 16;
+ cachedlen -= 16;
+ }
+ goto LOWERLEVEL;
+ }
+
+ log_cachedanswer(d,DNS_T_AAAA);
+ if (!rqa(z)) goto DIE;
+ while (cachedlen >= 16) {
+ if (!response_rstart(d,DNS_T_AAAA,ttl)) goto DIE;
+ if (!response_addbytes(cached,16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ cached += 16;
+ cachedlen -= 16;
+ }
+ cleanup(z);
+ return 1;
+ }
+ }
+
+ if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_CNAME,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype) && !typematch(DNS_T_AAAA,dtype)) {
byte_copy(key,2,dtype);
cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
@@ -390,7 +584,7 @@ static int doit(struct query *z,int state)
cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
if (cached && cachedlen) {
z->control[z->level] = d;
- byte_zero(z->servers[z->level],64);
+ byte_zero(z->servers[z->level],256);
for (j = 0;j < QUERY_MAXNS;++j)
dns_domain_free(&z->ns[z->level][j]);
pos = 0;
@@ -418,20 +612,22 @@ static int doit(struct query *z,int state)
if (!dns_domain_copy(&z->name[z->level + 1],z->ns[z->level][j])) goto DIE;
dns_domain_free(&z->ns[z->level][j]);
++z->level;
+ z->ipv6[z->level]=0;
goto NEWNAME;
}
dns_domain_free(&z->ns[z->level][j]);
}
- for (j = 0;j < 64;j += 4)
- if (byte_diff(z->servers[z->level] + j,4,"\0\0\0\0"))
+ for (j = 0;j < 256;j += 16)
+ if (byte_diff(z->servers[z->level] + j,16,V6any))
break;
- if (j == 64) goto SERVFAIL;
+ if (j == 256) goto SERVFAIL;
- dns_sortip(z->servers[z->level],64);
+ dns_sortip6(z->servers[z->level],256);
if (z->level) {
- log_tx(z->name[z->level],DNS_T_A,z->control[z->level],z->servers[z->level],z->level);
- if (dns_transmit_start(&z->dt,z->servers[z->level],flagforwardonly,z->name[z->level],DNS_T_A,z->localip) == -1) goto DIE;
+ dtype = z->ipv6[z->level] ? DNS_T_AAAA : DNS_T_A;
+ log_tx(z->name[z->level],dtype,z->control[z->level],z->servers[z->level],z->level);
+ if (dns_transmit_start(&z->dt,z->servers[z->level],flagforwardonly,z->name[z->level],dtype,z->localip) == -1) goto DIE;
}
else {
log_tx(z->name[0],z->type,z->control[0],z->servers[0],0);
@@ -453,10 +649,11 @@ static int doit(struct query *z,int state)
buf = z->dt.packet;
len = z->dt.packetlen;
- whichserver = z->dt.servers + 4 * z->dt.curserver;
+ whichserver = z->dt.servers + 16 * z->dt.curserver;
control = z->control[z->level];
d = z->name[z->level];
- dtype = z->level ? DNS_T_A : z->type;
+/* dtype = z->level ? DNS_T_A : z->type; */
+ dtype = z->level ? (z->ipv6[z->level] ? DNS_T_AAAA : DNS_T_A) : z->type;
pos = dns_packet_copy(buf,len,0,header,12); if (!pos) goto DIE;
pos = dns_packet_skipname(buf,len,pos); if (!pos) goto DIE;
@@ -519,7 +716,7 @@ static int doit(struct query *z,int state)
if (!flagcname && !rcode && !flagout && flagreferral && !flagsoa)
if (dns_domain_equal(referral,control) || !dns_domain_suffix(referral,control)) {
log_lame(whichserver,control,referral);
- byte_zero(whichserver,4);
+ byte_zero(whichserver,16);
goto HAVENS;
}
@@ -643,6 +840,11 @@ static int doit(struct query *z,int state)
pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
if (byte_equal(header + 8,2,"\0\4")) {
pos = dns_packet_copy(buf,len,pos,header,4); if (!pos) goto DIE;
+ if (ignoreip.len)
+ for(ii = 0; ii < ignoreip.len; ii+= 16) {
+ if (byte_equal(ignoreip.s+ii,12,V4mappedprefix) &&
+ byte_equal(header,4,ignoreip.s+ii+12)) goto NXDOMAIN;
+ }
save_data(header,4);
log_rr(whichserver,t1,DNS_T_A,header,4,ttl);
}
@@ -650,6 +852,23 @@ static int doit(struct query *z,int state)
}
save_finish(DNS_T_A,t1,ttl);
}
+ else if (byte_equal(type,2,DNS_T_AAAA)) {
+ save_start();
+ while (i < j) {
+ pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
+ pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
+ if (byte_equal(header + 8,2,"\0\20")) {
+ pos = dns_packet_copy(buf,len,pos,header,16); if (!pos) goto DIE;
+ if (ignoreip.len)
+ for(ii = 0; ii < ignoreip.len; ii+= 16)
+ if (byte_equal(header,16,ignoreip.s+ii)) goto NXDOMAIN;
+ save_data(header,16);
+ log_rr(whichserver,t1,DNS_T_AAAA,header,16,ttl);
+ }
+ ++i;
+ }
+ save_finish(DNS_T_AAAA,t1,ttl);
+ }
else {
save_start();
while (i < j) {
@@ -707,6 +926,11 @@ static int doit(struct query *z,int state)
save_start();
save_finish(dtype,d,soattl);
log_nodata(whichserver,d,dtype,soattl);
+ if (z->level && !byte_diff(DNS_T_A,2,dtype)) {
+ d = z->name[z->level];
+ z->ipv6[z->level] = 1;
+ goto NEWNAME; /* retry, will ask for AAAA next */
+ }
}
log_stats();
@@ -723,9 +947,18 @@ static int doit(struct query *z,int state)
if (typematch(header,DNS_T_A))
if (byte_equal(header + 2,2,DNS_C_IN)) /* should always be true */
if (datalen == 4)
- for (k = 0;k < 64;k += 4)
- if (byte_equal(z->servers[z->level - 1] + k,4,"\0\0\0\0")) {
- if (!dns_packet_copy(buf,len,pos,z->servers[z->level - 1] + k,4)) goto DIE;
+ for (k = 0;k < 256;k += 16)
+ if (byte_equal(z->servers[z->level - 1] + k,16,V6any)) {
+ byte_copy(z->servers[z->level - 1] + k,12,V4mappedprefix);
+ if (!dns_packet_copy(buf,len,pos,z->servers[z->level - 1] + k + 12,4)) goto DIE;
+ break;
+ }
+ if (typematch(header,DNS_T_AAAA))
+ if (byte_equal(header + 2,2,DNS_C_IN)) /* should always be true */
+ if (datalen == 16)
+ for (k = 0;k < 256;k += 16)
+ if (byte_equal(z->servers[z->level - 1] + k,16,V6any)) {
+ if (!dns_packet_copy(buf,len,pos,z->servers[z->level - 1] + k,16)) goto DIE;
break;
}
pos += datalen;
@@ -783,7 +1016,7 @@ static int doit(struct query *z,int state)
if (!dns_domain_suffix(d,referral)) goto DIE;
control = d + dns_domain_suffixpos(d,referral);
z->control[z->level] = control;
- byte_zero(z->servers[z->level],64);
+ byte_zero(z->servers[z->level],256);
for (j = 0;j < QUERY_MAXNS;++j)
dns_domain_free(&z->ns[z->level][j]);
k = 0;
@@ -818,7 +1051,7 @@ static int doit(struct query *z,int state)
return -1;
}
-int query_start(struct query *z,char *dn,char type[2],char class[2],char localip[4])
+int query_start(struct query *z,char *dn,char type[2],char class[2],char localip[16],unsigned int scope_id)
{
if (byte_equal(type,2,DNS_T_AXFR)) { errno = error_perm; return -1; }
@@ -829,7 +1062,9 @@ int query_start(struct query *z,char *dn,char type[2],char class[2],char localip
if (!dns_domain_copy(&z->name[0],dn)) return -1;
byte_copy(z->type,2,type);
byte_copy(z->class,2,class);
- byte_copy(z->localip,4,localip);
+ byte_copy(z->localip,16,localip);
+ z->scope_id=scope_id;
+ z->ipv6[0]=0;
return doit(z,0);
}