]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/dnsmasq/025-Major_tidy_up_of_EDNS0_handling_and_computation_use_of_udp.patch
bird: New package
[ipfire-2.x.git] / src / patches / dnsmasq / 025-Major_tidy_up_of_EDNS0_handling_and_computation_use_of_udp.patch
1 From fa14bec83b2db010fd076910fddab56957b9375d Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Sun, 20 Dec 2015 17:12:16 +0000
4 Subject: [PATCH] Major tidy up of EDNS0 handling and computation/use of udp
5 packet size.
6
7 ---
8 src/auth.c | 8 ++-
9 src/dnsmasq.h | 7 ++-
10 src/dnssec.c | 1 -
11 src/forward.c | 184 ++++++++++++++++++++++++++++++++++++++++----------------
12 src/netlink.c | 3 +-
13 src/rfc1035.c | 81 +++++++------------------
14 src/rrfilter.c | 2 +-
15 7 files changed, 168 insertions(+), 118 deletions(-)
16
17 diff --git a/src/auth.c b/src/auth.c
18 index 2b0b7d6..85bd5e7 100644
19 --- a/src/auth.c
20 +++ b/src/auth.c
21 @@ -81,7 +81,8 @@ int in_zone(struct auth_zone *zone, char *name, char **cut)
22 }
23
24
25 -size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr, int local_query)
26 +size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr,
27 + int local_query, int do_bit, int have_pseudoheader)
28 {
29 char *name = daemon->namebuff;
30 unsigned char *p, *ansp;
31 @@ -820,6 +821,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
32 header->ancount = htons(anscount);
33 header->nscount = htons(authcount);
34 header->arcount = htons(0);
35 +
36 + /* Advertise our packet size limit in our reply */
37 + if (have_pseudoheader)
38 + return add_pseudoheader(header, ansp - (unsigned char *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit);
39 +
40 return ansp - (unsigned char *)header;
41 }
42
43 diff --git a/src/dnsmasq.h b/src/dnsmasq.h
44 index 39a930c..abb34c5 100644
45 --- a/src/dnsmasq.h
46 +++ b/src/dnsmasq.h
47 @@ -1113,7 +1113,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff,
48 int no_cache, int secure, int *doctored);
49 size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
50 struct in_addr local_addr, struct in_addr local_netmask,
51 - time_t now, int *ad_reqd, int *do_bit);
52 + time_t now, int ad_reqd, int do_bit, int have_pseudoheader);
53 int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
54 struct bogus_addr *addr, time_t now);
55 int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
56 @@ -1123,6 +1123,8 @@ int check_for_local_domain(char *name, time_t now);
57 unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
58 size_t resize_packet(struct dns_header *header, size_t plen,
59 unsigned char *pheader, size_t hlen);
60 +size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
61 + unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do);
62 size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
63 size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, union mysockaddr *source);
64 #ifdef HAVE_DNSSEC
65 @@ -1141,7 +1143,8 @@ int private_net(struct in_addr addr, int ban_localhost);
66 /* auth.c */
67 #ifdef HAVE_AUTH
68 size_t answer_auth(struct dns_header *header, char *limit, size_t qlen,
69 - time_t now, union mysockaddr *peer_addr, int local_query);
70 + time_t now, union mysockaddr *peer_addr, int local_query,
71 + int do_bit, int have_pseudoheader);
72 int in_zone(struct auth_zone *zone, char *name, char **cut);
73 #endif
74
75 diff --git a/src/dnssec.c b/src/dnssec.c
76 index 82394ee..299ca64 100644
77 --- a/src/dnssec.c
78 +++ b/src/dnssec.c
79 @@ -67,7 +67,6 @@ static char *algo_digest_name(int algo)
80 case 12: return "gosthash94";
81 case 13: return "sha256";
82 case 14: return "sha384";
83 -
84 default: return NULL;
85 }
86 }
87 diff --git a/src/forward.c b/src/forward.c
88 index 3e801c8..041353c 100644
89 --- a/src/forward.c
90 +++ b/src/forward.c
91 @@ -244,7 +244,6 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
92 void *hash = &crc;
93 #endif
94 unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
95 - unsigned char *pheader;
96
97 (void)do_bit;
98
99 @@ -264,7 +263,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
100 there's no point retrying the query, retry the key query instead...... */
101 if (forward->blocking_query)
102 {
103 - int fd;
104 + int fd, is_sign;
105 + unsigned char *pheader;
106
107 forward->flags &= ~FREC_TEST_PKTSZ;
108
109 @@ -276,8 +276,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
110 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
111 plen = forward->stash_len;
112
113 - if (find_pseudoheader(header, plen, NULL, &pheader, NULL))
114 - PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? SAFE_PKTSZ : forward->sentto->edns_pktsz, pheader);
115 + if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign) && !is_sign)
116 + PUTSHORT(SAFE_PKTSZ, pheader);
117
118 if (forward->sentto->addr.sa.sa_family == AF_INET)
119 log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
120 @@ -394,32 +394,40 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
121 forward->log_id = daemon->log_id;
122
123 if (option_bool(OPT_ADD_MAC))
124 - plen = add_mac(header, plen, ((char *) header) + daemon->packet_buff_sz, &forward->source);
125 -
126 + {
127 + size_t new = add_mac(header, plen, ((char *) header) + daemon->packet_buff_sz, &forward->source);
128 + if (new != plen)
129 + {
130 + plen = new;
131 + forward->flags |= FREC_ADDED_PHEADER;
132 + }
133 + }
134 +
135 if (option_bool(OPT_CLIENT_SUBNET))
136 {
137 size_t new = add_source_addr(header, plen, ((char *) header) + daemon->packet_buff_sz, &forward->source);
138 if (new != plen)
139 {
140 plen = new;
141 - forward->flags |= FREC_HAS_SUBNET;
142 + forward->flags |= FREC_HAS_SUBNET | FREC_ADDED_PHEADER;
143 }
144 }
145
146 #ifdef HAVE_DNSSEC
147 if (option_bool(OPT_DNSSEC_VALID))
148 {
149 - size_t new_plen = add_do_bit(header, plen, ((char *) header) + daemon->packet_buff_sz);
150 + size_t new = add_do_bit(header, plen, ((char *) header) + daemon->packet_buff_sz);
151
152 + if (new != plen)
153 + forward->flags |= FREC_ADDED_PHEADER;
154 +
155 + plen = new;
156 +
157 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
158 this allows it to select auth servers when one is returning bad data. */
159 if (option_bool(OPT_DNSSEC_DEBUG))
160 header->hb4 |= HB4_CD;
161
162 - if (new_plen != plen)
163 - forward->flags |= FREC_ADDED_PHEADER;
164 -
165 - plen = new_plen;
166 }
167 #endif
168
169 @@ -469,10 +477,23 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
170 }
171 #endif
172 }
173 -
174 - if (find_pseudoheader(header, plen, NULL, &pheader, NULL))
175 - PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? SAFE_PKTSZ : start->edns_pktsz, pheader);
176
177 +#ifdef HAVE_DNSSEC
178 + if (option_bool(OPT_DNSSEC_VALID) && !do_bit)
179 + {
180 + /* Difficult one here. If our client didn't send EDNS0, we will have set the UDP
181 + packet size to 512. But that won't provide space for the RRSIGS in many cases.
182 + The RRSIGS will be stripped out before the answer goes back, so the packet should
183 + shrink again. So, if we added a do-bit, bump the udp packet size to the value
184 + known to be OK for this server. Maybe check returned size after stripping and set
185 + the truncated bit? */
186 + unsigned char *pheader;
187 + int is_sign;
188 + if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign))
189 + PUTSHORT(start->edns_pktsz, pheader);
190 + }
191 +#endif
192 +
193 if (retry_send(sendto(fd, (char *)header, plen, 0,
194 &start->addr.sa,
195 sa_len(&start->addr))))
196 @@ -563,30 +584,34 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
197 }
198 #endif
199
200 - /* If upstream is advertising a larger UDP packet size
201 - than we allow, trim it so that we don't get overlarge
202 - requests for the client. We can't do this for signed packets. */
203 -
204 if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)))
205 {
206 - unsigned short udpsz;
207 - unsigned char *psave = sizep;
208 -
209 - GETSHORT(udpsz, sizep);
210 -
211 - if (!is_sign && udpsz > daemon->edns_pktsz)
212 - PUTSHORT(daemon->edns_pktsz, psave);
213 -
214 if (check_subnet && !check_source(header, plen, pheader, query_source))
215 {
216 my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
217 return 0;
218 }
219
220 - if (added_pheader)
221 + if (!is_sign)
222 {
223 - pheader = 0;
224 - header->arcount = htons(0);
225 + if (added_pheader)
226 + {
227 + /* client didn't send EDNS0, we added one, strip it off before returning answer. */
228 + n = rrfilter(header, n, 0);
229 + pheader = NULL;
230 + }
231 + else
232 + {
233 + /* If upstream is advertising a larger UDP packet size
234 + than we allow, trim it so that we don't get overlarge
235 + requests for the client. We can't do this for signed packets. */
236 + unsigned short udpsz;
237 + unsigned char *psave = sizep;
238 +
239 + GETSHORT(udpsz, sizep);
240 + if (udpsz > daemon->edns_pktsz)
241 + PUTSHORT(daemon->edns_pktsz, psave);
242 + }
243 }
244 }
245
246 @@ -655,14 +680,16 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
247 }
248
249 if (option_bool(OPT_DNSSEC_VALID))
250 - header->hb4 &= ~HB4_AD;
251 -
252 - if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
253 - header->hb4 |= HB4_AD;
254 -
255 - /* If the requestor didn't set the DO bit, don't return DNSSEC info. */
256 - if (!do_bit)
257 - n = rrfilter(header, n, 1);
258 + {
259 + header->hb4 &= ~HB4_AD;
260 +
261 + if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
262 + header->hb4 |= HB4_AD;
263 +
264 + /* If the requestor didn't set the DO bit, don't return DNSSEC info. */
265 + if (!do_bit)
266 + n = rrfilter(header, n, 1);
267 + }
268 #endif
269
270 /* do this after extract_addresses. Ensure NODATA reply and remove
271 @@ -761,8 +788,14 @@ void reply_query(int fd, int family, time_t now)
272 if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
273 {
274 header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC);
275 - header->hb4 &= ~(HB4_RA | HB4_RCODE);
276 - forward_query(-1, NULL, NULL, 0, header, nn, now, forward, 0, 0);
277 + header->hb4 &= ~(HB4_RA | HB4_RCODE | HB4_CD | HB4_AD);
278 + if (forward->flags |= FREC_CHECKING_DISABLED)
279 + header->hb4 |= HB4_CD;
280 + if (forward->flags |= FREC_AD_QUESTION)
281 + header->hb4 |= HB4_AD;
282 + if (forward->flags & FREC_DO_QUESTION)
283 + add_do_bit(header, nn, (char *)pheader + plen);
284 + forward_query(-1, NULL, NULL, 0, header, nn, now, forward, forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION);
285 return;
286 }
287 }
288 @@ -1007,12 +1040,13 @@ void receive_query(struct listener *listen, time_t now)
289 {
290 struct dns_header *header = (struct dns_header *)daemon->packet;
291 union mysockaddr source_addr;
292 - unsigned short type;
293 + unsigned char *pheader;
294 + unsigned short type, udp_size = PACKETSZ; /* default if no EDNS0 */
295 struct all_addr dst_addr;
296 struct in_addr netmask, dst_addr_4;
297 size_t m;
298 ssize_t n;
299 - int if_index = 0, auth_dns = 0;
300 + int if_index = 0, auth_dns = 0, do_bit = 0, have_pseudoheader = 0;
301 #ifdef HAVE_AUTH
302 int local_auth = 0;
303 #endif
304 @@ -1279,10 +1313,30 @@ void receive_query(struct listener *listen, time_t now)
305 #endif
306 }
307
308 + if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL))
309 + {
310 + unsigned short flags;
311 +
312 + have_pseudoheader = 1;
313 + GETSHORT(udp_size, pheader);
314 + pheader += 2; /* ext_rcode */
315 + GETSHORT(flags, pheader);
316 +
317 + if (flags & 0x8000)
318 + do_bit = 1;/* do bit */
319 +
320 + /* If the client provides an EDNS0 UDP size, use that to limit our reply.
321 + (bounded by the maximum configured). If no EDNS0, then it
322 + defaults to 512 */
323 + if (udp_size > daemon->edns_pktsz)
324 + udp_size = daemon->edns_pktsz;
325 + }
326 +
327 #ifdef HAVE_AUTH
328 if (auth_dns)
329 {
330 - m = answer_auth(header, ((char *) header) + daemon->packet_buff_sz, (size_t)n, now, &source_addr, local_auth);
331 + m = answer_auth(header, ((char *) header) + udp_size, (size_t)n, now, &source_addr,
332 + local_auth, do_bit, have_pseudoheader);
333 if (m >= 1)
334 {
335 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
336 @@ -1293,9 +1347,13 @@ void receive_query(struct listener *listen, time_t now)
337 else
338 #endif
339 {
340 - int ad_reqd, do_bit;
341 - m = answer_request(header, ((char *) header) + daemon->packet_buff_sz, (size_t)n,
342 - dst_addr_4, netmask, now, &ad_reqd, &do_bit);
343 + int ad_reqd = do_bit;
344 + /* RFC 6840 5.7 */
345 + if (header->hb4 & HB4_AD)
346 + ad_reqd = 1;
347 +
348 + m = answer_request(header, ((char *) header) + udp_size, (size_t)n,
349 + dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
350
351 if (m >= 1)
352 {
353 @@ -1397,7 +1455,7 @@ unsigned char *tcp_request(int confd, time_t now,
354 #ifdef HAVE_AUTH
355 int local_auth = 0;
356 #endif
357 - int checking_disabled, ad_question, do_bit, added_pheader = 0;
358 + int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
359 int check_subnet, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
360 size_t m;
361 unsigned short qtype;
362 @@ -1414,6 +1472,7 @@ unsigned char *tcp_request(int confd, time_t now,
363 union mysockaddr peer_addr;
364 socklen_t peer_len = sizeof(union mysockaddr);
365 int query_count = 0;
366 + unsigned char *pheader;
367
368 if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
369 return packet;
370 @@ -1508,15 +1567,35 @@ unsigned char *tcp_request(int confd, time_t now,
371 else
372 dst_addr_4.s_addr = 0;
373
374 + do_bit = 0;
375 +
376 + if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL))
377 + {
378 + unsigned short flags;
379 +
380 + have_pseudoheader = 1;
381 + pheader += 4; /* udp_size, ext_rcode */
382 + GETSHORT(flags, pheader);
383 +
384 + if (flags & 0x8000)
385 + do_bit = 1;/* do bit */
386 + }
387 +
388 #ifdef HAVE_AUTH
389 if (auth_dns)
390 - m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr, local_auth);
391 + m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr,
392 + local_auth, do_bit, have_pseudoheader);
393 else
394 #endif
395 {
396 - /* m > 0 if answered from cache */
397 - m = answer_request(header, ((char *) header) + 65536, (size_t)size,
398 - dst_addr_4, netmask, now, &ad_question, &do_bit);
399 + int ad_reqd = do_bit;
400 + /* RFC 6840 5.7 */
401 + if (header->hb4 & HB4_AD)
402 + ad_reqd = 1;
403 +
404 + /* m > 0 if answered from cache */
405 + m = answer_request(header, ((char *) header) + 65536, (size_t)size,
406 + dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
407
408 /* Do this by steam now we're not in the select() loop */
409 check_log_writer(1);
410 @@ -1615,6 +1694,7 @@ unsigned char *tcp_request(int confd, time_t now,
411 }
412
413 #ifdef HAVE_DNSSEC
414 + added_pheader = 0;
415 if (option_bool(OPT_DNSSEC_VALID))
416 {
417 size_t new_size = add_do_bit(header, size, ((char *) header) + 65536);
418 @@ -1719,7 +1799,7 @@ unsigned char *tcp_request(int confd, time_t now,
419
420 m = process_reply(header, now, last_server, (unsigned int)m,
421 option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
422 - ad_question, do_bit, added_pheader, check_subnet, &peer_addr);
423 + ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr);
424
425 break;
426 }
427 diff --git a/src/netlink.c b/src/netlink.c
428 index 753784d..3376d68 100644
429 --- a/src/netlink.c
430 +++ b/src/netlink.c
431 @@ -288,7 +288,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
432 rta = RTA_NEXT(rta, len1);
433 }
434
435 - if (inaddr && mac && callback_ok)
436 + if (!(neigh->ndm_state & (NUD_NOARP | NUD_INCOMPLETE | NUD_FAILED)) &&
437 + inaddr && mac && callback_ok)
438 if (!((*callback)(neigh->ndm_family, inaddr, mac, maclen, parm)))
439 callback_ok = 0;
440 }
441 diff --git a/src/rfc1035.c b/src/rfc1035.c
442 index 188d05f..18858a8 100644
443 --- a/src/rfc1035.c
444 +++ b/src/rfc1035.c
445 @@ -489,8 +489,8 @@ struct macparm {
446 union mysockaddr *l3;
447 };
448
449 -static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
450 - int optno, unsigned char *opt, size_t optlen, int set_do)
451 +size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
452 + unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do)
453 {
454 unsigned char *lenp, *datap, *p;
455 int rdlen, is_sign;
456 @@ -508,7 +508,7 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned
457 return plen;
458 *p++ = 0; /* empty name */
459 PUTSHORT(T_OPT, p);
460 - PUTSHORT(SAFE_PKTSZ, p); /* max packet length, this will be overwritten */
461 + PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
462 PUTSHORT(0, p); /* extended RCODE and version */
463 PUTSHORT(set_do ? 0x8000 : 0, p); /* DO flag */
464 lenp = p;
465 @@ -594,7 +594,7 @@ static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *p
466 if (!match)
467 return 1; /* continue */
468
469 - parm->plen = add_pseudoheader(parm->header, parm->plen, parm->limit, EDNS0_OPTION_MAC, (unsigned char *)mac, maclen, 0);
470 + parm->plen = add_pseudoheader(parm->header, parm->plen, parm->limit, PACKETSZ, EDNS0_OPTION_MAC, (unsigned char *)mac, maclen, 0);
471
472 return 0; /* done */
473 }
474 @@ -603,12 +603,6 @@ size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysock
475 {
476 struct macparm parm;
477
478 -/* Must have an existing pseudoheader as the only ar-record,
479 - or have no ar-records. Must also not be signed */
480 -
481 - if (ntohs(header->arcount) > 1)
482 - return plen;
483 -
484 parm.header = header;
485 parm.limit = (unsigned char *)limit;
486 parm.plen = plen;
487 @@ -699,13 +693,13 @@ size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, unio
488 struct subnet_opt opt;
489
490 len = calc_subnet_opt(&opt, source);
491 - return add_pseudoheader(header, plen, (unsigned char *)limit, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0);
492 + return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0);
493 }
494
495 #ifdef HAVE_DNSSEC
496 size_t add_do_bit(struct dns_header *header, size_t plen, char *limit)
497 {
498 - return add_pseudoheader(header, plen, (unsigned char *)limit, 0, NULL, 0, 1);
499 + return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, 0, NULL, 0, 1);
500 }
501 #endif
502
503 @@ -1525,16 +1519,16 @@ static unsigned long crec_ttl(struct crec *crecp, time_t now)
504 /* return zero if we can't answer from cache, or packet size if we can */
505 size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
506 struct in_addr local_addr, struct in_addr local_netmask,
507 - time_t now, int *ad_reqd, int *do_bit)
508 + time_t now, int ad_reqd, int do_bit, int have_pseudoheader)
509 {
510 char *name = daemon->namebuff;
511 - unsigned char *p, *ansp, *pheader;
512 + unsigned char *p, *ansp;
513 unsigned int qtype, qclass;
514 struct all_addr addr;
515 int nameoffset;
516 unsigned short flag;
517 int q, ans, anscount = 0, addncount = 0;
518 - int dryrun = 0, sec_reqd = 0, have_pseudoheader = 0;
519 + int dryrun = 0;
520 struct crec *crecp;
521 int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
522 struct mx_srv_record *rec;
523 @@ -1550,35 +1544,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
524 if (header->hb4 & HB4_CD)
525 sec_data = 0;
526
527 - /* RFC 6840 5.7 */
528 - *ad_reqd = header->hb4 & HB4_AD;
529 - *do_bit = 0;
530 -
531 /* If there is an additional data section then it will be overwritten by
532 partial replies, so we have to do a dry run to see if we can answer
533 the query. */
534 -
535 if (ntohs(header->arcount) != 0)
536 - {
537 - dryrun = 1;
538 -
539 - /* If there's an additional section, there might be an EDNS(0) pseudoheader */
540 - if (find_pseudoheader(header, qlen, NULL, &pheader, NULL))
541 - {
542 - unsigned short flags;
543 -
544 - have_pseudoheader = 1;
545 -
546 - pheader += 4; /* udp size, ext_rcode */
547 - GETSHORT(flags, pheader);
548 -
549 - if ((sec_reqd = flags & 0x8000))
550 - {
551 - *do_bit = 1;/* do bit */
552 - *ad_reqd = 1;
553 - }
554 - }
555 - }
556 + dryrun = 1;
557
558 for (rec = daemon->mxnames; rec; rec = rec->next)
559 rec->offset = 0;
560 @@ -1603,11 +1573,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
561 GETSHORT(qtype, p);
562 GETSHORT(qclass, p);
563
564 - /* Don't filter RRSIGS from answers to ANY queries, even if do-bit
565 - not set. */
566 - if (qtype == T_ANY)
567 - *do_bit = 1;
568 -
569 ans = 0; /* have we answered this question */
570
571 if (qtype == T_TXT || qtype == T_ANY)
572 @@ -1739,7 +1704,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
573 the zone is unsigned, which implies that we're doing
574 validation. */
575 if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
576 - !sec_reqd ||
577 + !do_bit ||
578 (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
579 {
580 do
581 @@ -1927,7 +1892,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
582 }
583
584 /* If the client asked for DNSSEC don't use cached data. */
585 - if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !sec_reqd || !(crecp->flags & F_DNSSECOK))
586 + if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))
587 do
588 {
589 /* don't answer wildcard queries with data not from /etc/hosts
590 @@ -1961,17 +1926,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
591
592 if (crecp->flags & F_NEG)
593 {
594 - /* We don't cache NSEC records, so if a DNSSEC-validated negative answer
595 - is cached and the client wants DNSSEC, forward rather than answering from the cache */
596 - if (!sec_reqd || !(crecp->flags & F_DNSSECOK))
597 - {
598 - ans = 1;
599 - auth = 0;
600 - if (crecp->flags & F_NXDOMAIN)
601 - nxdomain = 1;
602 - if (!dryrun)
603 - log_query(crecp->flags, name, NULL, NULL);
604 - }
605 + ans = 1;
606 + auth = 0;
607 + if (crecp->flags & F_NXDOMAIN)
608 + nxdomain = 1;
609 + if (!dryrun)
610 + log_query(crecp->flags, name, NULL, NULL);
611 }
612 else
613 {
614 @@ -2209,10 +2169,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
615
616 len = ansp - (unsigned char *)header;
617
618 + /* Advertise our packet size limit in our reply */
619 if (have_pseudoheader)
620 - len = add_pseudoheader(header, len, (unsigned char *)limit, 0, NULL, 0, sec_reqd);
621 + len = add_pseudoheader(header, len, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit);
622
623 - if (*ad_reqd && sec_data)
624 + if (ad_reqd && sec_data)
625 header->hb4 |= HB4_AD;
626 else
627 header->hb4 &= ~HB4_AD;
628 diff --git a/src/rrfilter.c b/src/rrfilter.c
629 index ae12261..b26b39f 100644
630 --- a/src/rrfilter.c
631 +++ b/src/rrfilter.c
632 @@ -243,7 +243,7 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode)
633 for (p = rrs[0], i = 1; i < rr_found; i += 2)
634 {
635 unsigned char *start = rrs[i];
636 - unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)(header+1)) + plen;
637 + unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)header) + plen;
638
639 memmove(p, start, end-start);
640 p += end-start;
641 --
642 1.7.10.4
643