diff options
author | Henryk Plötz <henryk@ploetzli.ch> | 2014-10-03 20:04:14 +0200 |
---|---|---|
committer | Henryk Plötz <henryk@ploetzli.ch> | 2014-10-03 20:04:14 +0200 |
commit | c44d8b51ffb5a413f8bbdbd9991bbc573853e397 (patch) | |
tree | e7f2e644de620879f610c909c405cbc4e44d6062 /query.c | |
parent | 0e5b2871ca6456b01d4bf037a6e68badf1ff1a41 (diff) | |
download | tinydnssec-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.c | 287 |
1 files changed, 261 insertions, 26 deletions
@@ -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); } |