Lines 91-96
Link Here
|
91 |
} |
91 |
} |
92 |
} |
92 |
} |
93 |
|
93 |
|
|
|
94 |
static int move_name_to_alias(struct query *z,uint32 ttl) |
95 |
{ |
96 |
int j ; |
97 |
|
98 |
if (z->alias[QUERY_MAXALIAS - 1]) return 0 ; |
99 |
for (j = QUERY_MAXALIAS - 1;j > 0;--j) |
100 |
z->alias[j] = z->alias[j - 1]; |
101 |
for (j = QUERY_MAXALIAS - 1;j > 0;--j) |
102 |
z->aliasttl[j] = z->aliasttl[j - 1]; |
103 |
z->alias[0] = z->name[0]; |
104 |
z->aliasttl[0] = ttl; |
105 |
z->name[0] = 0; |
106 |
return 1 ; |
107 |
} |
108 |
|
94 |
static int rqa(struct query *z) |
109 |
static int rqa(struct query *z) |
95 |
{ |
110 |
{ |
96 |
int i; |
111 |
int i; |
Lines 123-129
Link Here
|
123 |
static char *t1 = 0; |
138 |
static char *t1 = 0; |
124 |
static char *t2 = 0; |
139 |
static char *t2 = 0; |
125 |
static char *t3 = 0; |
140 |
static char *t3 = 0; |
126 |
static char *cname = 0; |
|
|
127 |
static char *referral = 0; |
141 |
static char *referral = 0; |
128 |
static unsigned int *records = 0; |
142 |
static unsigned int *records = 0; |
129 |
|
143 |
|
Lines 179-193
Link Here
|
179 |
uint16 datalen; |
193 |
uint16 datalen; |
180 |
char *control; |
194 |
char *control; |
181 |
char *d; |
195 |
char *d; |
|
|
196 |
char *owner_name = 0 ; |
182 |
const char *dtype; |
197 |
const char *dtype; |
183 |
unsigned int dlen; |
198 |
unsigned int dlen; |
184 |
int flagout; |
199 |
int flagout; |
185 |
int flagcname; |
|
|
186 |
int flagreferral; |
200 |
int flagreferral; |
187 |
int flagsoa; |
201 |
int flagsoa; |
188 |
uint32 ttl; |
202 |
uint32 ttl; |
189 |
uint32 soattl; |
203 |
uint32 soattl; |
190 |
uint32 cnamettl; |
|
|
191 |
int i; |
204 |
int i; |
192 |
int j; |
205 |
int j; |
193 |
int k; |
206 |
int k; |
Lines 252-258
Link Here
|
252 |
|
265 |
|
253 |
byte_copy(key,2,DNS_T_CNAME); |
266 |
byte_copy(key,2,DNS_T_CNAME); |
254 |
cached = cache_get(key,dlen + 2,&cachedlen,&ttl); |
267 |
cached = cache_get(key,dlen + 2,&cachedlen,&ttl); |
255 |
if (cached) { |
268 |
/* A previous explicit query might have caused an empty RRSet to have been |
|
|
269 |
** cached. Take care to ignore such a thing. |
270 |
*/ |
271 |
if (cached && cachedlen) { |
256 |
if (typematch(DNS_T_CNAME,dtype)) { |
272 |
if (typematch(DNS_T_CNAME,dtype)) { |
257 |
log_cachedanswer(d,DNS_T_CNAME); |
273 |
log_cachedanswer(d,DNS_T_CNAME); |
258 |
if (!rqa(z)) goto DIE; |
274 |
if (!rqa(z)) goto DIE; |
Lines 261-268
Link Here
|
261 |
return 1; |
277 |
return 1; |
262 |
} |
278 |
} |
263 |
log_cachedcname(d,cached); |
279 |
log_cachedcname(d,cached); |
264 |
if (!dns_domain_copy(&cname,cached)) goto DIE; |
280 |
if (!z->level) { |
265 |
goto CNAME; |
281 |
if (!move_name_to_alias(z,ttl)) goto DIE ; |
|
|
282 |
} |
283 |
if (!dns_domain_copy(&z->name[z->level],cached)) goto DIE; |
284 |
goto NEWNAME; |
266 |
} |
285 |
} |
267 |
|
286 |
|
268 |
if (typematch(DNS_T_NS,dtype)) { |
287 |
if (typematch(DNS_T_NS,dtype)) { |
Lines 351-357
Link Here
|
351 |
} |
370 |
} |
352 |
} |
371 |
} |
353 |
|
372 |
|
354 |
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)) { |
373 |
if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype)) { |
355 |
byte_copy(key,2,dtype); |
374 |
byte_copy(key,2,dtype); |
356 |
cached = cache_get(key,dlen + 2,&cachedlen,&ttl); |
375 |
cached = cache_get(key,dlen + 2,&cachedlen,&ttl); |
357 |
if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) { |
376 |
if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) { |
Lines 471-499
Link Here
|
471 |
if (rcode && (rcode != 3)) goto DIE; /* impossible; see irrelevant() */ |
490 |
if (rcode && (rcode != 3)) goto DIE; /* impossible; see irrelevant() */ |
472 |
|
491 |
|
473 |
flagout = 0; |
492 |
flagout = 0; |
474 |
flagcname = 0; |
|
|
475 |
flagreferral = 0; |
493 |
flagreferral = 0; |
476 |
flagsoa = 0; |
494 |
flagsoa = 0; |
477 |
soattl = 0; |
495 |
soattl = 0; |
478 |
cnamettl = 0; |
496 |
if (!dns_domain_copy(&owner_name,d)) goto DIE; |
|
|
497 |
/* This code assumes that the CNAME chain is presented in the correct |
498 |
** order. The example algorithm in RFC 1034 will actually result in this |
499 |
** being the case, but the words do not require it to be so. |
500 |
*/ |
479 |
for (j = 0;j < numanswers;++j) { |
501 |
for (j = 0;j < numanswers;++j) { |
480 |
pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE; |
502 |
pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE; |
481 |
pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; |
503 |
pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; |
482 |
|
504 |
|
483 |
if (dns_domain_equal(t1,d)) |
505 |
if (dns_domain_equal(t1,owner_name)) |
484 |
if (byte_equal(header + 2,2,DNS_C_IN)) { /* should always be true */ |
506 |
if (byte_equal(header + 2,2,DNS_C_IN)) { /* should always be true */ |
485 |
if (typematch(header,dtype)) |
507 |
if (typematch(header,dtype)) |
486 |
flagout = 1; |
508 |
flagout = 1; |
487 |
else if (typematch(header,DNS_T_CNAME)) { |
509 |
else if (typematch(header,DNS_T_CNAME)) { |
488 |
if (!dns_packet_getname(buf,len,pos,&cname)) goto DIE; |
510 |
if (!dns_packet_getname(buf,len,pos,&owner_name)) goto DIE; |
489 |
flagcname = 1; |
|
|
490 |
cnamettl = ttlget(header + 4); |
491 |
} |
511 |
} |
492 |
} |
512 |
} |
493 |
|
513 |
|
494 |
uint16_unpack_big(header + 8,&datalen); |
514 |
uint16_unpack_big(header + 8,&datalen); |
495 |
pos += datalen; |
515 |
pos += datalen; |
496 |
} |
516 |
} |
|
|
517 |
dns_domain_free(&owner_name) ; |
497 |
posauthority = pos; |
518 |
posauthority = pos; |
498 |
|
519 |
|
499 |
for (j = 0;j < numauthority;++j) { |
520 |
for (j = 0;j < numauthority;++j) { |
Lines 515-529
Link Here
|
515 |
} |
536 |
} |
516 |
posglue = pos; |
537 |
posglue = pos; |
517 |
|
538 |
|
518 |
|
|
|
519 |
if (!flagcname && !rcode && !flagout && flagreferral && !flagsoa) |
520 |
if (dns_domain_equal(referral,control) || !dns_domain_suffix(referral,control)) { |
521 |
log_lame(whichserver,control,referral); |
522 |
byte_zero(whichserver,4); |
523 |
goto HAVENS; |
524 |
} |
525 |
|
526 |
|
527 |
if (records) { alloc_free(records); records = 0; } |
539 |
if (records) { alloc_free(records); records = 0; } |
528 |
|
540 |
|
529 |
k = numanswers + numauthority + numglue; |
541 |
k = numanswers + numauthority + numglue; |
Lines 670-693
Link Here
|
670 |
|
682 |
|
671 |
alloc_free(records); records = 0; |
683 |
alloc_free(records); records = 0; |
672 |
|
684 |
|
|
|
685 |
if (byte_diff(DNS_T_CNAME,2,dtype)) { |
686 |
/* This code assumes that the CNAME chain is presented in the correct |
687 |
** order. The example algorithm in RFC 1034 will actually result in this |
688 |
** being the case, but the words do not require it to be so. |
689 |
*/ |
690 |
pos = posanswers; |
691 |
for (j = 0;j < numanswers;++j) { |
692 |
pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE; |
693 |
pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; |
694 |
|
695 |
if (dns_domain_equal(t1,d)) |
696 |
if (byte_equal(header + 2,2,DNS_C_IN)) { /* should always be true */ |
697 |
if (typematch(header,DNS_T_CNAME)) { |
698 |
ttl = ttlget(header + 4); |
699 |
if (z->level == 0) { |
700 |
if (!move_name_to_alias(z,ttl)) goto DIE ; |
701 |
} |
702 |
if (!dns_packet_getname(buf,len,pos,&z->name[z->level])) goto DIE; |
703 |
d = z->name[z->level]; |
704 |
if (!dns_domain_suffix(d,control) || !roots_same(d,control)) |
705 |
goto NEWNAME ; /* Cannot trust the chain further - restart using current name */ |
706 |
} |
707 |
} |
673 |
|
708 |
|
674 |
if (flagcname) { |
709 |
uint16_unpack_big(header + 8,&datalen); |
675 |
ttl = cnamettl; |
710 |
pos += datalen; |
676 |
CNAME: |
|
|
677 |
if (!z->level) { |
678 |
if (z->alias[QUERY_MAXALIAS - 1]) goto DIE; |
679 |
for (j = QUERY_MAXALIAS - 1;j > 0;--j) |
680 |
z->alias[j] = z->alias[j - 1]; |
681 |
for (j = QUERY_MAXALIAS - 1;j > 0;--j) |
682 |
z->aliasttl[j] = z->aliasttl[j - 1]; |
683 |
z->alias[0] = z->name[0]; |
684 |
z->aliasttl[0] = ttl; |
685 |
z->name[0] = 0; |
686 |
} |
711 |
} |
687 |
if (!dns_domain_copy(&z->name[z->level],cname)) goto DIE; |
|
|
688 |
goto NEWNAME; |
689 |
} |
712 |
} |
690 |
|
713 |
|
|
|
714 |
/* A "no such name" error applies to the end of any CNAME chain, not to the start. */ |
691 |
if (rcode == 3) { |
715 |
if (rcode == 3) { |
692 |
log_nxdomain(whichserver,d,soattl); |
716 |
log_nxdomain(whichserver,d,soattl); |
693 |
cachegeneric(DNS_T_ANY,d,"",0,soattl); |
717 |
cachegeneric(DNS_T_ANY,d,"",0,soattl); |
Lines 700-709
Link Here
|
700 |
return 1; |
724 |
return 1; |
701 |
} |
725 |
} |
702 |
|
726 |
|
|
|
727 |
/* We check for a lame server _after_ we have cached any records that it |
728 |
** might have returned to us. This copes better with the incorrect |
729 |
** behaviour of one content DNS server software that doesn't return |
730 |
** complete CNAME chains but instead returns only the first link in a |
731 |
** chain followed by a lame delegation to the same server. |
732 |
** Also: We check for a lame server _after_ following the CNAME chain. The |
733 |
** delegation in a referral answer applies to the _end_ of the chain, not |
734 |
** to the beginning. |
735 |
*/ |
736 |
if (!rcode && !flagout && flagreferral && !flagsoa) |
737 |
if (dns_domain_equal(referral,control) || !dns_domain_suffix(referral,control)) { |
738 |
log_lame(whichserver,control,referral); |
739 |
byte_zero(whichserver,4); |
740 |
goto HAVENS; |
741 |
} |
742 |
|
703 |
if (!flagout && flagsoa) |
743 |
if (!flagout && flagsoa) |
|
|
744 |
/* Don't save empty RRSets for those types that we use as special markers. */ |
704 |
if (byte_diff(DNS_T_ANY,2,dtype)) |
745 |
if (byte_diff(DNS_T_ANY,2,dtype)) |
705 |
if (byte_diff(DNS_T_AXFR,2,dtype)) |
746 |
if (byte_diff(DNS_T_AXFR,2,dtype)) { |
706 |
if (byte_diff(DNS_T_CNAME,2,dtype)) { |
|
|
707 |
save_start(); |
747 |
save_start(); |
708 |
save_finish(dtype,d,soattl); |
748 |
save_finish(dtype,d,soattl); |
709 |
log_nodata(whichserver,d,dtype,soattl); |
749 |
log_nodata(whichserver,d,dtype,soattl); |
Lines 815-820
Link Here
|
815 |
DIE: |
855 |
DIE: |
816 |
cleanup(z); |
856 |
cleanup(z); |
817 |
if (records) { alloc_free(records); records = 0; } |
857 |
if (records) { alloc_free(records); records = 0; } |
|
|
858 |
dns_domain_free(&owner_name) ; |
818 |
return -1; |
859 |
return -1; |
819 |
} |
860 |
} |