diet-djbdns-dnscache-cname-handling.patch: patching djbdns
authorTomas Zeman <tzeman@volny.cz>
Fri, 17 Feb 2012 10:48:04 +0100
changeset 134 a78e58de5a7e
parent 133 234a43b14e18
child 135 92afa092bd07
diet-djbdns-dnscache-cname-handling.patch: patching djbdns
diet-djbdns-dnscache-cname-handling.patch
series
--- /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;
++ }
++ 
--- a/series	Fri Feb 17 10:25:06 2012 +0100
+++ b/series	Fri Feb 17 10:48:04 2012 +0100
@@ -9,6 +9,7 @@
 cvm.patch
 diet-ucspi-tcp.patch
 diet-djbdns.patch
+diet-djbdns-dnscache-cname-handling.patch
 mailfront.patch
 diet-runit.patch
 diet-mess822.patch