|
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 + |