diet-djbdns-dnscache-cname-handling.patch
changeset 134 a78e58de5a7e
child 135 92afa092bd07
equal deleted inserted replaced
133:234a43b14e18 134:a78e58de5a7e
       
     1 # HG changeset patch
       
     2 # Parent 847c22ddbdd92b4a49325912c5bb7c075b0350e3
       
     3 dnscache CNAME handling
       
     4 
       
     5 diff -r 847c22ddbdd9 source/dietlibc/diet-djbdns/FrugalBuild
       
     6 --- a/source/dietlibc/diet-djbdns/FrugalBuild	Fri Feb 17 10:25:48 2012 +0100
       
     7 +++ b/source/dietlibc/diet-djbdns/FrugalBuild	Fri Feb 17 10:47:53 2012 +0100
       
     8 @@ -4,7 +4,7 @@
       
     9  pkgorig=djbdns
       
    10  pkgname=$branch-$pkgorig
       
    11  pkgver=1.05
       
    12 -pkgrel=3
       
    13 +pkgrel=4
       
    14  pkgdesc="High-performant & secure DNS services."
       
    15  url="http://cr.yp.to/djbdns.html"
       
    16  archs=(i686)
       
    17 @@ -13,12 +13,14 @@
       
    18  makedepends=(dietlibc)
       
    19  install="$pkgorig.install"
       
    20  backup=(etc/dnsroots.global)
       
    21 -source=(http://cr.yp.to/$pkgorig/$pkgorig-$pkgver.tar.gz)
       
    22 +source=(http://cr.yp.to/$pkgorig/$pkgorig-$pkgver.tar.gz \
       
    23 +	dnscache-cname-handling.patch)
       
    24  sha1sums=('2efdb3a039d0c548f40936aa9cb30829e0ce8c3d')
       
    25  provides=(djbdns)
       
    26  
       
    27  build() {
       
    28  	Fcd $pkgorig-$pkgver
       
    29 +	Fpatchall
       
    30  	echo "diet gcc ${CFLAGS}" > conf-cc
       
    31  	echo "diet gcc -s -static" > conf-ld
       
    32  	echo "/usr" > conf-home
       
    33 diff -r 847c22ddbdd9 source/dietlibc/diet-djbdns/dnscache-cname-handling.patch
       
    34 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
       
    35 +++ b/source/dietlibc/diet-djbdns/dnscache-cname-handling.patch	Fri Feb 17 10:47:53 2012 +0100
       
    36 @@ -0,0 +1,256 @@
       
    37 +http://homepage.ntlworld.com/jonathan.deboynepollard/Softwares/djbdns/dnscache-cname-handling.patch
       
    38 +http://homepage.ntlworld.com/jonathan.deboynepollard/Softwares/djbdns/
       
    39 +
       
    40 +Making dnscache handle client-side aliases ("CNAME" records) correctly
       
    41 +
       
    42 +There are several problems with the way that dnscache handles client-side
       
    43 +aliases, that become acutely apparent if one patches qmail to remove the
       
    44 +workaround for a BIND version 4 problem. This patch modifies the behaviour of
       
    45 +dnscache, to correct them, in the following ways:
       
    46 +
       
    47 +dnscache will cache "CNAME" resource record sets (both empty and non-empty).
       
    48 +
       
    49 +dnscache will correctly ignore a cached "CNAME" resource record set that
       
    50 +happens to be empty (which will result if an explicit "CNAME" query is made
       
    51 +against a domain name that has no client-side aliases).
       
    52 +
       
    53 +dnscache will notice lame servers where the lame delegation is present at the
       
    54 +end of a chain of client-side aliases. Any instances of tinydns that have not
       
    55 +been patched to make them publish whole alias chains instead of just the first
       
    56 +links will thus be logged as "lame".
       
    57 +
       
    58 +dnscache will not issue redundant queries if it can follow an entire
       
    59 +client-side alias chain to the end using the information that it already has in
       
    60 +a response.
       
    61 +
       
    62 +dnscache will cache any in-bailiwick information that it receives from lame
       
    63 +servers. Any in-bailiwick client-side alias information and delegation
       
    64 +information that are received from an otherwise "lame" server will no longer be
       
    65 +thrown away along with the bath-water.
       
    66 +
       
    67 +--- djbdns-1.05-original/query.c	Sun Feb 11 21:11:45 2001
       
    68 ++++ djbdns-1.05/query.c	Wed Mar 26 15:48:20 2003
       
    69 +@@ -91,6 +91,21 @@
       
    70 +   }
       
    71 + }
       
    72 + 
       
    73 ++static int move_name_to_alias(struct query *z,uint32 ttl)
       
    74 ++{
       
    75 ++  int j ;
       
    76 ++
       
    77 ++  if (z->alias[QUERY_MAXALIAS - 1]) return 0 ;
       
    78 ++  for (j = QUERY_MAXALIAS - 1;j > 0;--j)
       
    79 ++    z->alias[j] = z->alias[j - 1];
       
    80 ++  for (j = QUERY_MAXALIAS - 1;j > 0;--j)
       
    81 ++    z->aliasttl[j] = z->aliasttl[j - 1];
       
    82 ++  z->alias[0] = z->name[0];
       
    83 ++  z->aliasttl[0] = ttl;
       
    84 ++  z->name[0] = 0;
       
    85 ++  return 1 ;
       
    86 ++}
       
    87 ++
       
    88 + static int rqa(struct query *z)
       
    89 + {
       
    90 +   int i;
       
    91 +@@ -123,7 +138,6 @@
       
    92 + static char *t1 = 0;
       
    93 + static char *t2 = 0;
       
    94 + static char *t3 = 0;
       
    95 +-static char *cname = 0;
       
    96 + static char *referral = 0;
       
    97 + static unsigned int *records = 0;
       
    98 + 
       
    99 +@@ -179,15 +193,14 @@
       
   100 +   uint16 datalen;
       
   101 +   char *control;
       
   102 +   char *d;
       
   103 ++  char *owner_name = 0 ;
       
   104 +   const char *dtype;
       
   105 +   unsigned int dlen;
       
   106 +   int flagout;
       
   107 +-  int flagcname;
       
   108 +   int flagreferral;
       
   109 +   int flagsoa;
       
   110 +   uint32 ttl;
       
   111 +   uint32 soattl;
       
   112 +-  uint32 cnamettl;
       
   113 +   int i;
       
   114 +   int j;
       
   115 +   int k;
       
   116 +@@ -252,7 +265,10 @@
       
   117 + 
       
   118 +     byte_copy(key,2,DNS_T_CNAME);
       
   119 +     cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
       
   120 +-    if (cached) {
       
   121 ++    /* A previous explicit query might have caused an empty RRSet to have been
       
   122 ++    ** cached.  Take care to ignore such a thing. 
       
   123 ++    */
       
   124 ++    if (cached && cachedlen) {
       
   125 +       if (typematch(DNS_T_CNAME,dtype)) {
       
   126 +         log_cachedanswer(d,DNS_T_CNAME);
       
   127 +         if (!rqa(z)) goto DIE;
       
   128 +@@ -261,8 +277,11 @@
       
   129 + 	return 1;
       
   130 +       }
       
   131 +       log_cachedcname(d,cached);
       
   132 +-      if (!dns_domain_copy(&cname,cached)) goto DIE;
       
   133 +-      goto CNAME;
       
   134 ++      if (!z->level) {
       
   135 ++	if (!move_name_to_alias(z,ttl)) goto DIE ;
       
   136 ++      }
       
   137 ++      if (!dns_domain_copy(&z->name[z->level],cached)) goto DIE;
       
   138 ++      goto NEWNAME;
       
   139 +     }
       
   140 + 
       
   141 +     if (typematch(DNS_T_NS,dtype)) {
       
   142 +@@ -351,7 +370,7 @@
       
   143 +       }
       
   144 +     }
       
   145 + 
       
   146 +-    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)) {
       
   147 ++    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)) {
       
   148 +       byte_copy(key,2,dtype);
       
   149 +       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
       
   150 +       if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
       
   151 +@@ -471,29 +490,31 @@
       
   152 +   if (rcode && (rcode != 3)) goto DIE; /* impossible; see irrelevant() */
       
   153 + 
       
   154 +   flagout = 0;
       
   155 +-  flagcname = 0;
       
   156 +   flagreferral = 0;
       
   157 +   flagsoa = 0;
       
   158 +   soattl = 0;
       
   159 +-  cnamettl = 0;
       
   160 ++  if (!dns_domain_copy(&owner_name,d)) goto DIE;
       
   161 ++  /* This code assumes that the CNAME chain is presented in the correct 
       
   162 ++  ** order.  The example algorithm in RFC 1034 will actually result in this
       
   163 ++  ** being the case, but the words do not require it to be so.
       
   164 ++  */
       
   165 +   for (j = 0;j < numanswers;++j) {
       
   166 +     pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
       
   167 +     pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
       
   168 + 
       
   169 +-    if (dns_domain_equal(t1,d))
       
   170 ++    if (dns_domain_equal(t1,owner_name))
       
   171 +       if (byte_equal(header + 2,2,DNS_C_IN)) { /* should always be true */
       
   172 +         if (typematch(header,dtype))
       
   173 +           flagout = 1;
       
   174 +         else if (typematch(header,DNS_T_CNAME)) {
       
   175 +-          if (!dns_packet_getname(buf,len,pos,&cname)) goto DIE;
       
   176 +-          flagcname = 1;
       
   177 +-	  cnamettl = ttlget(header + 4);
       
   178 ++          if (!dns_packet_getname(buf,len,pos,&owner_name)) goto DIE;
       
   179 +         }
       
   180 +       }
       
   181 +   
       
   182 +     uint16_unpack_big(header + 8,&datalen);
       
   183 +     pos += datalen;
       
   184 +   }
       
   185 ++  dns_domain_free(&owner_name) ;
       
   186 +   posauthority = pos;
       
   187 + 
       
   188 +   for (j = 0;j < numauthority;++j) {
       
   189 +@@ -515,15 +536,6 @@
       
   190 +   }
       
   191 +   posglue = pos;
       
   192 + 
       
   193 +-
       
   194 +-  if (!flagcname && !rcode && !flagout && flagreferral && !flagsoa)
       
   195 +-    if (dns_domain_equal(referral,control) || !dns_domain_suffix(referral,control)) {
       
   196 +-      log_lame(whichserver,control,referral);
       
   197 +-      byte_zero(whichserver,4);
       
   198 +-      goto HAVENS;
       
   199 +-    }
       
   200 +-
       
   201 +-
       
   202 +   if (records) { alloc_free(records); records = 0; }
       
   203 + 
       
   204 +   k = numanswers + numauthority + numglue;
       
   205 +@@ -670,24 +682,36 @@
       
   206 + 
       
   207 +   alloc_free(records); records = 0;
       
   208 + 
       
   209 ++  if (byte_diff(DNS_T_CNAME,2,dtype)) {
       
   210 ++    /* This code assumes that the CNAME chain is presented in the correct 
       
   211 ++    ** order.  The example algorithm in RFC 1034 will actually result in this
       
   212 ++    ** being the case, but the words do not require it to be so.
       
   213 ++    */
       
   214 ++    pos = posanswers;
       
   215 ++    for (j = 0;j < numanswers;++j) {
       
   216 ++      pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
       
   217 ++      pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
       
   218 ++
       
   219 ++      if (dns_domain_equal(t1,d))
       
   220 ++	if (byte_equal(header + 2,2,DNS_C_IN)) { /* should always be true */
       
   221 ++	  if (typematch(header,DNS_T_CNAME)) {
       
   222 ++	    ttl = ttlget(header + 4);
       
   223 ++	    if (z->level == 0) {
       
   224 ++	      if (!move_name_to_alias(z,ttl)) goto DIE ;
       
   225 ++	    }
       
   226 ++	    if (!dns_packet_getname(buf,len,pos,&z->name[z->level])) goto DIE;
       
   227 ++	    d = z->name[z->level];
       
   228 ++	    if (!dns_domain_suffix(d,control) || !roots_same(d,control))
       
   229 ++	      goto NEWNAME ;  /* Cannot trust the chain further - restart using current name */
       
   230 ++	  }
       
   231 ++	}
       
   232 + 
       
   233 +-  if (flagcname) {
       
   234 +-    ttl = cnamettl;
       
   235 +-    CNAME:
       
   236 +-    if (!z->level) {
       
   237 +-      if (z->alias[QUERY_MAXALIAS - 1]) goto DIE;
       
   238 +-      for (j = QUERY_MAXALIAS - 1;j > 0;--j)
       
   239 +-        z->alias[j] = z->alias[j - 1];
       
   240 +-      for (j = QUERY_MAXALIAS - 1;j > 0;--j)
       
   241 +-        z->aliasttl[j] = z->aliasttl[j - 1];
       
   242 +-      z->alias[0] = z->name[0];
       
   243 +-      z->aliasttl[0] = ttl;
       
   244 +-      z->name[0] = 0;
       
   245 ++      uint16_unpack_big(header + 8,&datalen);
       
   246 ++      pos += datalen;
       
   247 +     }
       
   248 +-    if (!dns_domain_copy(&z->name[z->level],cname)) goto DIE;
       
   249 +-    goto NEWNAME;
       
   250 +   }
       
   251 + 
       
   252 ++  /* A "no such name" error applies to the end of any CNAME chain, not to the start. */
       
   253 +   if (rcode == 3) {
       
   254 +     log_nxdomain(whichserver,d,soattl);
       
   255 +     cachegeneric(DNS_T_ANY,d,"",0,soattl);
       
   256 +@@ -700,10 +724,26 @@
       
   257 +     return 1;
       
   258 +   }
       
   259 + 
       
   260 ++  /* We check for a lame server _after_ we have cached any records that it
       
   261 ++  ** might have returned to us.  This copes better with the incorrect
       
   262 ++  ** behaviour of one content DNS server software that doesn't return
       
   263 ++  ** complete CNAME chains but instead returns only the first link in a
       
   264 ++  ** chain followed by a lame delegation to the same server.
       
   265 ++  ** Also: We check for a lame server _after_ following the CNAME chain.  The
       
   266 ++  ** delegation in a referral answer applies to the _end_ of the chain, not
       
   267 ++  ** to the beginning.
       
   268 ++  */
       
   269 ++  if (!rcode && !flagout && flagreferral && !flagsoa)
       
   270 ++    if (dns_domain_equal(referral,control) || !dns_domain_suffix(referral,control)) {
       
   271 ++      log_lame(whichserver,control,referral);
       
   272 ++      byte_zero(whichserver,4);
       
   273 ++      goto HAVENS;
       
   274 ++    }
       
   275 ++
       
   276 +   if (!flagout && flagsoa)
       
   277 ++    /* Don't save empty RRSets for those types that we use as special markers. */
       
   278 +     if (byte_diff(DNS_T_ANY,2,dtype))
       
   279 +-      if (byte_diff(DNS_T_AXFR,2,dtype))
       
   280 +-        if (byte_diff(DNS_T_CNAME,2,dtype)) {
       
   281 ++      if (byte_diff(DNS_T_AXFR,2,dtype)) {
       
   282 +           save_start();
       
   283 +           save_finish(dtype,d,soattl);
       
   284 + 	  log_nodata(whichserver,d,dtype,soattl);
       
   285 +@@ -815,6 +855,7 @@
       
   286 +   DIE:
       
   287 +   cleanup(z);
       
   288 +   if (records) { alloc_free(records); records = 0; }
       
   289 ++  dns_domain_free(&owner_name) ;
       
   290 +   return -1;
       
   291 + }
       
   292 +