diff -r 234a43b14e18 -r a78e58de5a7e diet-djbdns-dnscache-cname-handling.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/diet-djbdns-dnscache-cname-handling.patch Fri Feb 17 10:48:04 2012 +0100 @@ -0,0 +1,292 @@ +# HG changeset patch +# Parent 847c22ddbdd92b4a49325912c5bb7c075b0350e3 +dnscache CNAME handling + +diff -r 847c22ddbdd9 source/dietlibc/diet-djbdns/FrugalBuild +--- a/source/dietlibc/diet-djbdns/FrugalBuild Fri Feb 17 10:25:48 2012 +0100 ++++ b/source/dietlibc/diet-djbdns/FrugalBuild Fri Feb 17 10:47:53 2012 +0100 +@@ -4,7 +4,7 @@ + pkgorig=djbdns + pkgname=$branch-$pkgorig + pkgver=1.05 +-pkgrel=3 ++pkgrel=4 + pkgdesc="High-performant & secure DNS services." + url="http://cr.yp.to/djbdns.html" + archs=(i686) +@@ -13,12 +13,14 @@ + makedepends=(dietlibc) + install="$pkgorig.install" + backup=(etc/dnsroots.global) +-source=(http://cr.yp.to/$pkgorig/$pkgorig-$pkgver.tar.gz) ++source=(http://cr.yp.to/$pkgorig/$pkgorig-$pkgver.tar.gz \ ++ dnscache-cname-handling.patch) + sha1sums=('2efdb3a039d0c548f40936aa9cb30829e0ce8c3d') + provides=(djbdns) + + build() { + Fcd $pkgorig-$pkgver ++ Fpatchall + echo "diet gcc ${CFLAGS}" > conf-cc + echo "diet gcc -s -static" > conf-ld + echo "/usr" > conf-home +diff -r 847c22ddbdd9 source/dietlibc/diet-djbdns/dnscache-cname-handling.patch +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/source/dietlibc/diet-djbdns/dnscache-cname-handling.patch Fri Feb 17 10:47:53 2012 +0100 +@@ -0,0 +1,256 @@ ++http://homepage.ntlworld.com/jonathan.deboynepollard/Softwares/djbdns/dnscache-cname-handling.patch ++http://homepage.ntlworld.com/jonathan.deboynepollard/Softwares/djbdns/ ++ ++Making dnscache handle client-side aliases ("CNAME" records) correctly ++ ++There are several problems with the way that dnscache handles client-side ++aliases, that become acutely apparent if one patches qmail to remove the ++workaround for a BIND version 4 problem. This patch modifies the behaviour of ++dnscache, to correct them, in the following ways: ++ ++dnscache will cache "CNAME" resource record sets (both empty and non-empty). ++ ++dnscache will correctly ignore a cached "CNAME" resource record set that ++happens to be empty (which will result if an explicit "CNAME" query is made ++against a domain name that has no client-side aliases). ++ ++dnscache will notice lame servers where the lame delegation is present at the ++end of a chain of client-side aliases. Any instances of tinydns that have not ++been patched to make them publish whole alias chains instead of just the first ++links will thus be logged as "lame". ++ ++dnscache will not issue redundant queries if it can follow an entire ++client-side alias chain to the end using the information that it already has in ++a response. ++ ++dnscache will cache any in-bailiwick information that it receives from lame ++servers. Any in-bailiwick client-side alias information and delegation ++information that are received from an otherwise "lame" server will no longer be ++thrown away along with the bath-water. ++ ++--- 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; ++ } ++