added djbdns patch provided by Johnny Halfmoon
removed dnsmasq.patch as the options were included upstream already. git-svn-id: svn://svn.openwrt.org/openwrt/packages@15612 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
226
net/djbdns/patches/200-dnscache-cname-handling.patch
Normal file
226
net/djbdns/patches/200-dnscache-cname-handling.patch
Normal file
@ -0,0 +1,226 @@
|
||||
--- djbdns-1.05-original/query.c Sun Feb 11 21:11:45 2001
|
||||
+++ djbdns-1.05/query.c Wed Mar 26 15:48:20 2003
|
||||
@@ -91,6 +91,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
+static int move_name_to_alias(struct query *z,uint32 ttl)
|
||||
+{
|
||||
+ int j ;
|
||||
+
|
||||
+ if (z->alias[QUERY_MAXALIAS - 1]) return 0 ;
|
||||
+ for (j = QUERY_MAXALIAS - 1;j > 0;--j)
|
||||
+ z->alias[j] = z->alias[j - 1];
|
||||
+ for (j = QUERY_MAXALIAS - 1;j > 0;--j)
|
||||
+ z->aliasttl[j] = z->aliasttl[j - 1];
|
||||
+ z->alias[0] = z->name[0];
|
||||
+ z->aliasttl[0] = ttl;
|
||||
+ z->name[0] = 0;
|
||||
+ return 1 ;
|
||||
+}
|
||||
+
|
||||
static int rqa(struct query *z)
|
||||
{
|
||||
int i;
|
||||
@@ -123,7 +138,6 @@
|
||||
static char *t1 = 0;
|
||||
static char *t2 = 0;
|
||||
static char *t3 = 0;
|
||||
-static char *cname = 0;
|
||||
static char *referral = 0;
|
||||
static unsigned int *records = 0;
|
||||
|
||||
@@ -179,15 +193,14 @@
|
||||
uint16 datalen;
|
||||
char *control;
|
||||
char *d;
|
||||
+ char *owner_name = 0 ;
|
||||
const char *dtype;
|
||||
unsigned int dlen;
|
||||
int flagout;
|
||||
- int flagcname;
|
||||
int flagreferral;
|
||||
int flagsoa;
|
||||
uint32 ttl;
|
||||
uint32 soattl;
|
||||
- uint32 cnamettl;
|
||||
int i;
|
||||
int j;
|
||||
int k;
|
||||
@@ -252,7 +265,10 @@
|
||||
|
||||
byte_copy(key,2,DNS_T_CNAME);
|
||||
cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
|
||||
- if (cached) {
|
||||
+ /* A previous explicit query might have caused an empty RRSet to have been
|
||||
+ ** cached. Take care to ignore such a thing.
|
||||
+ */
|
||||
+ if (cached && cachedlen) {
|
||||
if (typematch(DNS_T_CNAME,dtype)) {
|
||||
log_cachedanswer(d,DNS_T_CNAME);
|
||||
if (!rqa(z)) goto DIE;
|
||||
@@ -261,8 +277,11 @@
|
||||
return 1;
|
||||
}
|
||||
log_cachedcname(d,cached);
|
||||
- if (!dns_domain_copy(&cname,cached)) goto DIE;
|
||||
- goto CNAME;
|
||||
+ if (!z->level) {
|
||||
+ if (!move_name_to_alias(z,ttl)) goto DIE ;
|
||||
+ }
|
||||
+ if (!dns_domain_copy(&z->name[z->level],cached)) goto DIE;
|
||||
+ goto NEWNAME;
|
||||
}
|
||||
|
||||
if (typematch(DNS_T_NS,dtype)) {
|
||||
@@ -351,7 +370,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
- 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_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)) {
|
||||
byte_copy(key,2,dtype);
|
||||
cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
|
||||
if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
|
||||
@@ -471,29 +490,31 @@
|
||||
if (rcode && (rcode != 3)) goto DIE; /* impossible; see irrelevant() */
|
||||
|
||||
flagout = 0;
|
||||
- flagcname = 0;
|
||||
flagreferral = 0;
|
||||
flagsoa = 0;
|
||||
soattl = 0;
|
||||
- cnamettl = 0;
|
||||
+ if (!dns_domain_copy(&owner_name,d)) goto DIE;
|
||||
+ /* This code assumes that the CNAME chain is presented in the correct
|
||||
+ ** order. The example algorithm in RFC 1034 will actually result in this
|
||||
+ ** being the case, but the words do not require it to be so.
|
||||
+ */
|
||||
for (j = 0;j < numanswers;++j) {
|
||||
pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
|
||||
pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
|
||||
|
||||
- if (dns_domain_equal(t1,d))
|
||||
+ if (dns_domain_equal(t1,owner_name))
|
||||
if (byte_equal(header + 2,2,DNS_C_IN)) { /* should always be true */
|
||||
if (typematch(header,dtype))
|
||||
flagout = 1;
|
||||
else if (typematch(header,DNS_T_CNAME)) {
|
||||
- if (!dns_packet_getname(buf,len,pos,&cname)) goto DIE;
|
||||
- flagcname = 1;
|
||||
- cnamettl = ttlget(header + 4);
|
||||
+ if (!dns_packet_getname(buf,len,pos,&owner_name)) goto DIE;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_unpack_big(header + 8,&datalen);
|
||||
pos += datalen;
|
||||
}
|
||||
+ dns_domain_free(&owner_name) ;
|
||||
posauthority = pos;
|
||||
|
||||
for (j = 0;j < numauthority;++j) {
|
||||
@@ -515,15 +536,6 @@
|
||||
}
|
||||
posglue = pos;
|
||||
|
||||
-
|
||||
- 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);
|
||||
- goto HAVENS;
|
||||
- }
|
||||
-
|
||||
-
|
||||
if (records) { alloc_free(records); records = 0; }
|
||||
|
||||
k = numanswers + numauthority + numglue;
|
||||
@@ -670,24 +682,36 @@
|
||||
|
||||
alloc_free(records); records = 0;
|
||||
|
||||
+ if (byte_diff(DNS_T_CNAME,2,dtype)) {
|
||||
+ /* This code assumes that the CNAME chain is presented in the correct
|
||||
+ ** order. The example algorithm in RFC 1034 will actually result in this
|
||||
+ ** being the case, but the words do not require it to be so.
|
||||
+ */
|
||||
+ pos = posanswers;
|
||||
+ for (j = 0;j < numanswers;++j) {
|
||||
+ pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
|
||||
+ pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
|
||||
+
|
||||
+ if (dns_domain_equal(t1,d))
|
||||
+ if (byte_equal(header + 2,2,DNS_C_IN)) { /* should always be true */
|
||||
+ if (typematch(header,DNS_T_CNAME)) {
|
||||
+ ttl = ttlget(header + 4);
|
||||
+ if (z->level == 0) {
|
||||
+ if (!move_name_to_alias(z,ttl)) goto DIE ;
|
||||
+ }
|
||||
+ if (!dns_packet_getname(buf,len,pos,&z->name[z->level])) goto DIE;
|
||||
+ d = z->name[z->level];
|
||||
+ if (!dns_domain_suffix(d,control) || !roots_same(d,control))
|
||||
+ goto NEWNAME ; /* Cannot trust the chain further - restart using current name */
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (flagcname) {
|
||||
- ttl = cnamettl;
|
||||
- CNAME:
|
||||
- if (!z->level) {
|
||||
- if (z->alias[QUERY_MAXALIAS - 1]) goto DIE;
|
||||
- for (j = QUERY_MAXALIAS - 1;j > 0;--j)
|
||||
- z->alias[j] = z->alias[j - 1];
|
||||
- for (j = QUERY_MAXALIAS - 1;j > 0;--j)
|
||||
- z->aliasttl[j] = z->aliasttl[j - 1];
|
||||
- z->alias[0] = z->name[0];
|
||||
- z->aliasttl[0] = ttl;
|
||||
- z->name[0] = 0;
|
||||
+ uint16_unpack_big(header + 8,&datalen);
|
||||
+ pos += datalen;
|
||||
}
|
||||
- if (!dns_domain_copy(&z->name[z->level],cname)) goto DIE;
|
||||
- goto NEWNAME;
|
||||
}
|
||||
|
||||
+ /* A "no such name" error applies to the end of any CNAME chain, not to the start. */
|
||||
if (rcode == 3) {
|
||||
log_nxdomain(whichserver,d,soattl);
|
||||
cachegeneric(DNS_T_ANY,d,"",0,soattl);
|
||||
@@ -700,10 +724,26 @@
|
||||
return 1;
|
||||
}
|
||||
|
||||
+ /* We check for a lame server _after_ we have cached any records that it
|
||||
+ ** might have returned to us. This copes better with the incorrect
|
||||
+ ** behaviour of one content DNS server software that doesn't return
|
||||
+ ** complete CNAME chains but instead returns only the first link in a
|
||||
+ ** chain followed by a lame delegation to the same server.
|
||||
+ ** Also: We check for a lame server _after_ following the CNAME chain. The
|
||||
+ ** delegation in a referral answer applies to the _end_ of the chain, not
|
||||
+ ** to the beginning.
|
||||
+ */
|
||||
+ if (!rcode && !flagout && flagreferral && !flagsoa)
|
||||
+ if (dns_domain_equal(referral,control) || !dns_domain_suffix(referral,control)) {
|
||||
+ log_lame(whichserver,control,referral);
|
||||
+ byte_zero(whichserver,4);
|
||||
+ goto HAVENS;
|
||||
+ }
|
||||
+
|
||||
if (!flagout && flagsoa)
|
||||
+ /* Don't save empty RRSets for those types that we use as special markers. */
|
||||
if (byte_diff(DNS_T_ANY,2,dtype))
|
||||
- if (byte_diff(DNS_T_AXFR,2,dtype))
|
||||
- if (byte_diff(DNS_T_CNAME,2,dtype)) {
|
||||
+ if (byte_diff(DNS_T_AXFR,2,dtype)) {
|
||||
save_start();
|
||||
save_finish(dtype,d,soattl);
|
||||
log_nodata(whichserver,d,dtype,soattl);
|
||||
@@ -815,6 +855,7 @@
|
||||
DIE:
|
||||
cleanup(z);
|
||||
if (records) { alloc_free(records); records = 0; }
|
||||
+ dns_domain_free(&owner_name) ;
|
||||
return -1;
|
||||
}
|
||||
|
Reference in New Issue
Block a user