1 /*
2 * Copyright (C) 2004-2016 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /*! \file */
19
20 #include <config.h>
21
22 #include <isc/counter.h>
23 #include <isc/log.h>
24 #include <isc/platform.h>
25 #include <isc/print.h>
26 #include <isc/string.h>
27 #include <isc/random.h>
28 #include <isc/socket.h>
29 #include <isc/stats.h>
30 #include <isc/task.h>
31 #include <isc/timer.h>
32 #include <isc/util.h>
33
34 #include <dns/acl.h>
35 #include <dns/adb.h>
36 #include <dns/cache.h>
37 #include <dns/db.h>
38 #include <dns/dispatch.h>
39 #include <dns/ds.h>
40 #include <dns/events.h>
41 #include <dns/forward.h>
42 #include <dns/keytable.h>
43 #include <dns/log.h>
44 #include <dns/message.h>
45 #include <dns/ncache.h>
46 #include <dns/nsec.h>
47 #include <dns/nsec3.h>
48 #include <dns/opcode.h>
49 #include <dns/peer.h>
50 #include <dns/rbt.h>
51 #include <dns/rcode.h>
52 #include <dns/rdata.h>
53 #include <dns/rdataclass.h>
54 #include <dns/rdatalist.h>
55 #include <dns/rdataset.h>
56 #include <dns/rdatastruct.h>
57 #include <dns/rdatatype.h>
58 #include <dns/resolver.h>
59 #include <dns/result.h>
60 #include <dns/rootns.h>
61 #include <dns/stats.h>
62 #include <dns/tsig.h>
63 #include <dns/validator.h>
64
65 #ifdef WANT_QUERYTRACE
66 #define RTRACE(m) isc_log_write(dns_lctx, \
67 DNS_LOGCATEGORY_RESOLVER, \
68 DNS_LOGMODULE_RESOLVER, \
69 ISC_LOG_DEBUG(3), \
70 "res %p: %s", res, (m))
71 #define RRTRACE(r, m) isc_log_write(dns_lctx, \
72 DNS_LOGCATEGORY_RESOLVER, \
73 DNS_LOGMODULE_RESOLVER, \
74 ISC_LOG_DEBUG(3), \
75 "res %p: %s", (r), (m))
76 #define FCTXTRACE(m) \
77 isc_log_write(dns_lctx, \
78 DNS_LOGCATEGORY_RESOLVER, \
79 DNS_LOGMODULE_RESOLVER, \
80 ISC_LOG_DEBUG(3), \
81 "fctx %p(%s): %s", \
82 fctx, fctx->info, (m))
83 #define FCTXTRACE2(m1, m2) \
84 isc_log_write(dns_lctx, \
85 DNS_LOGCATEGORY_RESOLVER, \
86 DNS_LOGMODULE_RESOLVER, \
87 ISC_LOG_DEBUG(3), \
88 "fctx %p(%s): %s %s", \
89 fctx, fctx->info, (m1), (m2))
90 #define FCTXTRACE3(m, res) \
91 isc_log_write(dns_lctx, \
92 DNS_LOGCATEGORY_RESOLVER, \
93 DNS_LOGMODULE_RESOLVER, \
94 ISC_LOG_DEBUG(3), \
95 "fctx %p(%s): [result: %s] %s", \
96 fctx, fctx->info, \
97 isc_result_totext(res), (m))
98 #define FCTXTRACE4(m1, m2, res) \
99 isc_log_write(dns_lctx, \
100 DNS_LOGCATEGORY_RESOLVER, \
101 DNS_LOGMODULE_RESOLVER, \
102 ISC_LOG_DEBUG(3), \
103 "fctx %p(%s): [result: %s] %s %s", \
104 fctx, fctx->info, \
105 isc_result_totext(res), (m1), (m2))
106 #define FCTXTRACE5(m1, m2, v) \
107 isc_log_write(dns_lctx, \
108 DNS_LOGCATEGORY_RESOLVER, \
109 DNS_LOGMODULE_RESOLVER, \
110 ISC_LOG_DEBUG(3), \
111 "fctx %p(%s): %s %s%u", \
112 fctx, fctx->info, (m1), (m2), (v))
113 #define FTRACE(m) isc_log_write(dns_lctx, \
114 DNS_LOGCATEGORY_RESOLVER, \
115 DNS_LOGMODULE_RESOLVER, \
116 ISC_LOG_DEBUG(3), \
117 "fetch %p (fctx %p(%s)): %s", \
118 fetch, fetch->private, \
119 fetch->private->info, (m))
120 #define QTRACE(m) isc_log_write(dns_lctx, \
121 DNS_LOGCATEGORY_RESOLVER, \
122 DNS_LOGMODULE_RESOLVER, \
123 ISC_LOG_DEBUG(3), \
124 "resquery %p (fctx %p(%s)): %s", \
125 query, query->fctx, \
126 query->fctx->info, (m))
127 #else
128 #define RTRACE(m) do { UNUSED(m); } while (0)
129 #define RRTRACE(r, m) do { UNUSED(r); UNUSED(m); } while (0)
130 #define FCTXTRACE(m) do { UNUSED(m); } while (0)
131 #define FCTXTRACE2(m1, m2) do { UNUSED(m1); UNUSED(m2); } while (0)
132 #define FCTXTRACE3(m1, res) do { UNUSED(m1); UNUSED(res); } while (0)
133 #define FCTXTRACE4(m1, m2, res) \
134 do { UNUSED(m1); UNUSED(m2); UNUSED(res); } while (0)
135 #define FCTXTRACE5(m1, m2, v) \
136 do { UNUSED(m1); UNUSED(m2); UNUSED(v); } while (0)
137 #define FTRACE(m) do { UNUSED(m); } while (0)
138 #define QTRACE(m) do { UNUSED(m); } while (0)
139 #endif /* WANT_QUERYTRACE */
140
141 #define US_PER_SEC 1000000U
142 /*
143 * The maximum time we will wait for a single query.
144 */
145 #define MAX_SINGLE_QUERY_TIMEOUT 9U
146 #define MAX_SINGLE_QUERY_TIMEOUT_US (MAX_SINGLE_QUERY_TIMEOUT*US_PER_SEC)
147
148 /*
149 * We need to allow a individual query time to complete / timeout.
150 */
151 #define MINIMUM_QUERY_TIMEOUT (MAX_SINGLE_QUERY_TIMEOUT + 1U)
152
153 /* The default time in seconds for the whole query to live. */
154 #ifndef DEFAULT_QUERY_TIMEOUT
155 #define DEFAULT_QUERY_TIMEOUT MINIMUM_QUERY_TIMEOUT
156 #endif
157
158 /* The maximum time in seconds for the whole query to live. */
159 #ifndef MAXIMUM_QUERY_TIMEOUT
160 #define MAXIMUM_QUERY_TIMEOUT 30
161 #endif
162
163 /* The default maximum number of recursions to follow before giving up. */
164 #ifndef DEFAULT_RECURSION_DEPTH
165 #define DEFAULT_RECURSION_DEPTH 7
166 #endif
167
168 /* The default maximum number of iterative queries to allow before giving up. */
169 #ifndef DEFAULT_MAX_QUERIES
170 #define DEFAULT_MAX_QUERIES 50
171 #endif
172
173 /* Number of hash buckets for zone counters */
174 #ifndef RES_DOMAIN_BUCKETS
175 #define RES_DOMAIN_BUCKETS 523
176 #endif
177 #define RES_NOBUCKET 0xffffffff
178
179 /*%
180 * Maximum EDNS0 input packet size.
181 */
182 #define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
183
184 /*%
185 * This defines the maximum number of timeouts we will permit before we
186 * disable EDNS0 on the query.
187 */
188 #define MAX_EDNS0_TIMEOUTS 3
189
190 typedef struct fetchctx fetchctx_t;
191
192 typedef struct query {
193 /* Locked by task event serialization. */
194 unsigned int magic;
195 fetchctx_t * fctx;
196 isc_mem_t * mctx;
197 dns_dispatchmgr_t * dispatchmgr;
198 dns_dispatch_t * dispatch;
199 isc_boolean_t exclusivesocket;
200 dns_adbaddrinfo_t * addrinfo;
201 isc_socket_t * tcpsocket;
202 isc_time_t start;
203 dns_messageid_t id;
204 dns_dispentry_t * dispentry;
205 ISC_LINK(struct query) link;
206 isc_buffer_t buffer;
207 isc_buffer_t *tsig;
208 dns_tsigkey_t *tsigkey;
209 isc_socketevent_t sendevent;
210 int ednsversion;
211 unsigned int options;
212 unsigned int attributes;
213 unsigned int sends;
214 unsigned int connects;
215 unsigned char data[512];
216 } resquery_t;
217
218 #define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
219 #define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
220
221 #define RESQUERY_ATTR_CANCELED 0x02
222
223 #define RESQUERY_CONNECTING(q) ((q)->connects > 0)
224 #define RESQUERY_CANCELED(q) (((q)->attributes & \
225 RESQUERY_ATTR_CANCELED) != 0)
226 #define RESQUERY_SENDING(q) ((q)->sends > 0)
227
228 typedef enum {
229 fetchstate_init = 0, /*%< Start event has not run yet. */
230 fetchstate_active,
231 fetchstate_done /*%< FETCHDONE events posted. */
232 } fetchstate;
233
234 typedef enum {
235 badns_unreachable = 0,
236 badns_response,
237 badns_validation
238 } badnstype_t;
239
240 struct fetchctx {
241 /*% Not locked. */
242 unsigned int magic;
243 dns_resolver_t * res;
244 dns_name_t name;
245 dns_rdatatype_t type;
246 unsigned int options;
247 unsigned int bucketnum;
248 unsigned int dbucketnum;
249 char * info;
250 isc_mem_t * mctx;
251
252 /*% Locked by appropriate bucket lock. */
253 fetchstate state;
254 isc_boolean_t want_shutdown;
255 isc_boolean_t cloned;
256 isc_boolean_t spilled;
257 unsigned int references;
258 isc_event_t control_event;
259 ISC_LINK(struct fetchctx) link;
260 ISC_LIST(dns_fetchevent_t) events;
261 /*% Locked by task event serialization. */
262 dns_name_t domain;
263 dns_rdataset_t nameservers;
264 unsigned int attributes;
265 isc_timer_t * timer;
266 isc_time_t expires;
267 isc_interval_t interval;
268 dns_message_t * qmessage;
269 dns_message_t * rmessage;
270 ISC_LIST(resquery_t) queries;
271 dns_adbfindlist_t finds;
272 dns_adbfind_t * find;
273 dns_adbfindlist_t altfinds;
274 dns_adbfind_t * altfind;
275 dns_adbaddrinfolist_t forwaddrs;
276 dns_adbaddrinfolist_t altaddrs;
277 isc_sockaddrlist_t forwarders;
278 dns_fwdpolicy_t fwdpolicy;
279 isc_sockaddrlist_t bad;
280 isc_sockaddrlist_t edns;
281 isc_sockaddrlist_t edns512;
282 isc_sockaddrlist_t bad_edns;
283 dns_validator_t * validator;
284 ISC_LIST(dns_validator_t) validators;
285 dns_db_t * cache;
286 dns_adb_t * adb;
287 isc_boolean_t ns_ttl_ok;
288 isc_uint32_t ns_ttl;
289 isc_counter_t * qc;
290
291 /*%
292 * The number of events we're waiting for.
293 */
294 unsigned int pending;
295
296 /*%
297 * The number of times we've "restarted" the current
298 * nameserver set. This acts as a failsafe to prevent
299 * us from pounding constantly on a particular set of
300 * servers that, for whatever reason, are not giving
301 * us useful responses, but are responding in such a
302 * way that they are not marked "bad".
303 */
304 unsigned int restarts;
305
306 /*%
307 * The number of timeouts that have occurred since we
308 * last successfully received a response packet. This
309 * is used for EDNS0 black hole detection.
310 */
311 unsigned int timeouts;
312
313 /*%
314 * Look aside state for DS lookups.
315 */
316 dns_name_t nsname;
317 dns_fetch_t * nsfetch;
318 dns_rdataset_t nsrrset;
319
320 /*%
321 * Number of queries that reference this context.
322 */
323 unsigned int nqueries;
324
325 /*%
326 * The reason to print when logging a successful
327 * response to a query.
328 */
329 const char * reason;
330
331 /*%
332 * Random numbers to use for mixing up server addresses.
333 */
334 isc_uint32_t rand_buf;
335 isc_uint32_t rand_bits;
336
337 /*%
338 * Fetch-local statistics for detailed logging.
339 */
340 isc_result_t result; /*%< fetch result */
341 isc_result_t vresult; /*%< validation result */
342 int exitline;
343 isc_time_t start;
344 isc_uint64_t duration;
345 isc_boolean_t logged;
346 unsigned int querysent;
347 unsigned int referrals;
348 unsigned int lamecount;
349 unsigned int quotacount;
350 unsigned int neterr;
351 unsigned int badresp;
352 unsigned int adberr;
353 unsigned int findfail;
354 unsigned int valfail;
355 isc_boolean_t timeout;
356 dns_adbaddrinfo_t *addrinfo;
357 isc_sockaddr_t *client;
358 unsigned int depth;
359 };
360
361 #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
362 #define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
363
364 #define FCTX_ATTR_HAVEANSWER 0x0001
365 #define FCTX_ATTR_GLUING 0x0002
366 #define FCTX_ATTR_ADDRWAIT 0x0004
367 #define FCTX_ATTR_SHUTTINGDOWN 0x0008
368 #define FCTX_ATTR_WANTCACHE 0x0010
369 #define FCTX_ATTR_WANTNCACHE 0x0020
370 #define FCTX_ATTR_NEEDEDNS0 0x0040
371 #define FCTX_ATTR_TRIEDFIND 0x0080
372 #define FCTX_ATTR_TRIEDALT 0x0100
373
374 #define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
375 0)
376 #define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
377 0)
378 #define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
379 0)
380 #define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
381 != 0)
382 #define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
383 #define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
384 #define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
385 #define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
386 #define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
387
388 typedef struct {
389 dns_adbaddrinfo_t * addrinfo;
390 fetchctx_t * fctx;
391 } dns_valarg_t;
392
393 struct dns_fetch {
394 unsigned int magic;
395 isc_mem_t * mctx;
396 fetchctx_t * private;
397 };
398
399 #define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h')
400 #define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
401
402 typedef struct fctxbucket {
403 isc_task_t * task;
404 isc_mutex_t lock;
405 ISC_LIST(fetchctx_t) fctxs;
406 isc_boolean_t exiting;
407 isc_mem_t * mctx;
408 } fctxbucket_t;
409
410 #ifdef ENABLE_FETCHLIMIT
411 typedef struct fctxcount fctxcount_t;
412 struct fctxcount {
413 dns_fixedname_t fdname;
414 dns_name_t *domain;
415 isc_uint32_t count;
416 isc_uint32_t allowed;
417 isc_uint32_t dropped;
418 isc_stdtime_t logged;
419 ISC_LINK(fctxcount_t) link;
420 };
421
422 typedef struct zonebucket {
423 isc_mutex_t lock;
424 isc_mem_t *mctx;
425 ISC_LIST(fctxcount_t) list;
426 } zonebucket_t;
427 #endif /* ENABLE_FETCHLIMIT */
428
429 typedef struct alternate {
430 isc_boolean_t isaddress;
431 union {
432 isc_sockaddr_t addr;
433 struct {
434 dns_name_t name;
435 in_port_t port;
436 } _n;
437 } _u;
438 ISC_LINK(struct alternate) link;
439 } alternate_t;
440
441 typedef struct dns_badcache dns_badcache_t;
442 struct dns_badcache {
443 dns_badcache_t * next;
444 dns_rdatatype_t type;
445 isc_time_t expire;
446 unsigned int hashval;
447 dns_name_t name;
448 };
449 #define DNS_BADCACHE_SIZE 1021
450 #define DNS_BADCACHE_TTL(fctx) \
451 (((fctx)->res->lame_ttl > 30 ) ? (fctx)->res->lame_ttl : 30)
452
453 struct dns_resolver {
454 /* Unlocked. */
455 unsigned int magic;
456 isc_mem_t * mctx;
457 isc_mutex_t lock;
458 isc_mutex_t nlock;
459 isc_mutex_t primelock;
460 dns_rdataclass_t rdclass;
461 isc_socketmgr_t * socketmgr;
462 isc_timermgr_t * timermgr;
463 isc_taskmgr_t * taskmgr;
464 dns_view_t * view;
465 isc_boolean_t frozen;
466 unsigned int options;
467 dns_dispatchmgr_t * dispatchmgr;
468 dns_dispatchset_t * dispatches4;
469 isc_boolean_t exclusivev4;
470 dns_dispatchset_t * dispatches6;
471 isc_boolean_t exclusivev6;
472 unsigned int nbuckets;
473 fctxbucket_t * buckets;
474 #ifdef ENABLE_FETCHLIMIT
475 zonebucket_t * dbuckets;
476 #endif /* ENABLE_FETCHLIMIT */
477 isc_uint32_t lame_ttl;
478 ISC_LIST(alternate_t) alternates;
479 isc_uint16_t udpsize;
480 #if USE_ALGLOCK
481 isc_rwlock_t alglock;
482 #endif
483 dns_rbt_t * algorithms;
484 #if USE_MBSLOCK
485 isc_rwlock_t mbslock;
486 #endif
487 dns_rbt_t * mustbesecure;
488 unsigned int spillatmax;
489 unsigned int spillatmin;
490 isc_timer_t * spillattimer;
491 isc_boolean_t zero_no_soa_ttl;
492 unsigned int query_timeout;
493 unsigned int maxdepth;
494 unsigned int maxqueries;
495 isc_result_t quotaresp[2];
496
497 /* Locked by lock. */
498 unsigned int references;
499 isc_boolean_t exiting;
500 isc_eventlist_t whenshutdown;
501 unsigned int activebuckets;
502 isc_boolean_t priming;
503 unsigned int spillat; /* clients-per-query */
504 unsigned int zspill; /* fetches-per-zone */
505
506 /* Bad cache. */
507 dns_badcache_t ** badcache;
508 unsigned int badcount;
509 unsigned int badhash;
510 unsigned int badsweep;
511
512 /* Locked by primelock. */
513 dns_fetch_t * primefetch;
514 /* Locked by nlock. */
515 unsigned int nfctx;
516 };
517
518 #define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
519 #define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
520
521 /*%
522 * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0,
523 * which we also use as an addrinfo flag.
524 */
525 #define FCTX_ADDRINFO_MARK 0x0001
526 #define FCTX_ADDRINFO_FORWARDER 0x1000
527 #define FCTX_ADDRINFO_TRIED 0x2000
528 #define FCTX_ADDRINFO_EDNSOK 0x4000
529
530 #define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
531 == 0)
532 #define ISFORWARDER(a) (((a)->flags & \
533 FCTX_ADDRINFO_FORWARDER) != 0)
534 #define TRIED(a) (((a)->flags & \
535 FCTX_ADDRINFO_TRIED) != 0)
536 #define EDNSOK(a) (((a)->flags & \
537 FCTX_ADDRINFO_EDNSOK) != 0)
538
539 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
540 #define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
541
542 static void destroy(dns_resolver_t *res);
543 static void empty_bucket(dns_resolver_t *res);
544 static isc_result_t resquery_send(resquery_t *query);
545 static void resquery_response(isc_task_t *task, isc_event_t *event);
546 static void resquery_connected(isc_task_t *task, isc_event_t *event);
547 static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying,
548 isc_boolean_t badcache);
549 static void fctx_destroy(fetchctx_t *fctx);
550 static isc_boolean_t fctx_unlink(fetchctx_t *fctx);
551 static isc_result_t ncache_adderesult(dns_message_t *message,
552 dns_db_t *cache, dns_dbnode_t *node,
553 dns_rdatatype_t covers,
554 isc_stdtime_t now, dns_ttl_t maxttl,
555 isc_boolean_t optout,
556 isc_boolean_t secure,
557 dns_rdataset_t *ardataset,
558 isc_result_t *eresultp);
559 static void validated(isc_task_t *task, isc_event_t *event);
560 static isc_boolean_t maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked);
561 static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
562 isc_result_t reason, badnstype_t badtype);
563 static inline isc_result_t findnoqname(fetchctx_t *fctx, dns_name_t *name,
564 dns_rdatatype_t type,
565 dns_name_t **noqname);
566 static void fctx_increference(fetchctx_t *fctx);
567 static isc_boolean_t fctx_decreference(fetchctx_t *fctx);
568
569 /*%
570 * Increment resolver-related statistics counters.
571 */
572 static inline void
inc_stats(dns_resolver_t * res,isc_statscounter_t counter)573 inc_stats(dns_resolver_t *res, isc_statscounter_t counter) {
574 if (res->view->resstats != NULL)
575 isc_stats_increment(res->view->resstats, counter);
576 }
577
578 static isc_result_t
valcreate(fetchctx_t * fctx,dns_adbaddrinfo_t * addrinfo,dns_name_t * name,dns_rdatatype_t type,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset,unsigned int valoptions,isc_task_t * task)579 valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
580 dns_rdatatype_t type, dns_rdataset_t *rdataset,
581 dns_rdataset_t *sigrdataset, unsigned int valoptions,
582 isc_task_t *task)
583 {
584 dns_validator_t *validator = NULL;
585 dns_valarg_t *valarg;
586 isc_result_t result;
587
588 valarg = isc_mem_get(fctx->mctx, sizeof(*valarg));
589 if (valarg == NULL)
590 return (ISC_R_NOMEMORY);
591
592 valarg->fctx = fctx;
593 valarg->addrinfo = addrinfo;
594
595 if (!ISC_LIST_EMPTY(fctx->validators))
596 valoptions |= DNS_VALIDATOR_DEFER;
597 else
598 valoptions &= ~DNS_VALIDATOR_DEFER;
599
600 result = dns_validator_create(fctx->res->view, name, type, rdataset,
601 sigrdataset, fctx->rmessage,
602 valoptions, task, validated, valarg,
603 &validator);
604 if (result == ISC_R_SUCCESS) {
605 inc_stats(fctx->res, dns_resstatscounter_val);
606 if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
607 INSIST(fctx->validator == NULL);
608 fctx->validator = validator;
609 }
610 ISC_LIST_APPEND(fctx->validators, validator, link);
611 } else
612 isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
613 return (result);
614 }
615
616 static isc_boolean_t
rrsig_fromchildzone(fetchctx_t * fctx,dns_rdataset_t * rdataset)617 rrsig_fromchildzone(fetchctx_t *fctx, dns_rdataset_t *rdataset) {
618 dns_namereln_t namereln;
619 dns_rdata_rrsig_t rrsig;
620 dns_rdata_t rdata = DNS_RDATA_INIT;
621 int order;
622 isc_result_t result;
623 unsigned int labels;
624
625 for (result = dns_rdataset_first(rdataset);
626 result == ISC_R_SUCCESS;
627 result = dns_rdataset_next(rdataset)) {
628 dns_rdataset_current(rdataset, &rdata);
629 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
630 RUNTIME_CHECK(result == ISC_R_SUCCESS);
631 namereln = dns_name_fullcompare(&rrsig.signer, &fctx->domain,
632 &order, &labels);
633 if (namereln == dns_namereln_subdomain)
634 return (ISC_TRUE);
635 dns_rdata_reset(&rdata);
636 }
637 return (ISC_FALSE);
638 }
639
640 static isc_boolean_t
fix_mustbedelegationornxdomain(dns_message_t * message,fetchctx_t * fctx)641 fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
642 dns_name_t *name;
643 dns_name_t *domain = &fctx->domain;
644 dns_rdataset_t *rdataset;
645 dns_rdatatype_t type;
646 isc_result_t result;
647 isc_boolean_t keep_auth = ISC_FALSE;
648
649 if (message->rcode == dns_rcode_nxdomain)
650 return (ISC_FALSE);
651
652 /*
653 * A DS RRset can appear anywhere in a zone, even for a delegation-only
654 * zone. So a response to an explicit query for this type should be
655 * excluded from delegation-only fixup.
656 *
657 * SOA, NS, and DNSKEY can only exist at a zone apex, so a postive
658 * response to a query for these types can never violate the
659 * delegation-only assumption: if the query name is below a
660 * zone cut, the response should normally be a referral, which should
661 * be accepted; if the query name is below a zone cut but the server
662 * happens to have authority for the zone of the query name, the
663 * response is a (non-referral) answer. But this does not violate
664 * delegation-only because the query name must be in a different zone
665 * due to the "apex-only" nature of these types. Note that if the
666 * remote server happens to have authority for a child zone of a
667 * delegation-only zone, we may still incorrectly "fix" the response
668 * with NXDOMAIN for queries for other types. Unfortunately it's
669 * generally impossible to differentiate this case from violation of
670 * the delegation-only assumption. Once the resolver learns the
671 * correct zone cut, possibly via a separate query for an "apex-only"
672 * type, queries for other types will be resolved correctly.
673 *
674 * A query for type ANY will be accepted if it hits an exceptional
675 * type above in the answer section as it should be from a child
676 * zone.
677 *
678 * Also accept answers with RRSIG records from the child zone.
679 * Direct queries for RRSIG records should not be answered from
680 * the parent zone.
681 */
682
683 if (message->counts[DNS_SECTION_ANSWER] != 0 &&
684 (fctx->type == dns_rdatatype_ns ||
685 fctx->type == dns_rdatatype_ds ||
686 fctx->type == dns_rdatatype_soa ||
687 fctx->type == dns_rdatatype_any ||
688 fctx->type == dns_rdatatype_rrsig ||
689 fctx->type == dns_rdatatype_dnskey)) {
690 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
691 while (result == ISC_R_SUCCESS) {
692 name = NULL;
693 dns_message_currentname(message, DNS_SECTION_ANSWER,
694 &name);
695 for (rdataset = ISC_LIST_HEAD(name->list);
696 rdataset != NULL;
697 rdataset = ISC_LIST_NEXT(rdataset, link)) {
698 if (!dns_name_equal(name, &fctx->name))
699 continue;
700 type = rdataset->type;
701 /*
702 * RRsig from child?
703 */
704 if (type == dns_rdatatype_rrsig &&
705 rrsig_fromchildzone(fctx, rdataset))
706 return (ISC_FALSE);
707 /*
708 * Direct query for apex records or DS.
709 */
710 if (fctx->type == type &&
711 (type == dns_rdatatype_ds ||
712 type == dns_rdatatype_ns ||
713 type == dns_rdatatype_soa ||
714 type == dns_rdatatype_dnskey))
715 return (ISC_FALSE);
716 /*
717 * Indirect query for apex records or DS.
718 */
719 if (fctx->type == dns_rdatatype_any &&
720 (type == dns_rdatatype_ns ||
721 type == dns_rdatatype_ds ||
722 type == dns_rdatatype_soa ||
723 type == dns_rdatatype_dnskey))
724 return (ISC_FALSE);
725 }
726 result = dns_message_nextname(message,
727 DNS_SECTION_ANSWER);
728 }
729 }
730
731 /*
732 * A NODATA response to a DS query?
733 */
734 if (fctx->type == dns_rdatatype_ds &&
735 message->counts[DNS_SECTION_ANSWER] == 0)
736 return (ISC_FALSE);
737
738 /* Look for referral or indication of answer from child zone? */
739 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
740 goto munge;
741
742 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
743 while (result == ISC_R_SUCCESS) {
744 name = NULL;
745 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
746 for (rdataset = ISC_LIST_HEAD(name->list);
747 rdataset != NULL;
748 rdataset = ISC_LIST_NEXT(rdataset, link)) {
749 type = rdataset->type;
750 if (type == dns_rdatatype_soa &&
751 dns_name_equal(name, domain))
752 keep_auth = ISC_TRUE;
753
754 if (type != dns_rdatatype_ns &&
755 type != dns_rdatatype_soa &&
756 type != dns_rdatatype_rrsig)
757 continue;
758
759 if (type == dns_rdatatype_rrsig) {
760 if (rrsig_fromchildzone(fctx, rdataset))
761 return (ISC_FALSE);
762 else
763 continue;
764 }
765
766 /* NS or SOA records. */
767 if (dns_name_equal(name, domain)) {
768 /*
769 * If a query for ANY causes a negative
770 * response, we can be sure that this is
771 * an empty node. For other type of queries
772 * we cannot differentiate an empty node
773 * from a node that just doesn't have that
774 * type of record. We only accept the former
775 * case.
776 */
777 if (message->counts[DNS_SECTION_ANSWER] == 0 &&
778 fctx->type == dns_rdatatype_any)
779 return (ISC_FALSE);
780 } else if (dns_name_issubdomain(name, domain)) {
781 /* Referral or answer from child zone. */
782 return (ISC_FALSE);
783 }
784 }
785 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
786 }
787
788 munge:
789 message->rcode = dns_rcode_nxdomain;
790 message->counts[DNS_SECTION_ANSWER] = 0;
791 if (!keep_auth)
792 message->counts[DNS_SECTION_AUTHORITY] = 0;
793 message->counts[DNS_SECTION_ADDITIONAL] = 0;
794 return (ISC_TRUE);
795 }
796
797 static inline isc_result_t
fctx_starttimer(fetchctx_t * fctx)798 fctx_starttimer(fetchctx_t *fctx) {
799 /*
800 * Start the lifetime timer for fctx.
801 *
802 * This is also used for stopping the idle timer; in that
803 * case we must purge events already posted to ensure that
804 * no further idle events are delivered.
805 */
806 return (isc_timer_reset(fctx->timer, isc_timertype_once,
807 &fctx->expires, NULL, ISC_TRUE));
808 }
809
810 static inline void
fctx_stoptimer(fetchctx_t * fctx)811 fctx_stoptimer(fetchctx_t *fctx) {
812 isc_result_t result;
813
814 /*
815 * We don't return a result if resetting the timer to inactive fails
816 * since there's nothing to be done about it. Resetting to inactive
817 * should never fail anyway, since the code as currently written
818 * cannot fail in that case.
819 */
820 result = isc_timer_reset(fctx->timer, isc_timertype_inactive,
821 NULL, NULL, ISC_TRUE);
822 if (result != ISC_R_SUCCESS) {
823 UNEXPECTED_ERROR(__FILE__, __LINE__,
824 "isc_timer_reset(): %s",
825 isc_result_totext(result));
826 }
827 }
828
829
830 static inline isc_result_t
fctx_startidletimer(fetchctx_t * fctx,isc_interval_t * interval)831 fctx_startidletimer(fetchctx_t *fctx, isc_interval_t *interval) {
832 /*
833 * Start the idle timer for fctx. The lifetime timer continues
834 * to be in effect.
835 */
836 return (isc_timer_reset(fctx->timer, isc_timertype_once,
837 &fctx->expires, interval, ISC_FALSE));
838 }
839
840 /*
841 * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
842 * we use fctx_stopidletimer for readability in the code below.
843 */
844 #define fctx_stopidletimer fctx_starttimer
845
846 static inline void
resquery_destroy(resquery_t ** queryp)847 resquery_destroy(resquery_t **queryp) {
848 dns_resolver_t *res;
849 isc_boolean_t empty;
850 resquery_t *query;
851 fetchctx_t *fctx;
852 unsigned int bucket;
853
854 REQUIRE(queryp != NULL);
855 query = *queryp;
856 REQUIRE(!ISC_LINK_LINKED(query, link));
857
858 INSIST(query->tcpsocket == NULL);
859
860 fctx = query->fctx;
861 res = fctx->res;
862 bucket = fctx->bucketnum;
863
864 fctx->nqueries--;
865
866 LOCK(&res->buckets[bucket].lock);
867 empty = fctx_decreference(query->fctx);
868 UNLOCK(&res->buckets[bucket].lock);
869
870 query->magic = 0;
871 isc_mem_put(query->mctx, query, sizeof(*query));
872 *queryp = NULL;
873
874 if (empty)
875 empty_bucket(res);
876 }
877
878 static void
fctx_cancelquery(resquery_t ** queryp,dns_dispatchevent_t ** deventp,isc_time_t * finish,isc_boolean_t no_response,isc_boolean_t age_untried)879 fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
880 isc_time_t *finish, isc_boolean_t no_response,
881 isc_boolean_t age_untried)
882 {
883 fetchctx_t *fctx;
884 resquery_t *query;
885 unsigned int rtt, rttms;
886 unsigned int factor;
887 dns_adbfind_t *find;
888 dns_adbaddrinfo_t *addrinfo;
889 isc_socket_t *sock;
890 isc_stdtime_t now;
891
892 query = *queryp;
893 fctx = query->fctx;
894
895 FCTXTRACE("cancelquery");
896
897 REQUIRE(!RESQUERY_CANCELED(query));
898
899 query->attributes |= RESQUERY_ATTR_CANCELED;
900
901 /*
902 * Should we update the RTT?
903 */
904 if (finish != NULL || no_response) {
905 if (finish != NULL) {
906 /*
907 * We have both the start and finish times for this
908 * packet, so we can compute a real RTT.
909 */
910 rtt = (unsigned int)isc_time_microdiff(finish,
911 &query->start);
912 factor = DNS_ADB_RTTADJDEFAULT;
913
914 rttms = rtt / 1000;
915 if (rttms < DNS_RESOLVER_QRYRTTCLASS0) {
916 inc_stats(fctx->res,
917 dns_resstatscounter_queryrtt0);
918 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS1) {
919 inc_stats(fctx->res,
920 dns_resstatscounter_queryrtt1);
921 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS2) {
922 inc_stats(fctx->res,
923 dns_resstatscounter_queryrtt2);
924 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS3) {
925 inc_stats(fctx->res,
926 dns_resstatscounter_queryrtt3);
927 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS4) {
928 inc_stats(fctx->res,
929 dns_resstatscounter_queryrtt4);
930 } else {
931 inc_stats(fctx->res,
932 dns_resstatscounter_queryrtt5);
933 }
934 } else {
935 /*
936 * We don't have an RTT for this query. Maybe the
937 * packet was lost, or maybe this server is very
938 * slow. We don't know. Increase the RTT.
939 */
940 INSIST(no_response);
941 rtt = query->addrinfo->srtt + 200000;
942 if (rtt > MAX_SINGLE_QUERY_TIMEOUT_US)
943 rtt = MAX_SINGLE_QUERY_TIMEOUT_US;
944
945 /*
946 * Replace the current RTT with our value.
947 */
948 factor = DNS_ADB_RTTADJREPLACE;
949 dns_adb_timeout(fctx->adb, query->addrinfo);
950 }
951
952 dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
953 }
954
955 #ifdef ENABLE_FETCHLIMIT
956 dns_adb_endudpfetch(fctx->adb, query->addrinfo);
957 #endif /* ENABLE_FETCHLIMIT */
958
959 /*
960 * Age RTTs of servers not tried.
961 */
962 isc_stdtime_get(&now);
963 if (finish != NULL || age_untried)
964 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
965 addrinfo != NULL;
966 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
967 if (UNMARKED(addrinfo))
968 dns_adb_agesrtt(fctx->adb, addrinfo, now);
969
970 if ((finish != NULL || age_untried) && TRIEDFIND(fctx))
971 for (find = ISC_LIST_HEAD(fctx->finds);
972 find != NULL;
973 find = ISC_LIST_NEXT(find, publink))
974 for (addrinfo = ISC_LIST_HEAD(find->list);
975 addrinfo != NULL;
976 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
977 if (UNMARKED(addrinfo))
978 dns_adb_agesrtt(fctx->adb, addrinfo,
979 now);
980
981 if ((finish != NULL || age_untried) && TRIEDALT(fctx)) {
982 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
983 addrinfo != NULL;
984 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
985 if (UNMARKED(addrinfo))
986 dns_adb_agesrtt(fctx->adb, addrinfo, now);
987 for (find = ISC_LIST_HEAD(fctx->altfinds);
988 find != NULL;
989 find = ISC_LIST_NEXT(find, publink))
990 for (addrinfo = ISC_LIST_HEAD(find->list);
991 addrinfo != NULL;
992 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
993 if (UNMARKED(addrinfo))
994 dns_adb_agesrtt(fctx->adb, addrinfo,
995 now);
996 }
997
998 /*
999 * Check for any outstanding socket events. If they exist, cancel
1000 * them and let the event handlers finish the cleanup. The resolver
1001 * only needs to worry about managing the connect and send events;
1002 * the dispatcher manages the recv events.
1003 */
1004 if (RESQUERY_CONNECTING(query)) {
1005 /*
1006 * Cancel the connect.
1007 */
1008 if (query->tcpsocket != NULL) {
1009 isc_socket_cancel(query->tcpsocket, NULL,
1010 ISC_SOCKCANCEL_CONNECT);
1011 } else if (query->dispentry != NULL) {
1012 INSIST(query->exclusivesocket);
1013 sock = dns_dispatch_getentrysocket(query->dispentry);
1014 if (sock != NULL)
1015 isc_socket_cancel(sock, NULL,
1016 ISC_SOCKCANCEL_CONNECT);
1017 }
1018 } else if (RESQUERY_SENDING(query)) {
1019 /*
1020 * Cancel the pending send.
1021 */
1022 if (query->exclusivesocket && query->dispentry != NULL)
1023 sock = dns_dispatch_getentrysocket(query->dispentry);
1024 else
1025 sock = dns_dispatch_getsocket(query->dispatch);
1026 if (sock != NULL)
1027 isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_SEND);
1028 }
1029
1030 if (query->dispentry != NULL)
1031 dns_dispatch_removeresponse(&query->dispentry, deventp);
1032
1033 ISC_LIST_UNLINK(fctx->queries, query, link);
1034
1035 if (query->tsig != NULL)
1036 isc_buffer_free(&query->tsig);
1037
1038 if (query->tsigkey != NULL)
1039 dns_tsigkey_detach(&query->tsigkey);
1040
1041 if (query->dispatch != NULL)
1042 dns_dispatch_detach(&query->dispatch);
1043
1044 if (! (RESQUERY_CONNECTING(query) || RESQUERY_SENDING(query)))
1045 /*
1046 * It's safe to destroy the query now.
1047 */
1048 resquery_destroy(&query);
1049 }
1050
1051 static void
fctx_cancelqueries(fetchctx_t * fctx,isc_boolean_t no_response,isc_boolean_t age_untried)1052 fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response,
1053 isc_boolean_t age_untried)
1054 {
1055 resquery_t *query, *next_query;
1056
1057 FCTXTRACE("cancelqueries");
1058
1059 for (query = ISC_LIST_HEAD(fctx->queries);
1060 query != NULL;
1061 query = next_query) {
1062 next_query = ISC_LIST_NEXT(query, link);
1063 fctx_cancelquery(&query, NULL, NULL, no_response,
1064 age_untried);
1065 }
1066 }
1067
1068 static void
fctx_cleanupfinds(fetchctx_t * fctx)1069 fctx_cleanupfinds(fetchctx_t *fctx) {
1070 dns_adbfind_t *find, *next_find;
1071
1072 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
1073
1074 for (find = ISC_LIST_HEAD(fctx->finds);
1075 find != NULL;
1076 find = next_find) {
1077 next_find = ISC_LIST_NEXT(find, publink);
1078 ISC_LIST_UNLINK(fctx->finds, find, publink);
1079 dns_adb_destroyfind(&find);
1080 }
1081 fctx->find = NULL;
1082 }
1083
1084 static void
fctx_cleanupaltfinds(fetchctx_t * fctx)1085 fctx_cleanupaltfinds(fetchctx_t *fctx) {
1086 dns_adbfind_t *find, *next_find;
1087
1088 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
1089
1090 for (find = ISC_LIST_HEAD(fctx->altfinds);
1091 find != NULL;
1092 find = next_find) {
1093 next_find = ISC_LIST_NEXT(find, publink);
1094 ISC_LIST_UNLINK(fctx->altfinds, find, publink);
1095 dns_adb_destroyfind(&find);
1096 }
1097 fctx->altfind = NULL;
1098 }
1099
1100 static void
fctx_cleanupforwaddrs(fetchctx_t * fctx)1101 fctx_cleanupforwaddrs(fetchctx_t *fctx) {
1102 dns_adbaddrinfo_t *addr, *next_addr;
1103
1104 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
1105
1106 for (addr = ISC_LIST_HEAD(fctx->forwaddrs);
1107 addr != NULL;
1108 addr = next_addr) {
1109 next_addr = ISC_LIST_NEXT(addr, publink);
1110 ISC_LIST_UNLINK(fctx->forwaddrs, addr, publink);
1111 dns_adb_freeaddrinfo(fctx->adb, &addr);
1112 }
1113 }
1114
1115 static void
fctx_cleanupaltaddrs(fetchctx_t * fctx)1116 fctx_cleanupaltaddrs(fetchctx_t *fctx) {
1117 dns_adbaddrinfo_t *addr, *next_addr;
1118
1119 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
1120
1121 for (addr = ISC_LIST_HEAD(fctx->altaddrs);
1122 addr != NULL;
1123 addr = next_addr) {
1124 next_addr = ISC_LIST_NEXT(addr, publink);
1125 ISC_LIST_UNLINK(fctx->altaddrs, addr, publink);
1126 dns_adb_freeaddrinfo(fctx->adb, &addr);
1127 }
1128 }
1129
1130 static inline void
fctx_stopeverything(fetchctx_t * fctx,isc_boolean_t no_response,isc_boolean_t age_untried)1131 fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response,
1132 isc_boolean_t age_untried)
1133 {
1134 FCTXTRACE("stopeverything");
1135 fctx_cancelqueries(fctx, no_response, age_untried);
1136 fctx_cleanupfinds(fctx);
1137 fctx_cleanupaltfinds(fctx);
1138 fctx_cleanupforwaddrs(fctx);
1139 fctx_cleanupaltaddrs(fctx);
1140 fctx_stoptimer(fctx);
1141 }
1142
1143 #ifdef ENABLE_FETCHLIMIT
1144 static void
fcount_logspill(fetchctx_t * fctx,fctxcount_t * counter)1145 fcount_logspill(fetchctx_t *fctx, fctxcount_t *counter) {
1146 char dbuf[DNS_NAME_FORMATSIZE];
1147 isc_stdtime_t now;
1148
1149 if (! isc_log_wouldlog(dns_lctx, ISC_LOG_INFO))
1150 return;
1151
1152 isc_stdtime_get(&now);
1153 if (counter->logged > now - 60)
1154 return;
1155
1156 dns_name_format(&fctx->domain, dbuf, sizeof(dbuf));
1157
1158 isc_log_write(dns_lctx, DNS_LOGCATEGORY_SPILL,
1159 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
1160 "too many simultaneous fetches for %s "
1161 "(allowed %d spilled %d)",
1162 dbuf, counter->allowed, counter->dropped);
1163
1164 counter->logged = now;
1165 }
1166
1167 static isc_result_t
fcount_incr(fetchctx_t * fctx,isc_boolean_t force)1168 fcount_incr(fetchctx_t *fctx, isc_boolean_t force) {
1169 isc_result_t result = ISC_R_SUCCESS;
1170 zonebucket_t *dbucket;
1171 fctxcount_t *counter;
1172 unsigned int bucketnum, spill;
1173
1174 REQUIRE(fctx != NULL);
1175 REQUIRE(fctx->res != NULL);
1176
1177 INSIST(fctx->dbucketnum == RES_NOBUCKET);
1178 bucketnum = dns_name_fullhash(&fctx->domain, ISC_FALSE)
1179 % RES_DOMAIN_BUCKETS;
1180
1181 LOCK(&fctx->res->lock);
1182 spill = fctx->res->zspill;
1183 UNLOCK(&fctx->res->lock);
1184
1185 dbucket = &fctx->res->dbuckets[bucketnum];
1186
1187 LOCK(&dbucket->lock);
1188 for (counter = ISC_LIST_HEAD(dbucket->list);
1189 counter != NULL;
1190 counter = ISC_LIST_NEXT(counter, link))
1191 {
1192 if (dns_name_equal(counter->domain, &fctx->domain))
1193 break;
1194 }
1195
1196 if (counter == NULL) {
1197 counter = isc_mem_get(dbucket->mctx, sizeof(fctxcount_t));
1198 if (counter == NULL)
1199 result = ISC_R_NOMEMORY;
1200 else {
1201 ISC_LINK_INIT(counter, link);
1202 counter->count = 1;
1203 counter->logged = 0;
1204 counter->allowed = 1;
1205 counter->dropped = 0;
1206 dns_fixedname_init(&counter->fdname);
1207 counter->domain = dns_fixedname_name(&counter->fdname);
1208 dns_name_copy(&fctx->domain, counter->domain, NULL);
1209 ISC_LIST_APPEND(dbucket->list, counter, link);
1210 }
1211 } else {
1212 if (!force && spill != 0 && counter->count >= spill) {
1213 counter->dropped++;
1214 fcount_logspill(fctx, counter);
1215 result = ISC_R_QUOTA;
1216 } else {
1217 counter->count++;
1218 counter->allowed++;
1219 }
1220 }
1221 UNLOCK(&dbucket->lock);
1222
1223 if (result == ISC_R_SUCCESS)
1224 fctx->dbucketnum = bucketnum;
1225
1226 return (result);
1227 }
1228
1229 static void
fcount_decr(fetchctx_t * fctx)1230 fcount_decr(fetchctx_t *fctx) {
1231 zonebucket_t *dbucket;
1232 fctxcount_t *counter;
1233
1234 REQUIRE(fctx != NULL);
1235
1236 if (fctx->dbucketnum == RES_NOBUCKET)
1237 return;
1238
1239 dbucket = &fctx->res->dbuckets[fctx->dbucketnum];
1240
1241 LOCK(&dbucket->lock);
1242 for (counter = ISC_LIST_HEAD(dbucket->list);
1243 counter != NULL;
1244 counter = ISC_LIST_NEXT(counter, link))
1245 {
1246 if (dns_name_equal(counter->domain, &fctx->domain))
1247 break;
1248 }
1249
1250 if (counter != NULL) {
1251 INSIST(counter->count != 0);
1252 counter->count--;
1253 fctx->dbucketnum = RES_NOBUCKET;
1254
1255 if (counter->count == 0) {
1256 ISC_LIST_UNLINK(dbucket->list, counter, link);
1257 isc_mem_put(dbucket->mctx, counter, sizeof(*counter));
1258 }
1259 }
1260
1261 UNLOCK(&dbucket->lock);
1262 }
1263 #endif /* ENABLE_FETCHLIMIT */
1264
1265 static inline void
fctx_sendevents(fetchctx_t * fctx,isc_result_t result,int line)1266 fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) {
1267 dns_fetchevent_t *event, *next_event;
1268 isc_task_t *task;
1269 unsigned int count = 0;
1270 isc_interval_t i;
1271 isc_boolean_t logit = ISC_FALSE;
1272 isc_time_t now;
1273 unsigned int old_spillat;
1274 unsigned int new_spillat = 0; /* initialized to silence
1275 compiler warnings */
1276
1277 /*
1278 * Caller must be holding the appropriate bucket lock.
1279 */
1280 REQUIRE(fctx->state == fetchstate_done);
1281
1282 FCTXTRACE("sendevents");
1283
1284 /*
1285 * Keep some record of fetch result for logging later (if required).
1286 */
1287 fctx->result = result;
1288 fctx->exitline = line;
1289 TIME_NOW(&now);
1290 fctx->duration = isc_time_microdiff(&now, &fctx->start);
1291
1292 for (event = ISC_LIST_HEAD(fctx->events);
1293 event != NULL;
1294 event = next_event) {
1295 next_event = ISC_LIST_NEXT(event, ev_link);
1296 ISC_LIST_UNLINK(fctx->events, event, ev_link);
1297 task = event->ev_sender;
1298 event->ev_sender = fctx;
1299 event->vresult = fctx->vresult;
1300 if (!HAVE_ANSWER(fctx))
1301 event->result = result;
1302
1303 INSIST(result != ISC_R_SUCCESS ||
1304 dns_rdataset_isassociated(event->rdataset) ||
1305 fctx->type == dns_rdatatype_any ||
1306 fctx->type == dns_rdatatype_rrsig ||
1307 fctx->type == dns_rdatatype_sig);
1308
1309 /*
1310 * Negative results must be indicated in event->result.
1311 */
1312 if (dns_rdataset_isassociated(event->rdataset) &&
1313 NEGATIVE(event->rdataset)) {
1314 INSIST(event->result == DNS_R_NCACHENXDOMAIN ||
1315 event->result == DNS_R_NCACHENXRRSET);
1316 }
1317
1318 isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
1319 count++;
1320 }
1321
1322 if ((fctx->attributes & FCTX_ATTR_HAVEANSWER) != 0 &&
1323 fctx->spilled &&
1324 (count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
1325 LOCK(&fctx->res->lock);
1326 if (count == fctx->res->spillat && !fctx->res->exiting) {
1327 old_spillat = fctx->res->spillat;
1328 fctx->res->spillat += 5;
1329 if (fctx->res->spillat > fctx->res->spillatmax &&
1330 fctx->res->spillatmax != 0)
1331 fctx->res->spillat = fctx->res->spillatmax;
1332 new_spillat = fctx->res->spillat;
1333 if (new_spillat != old_spillat) {
1334 logit = ISC_TRUE;
1335 }
1336 isc_interval_set(&i, 20 * 60, 0);
1337 result = isc_timer_reset(fctx->res->spillattimer,
1338 isc_timertype_ticker, NULL,
1339 &i, ISC_TRUE);
1340 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1341 }
1342 UNLOCK(&fctx->res->lock);
1343 if (logit)
1344 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
1345 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
1346 "clients-per-query increased to %u",
1347 new_spillat);
1348 }
1349 }
1350
1351 static inline void
log_edns(fetchctx_t * fctx)1352 log_edns(fetchctx_t *fctx) {
1353 char domainbuf[DNS_NAME_FORMATSIZE];
1354
1355 if (fctx->reason == NULL)
1356 return;
1357
1358 /*
1359 * We do not know if fctx->domain is the actual domain the record
1360 * lives in or a parent domain so we have a '?' after it.
1361 */
1362 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
1363 isc_log_write(dns_lctx, DNS_LOGCATEGORY_EDNS_DISABLED,
1364 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
1365 "success resolving '%s' (in '%s'?) after %s",
1366 fctx->info, domainbuf, fctx->reason);
1367
1368 fctx->reason = NULL;
1369 }
1370
1371 static void
fctx_done(fetchctx_t * fctx,isc_result_t result,int line)1372 fctx_done(fetchctx_t *fctx, isc_result_t result, int line) {
1373 dns_resolver_t *res;
1374 isc_boolean_t no_response = ISC_FALSE;
1375 isc_boolean_t age_untried = ISC_FALSE;
1376
1377 REQUIRE(line >= 0);
1378
1379 FCTXTRACE("done");
1380
1381 res = fctx->res;
1382
1383 if (result == ISC_R_SUCCESS) {
1384 /*%
1385 * Log any deferred EDNS timeout messages.
1386 */
1387 log_edns(fctx);
1388 no_response = ISC_TRUE;
1389 } else if (result == ISC_R_TIMEDOUT)
1390 age_untried = ISC_TRUE;
1391
1392 fctx->reason = NULL;
1393 fctx_stopeverything(fctx, no_response, age_untried);
1394
1395 LOCK(&res->buckets[fctx->bucketnum].lock);
1396
1397 fctx->state = fetchstate_done;
1398 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1399 fctx_sendevents(fctx, result, line);
1400
1401 UNLOCK(&res->buckets[fctx->bucketnum].lock);
1402 }
1403
1404 static void
process_sendevent(resquery_t * query,isc_event_t * event)1405 process_sendevent(resquery_t *query, isc_event_t *event) {
1406 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1407 isc_boolean_t destroy_query = ISC_FALSE;
1408 isc_boolean_t retry = ISC_FALSE;
1409 isc_result_t result;
1410 fetchctx_t *fctx;
1411
1412 fctx = query->fctx;
1413
1414 if (RESQUERY_CANCELED(query)) {
1415 if (query->sends == 0 && query->connects == 0) {
1416 /*
1417 * This query was canceled while the
1418 * isc_socket_sendto/connect() was in progress.
1419 */
1420 if (query->tcpsocket != NULL)
1421 isc_socket_detach(&query->tcpsocket);
1422 destroy_query = ISC_TRUE;
1423 }
1424 } else {
1425 switch (sevent->result) {
1426 case ISC_R_SUCCESS:
1427 break;
1428
1429 case ISC_R_HOSTUNREACH:
1430 case ISC_R_NETUNREACH:
1431 case ISC_R_NOPERM:
1432 case ISC_R_ADDRNOTAVAIL:
1433 case ISC_R_CONNREFUSED:
1434 FCTXTRACE3("query canceled in sendevent(): "
1435 "no route to host; no response",
1436 sevent->result);
1437
1438 /*
1439 * No route to remote.
1440 */
1441 add_bad(fctx, query->addrinfo, sevent->result,
1442 badns_unreachable);
1443 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE,
1444 ISC_FALSE);
1445 retry = ISC_TRUE;
1446 break;
1447
1448 default:
1449 FCTXTRACE3("query canceled in sendevent() due to "
1450 "unexpected event result; responding",
1451 sevent->result);
1452
1453 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE,
1454 ISC_FALSE);
1455 break;
1456 }
1457 }
1458
1459 if (event->ev_type == ISC_SOCKEVENT_CONNECT)
1460 isc_event_free(&event);
1461
1462 if (retry) {
1463 /*
1464 * Behave as if the idle timer has expired. For TCP
1465 * this may not actually reflect the latest timer.
1466 */
1467 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1468 result = fctx_stopidletimer(fctx);
1469 if (result != ISC_R_SUCCESS)
1470 fctx_done(fctx, result, __LINE__);
1471 else
1472 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
1473 }
1474
1475 if (destroy_query)
1476 resquery_destroy(&query);
1477 }
1478
1479 static void
resquery_udpconnected(isc_task_t * task,isc_event_t * event)1480 resquery_udpconnected(isc_task_t *task, isc_event_t *event) {
1481 resquery_t *query = event->ev_arg;
1482
1483 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
1484
1485 QTRACE("udpconnected");
1486
1487 UNUSED(task);
1488
1489 INSIST(RESQUERY_CONNECTING(query));
1490
1491 query->connects--;
1492
1493 process_sendevent(query, event);
1494 }
1495
1496 static void
resquery_senddone(isc_task_t * task,isc_event_t * event)1497 resquery_senddone(isc_task_t *task, isc_event_t *event) {
1498 resquery_t *query = event->ev_arg;
1499
1500 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1501
1502 QTRACE("senddone");
1503
1504 /*
1505 * XXXRTH
1506 *
1507 * Currently we don't wait for the senddone event before retrying
1508 * a query. This means that if we get really behind, we may end
1509 * up doing extra work!
1510 */
1511
1512 UNUSED(task);
1513
1514 INSIST(RESQUERY_SENDING(query));
1515
1516 query->sends--;
1517
1518 process_sendevent(query, event);
1519 }
1520
1521 static inline isc_result_t
fctx_addopt(dns_message_t * message,unsigned int version,isc_uint16_t udpsize,dns_ednsopt_t * ednsopts,size_t count)1522 fctx_addopt(dns_message_t *message, unsigned int version,
1523 isc_uint16_t udpsize, dns_ednsopt_t *ednsopts, size_t count)
1524 {
1525 dns_rdataset_t *rdataset = NULL;
1526 isc_result_t result;
1527
1528 result = dns_message_buildopt(message, &rdataset, version, udpsize,
1529 DNS_MESSAGEEXTFLAG_DO, ednsopts, count);
1530 if (result != ISC_R_SUCCESS)
1531 return (result);
1532 return (dns_message_setopt(message, rdataset));
1533 }
1534
1535 static inline void
fctx_setretryinterval(fetchctx_t * fctx,unsigned int rtt)1536 fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
1537 unsigned int seconds;
1538 unsigned int us;
1539
1540 /*
1541 * We retry every .8 seconds the first two times through the address
1542 * list, and then we do exponential back-off.
1543 */
1544 if (fctx->restarts < 3)
1545 us = 800000;
1546 else
1547 us = (800000 << (fctx->restarts - 2));
1548
1549 /*
1550 * Add a fudge factor to the expected rtt based on the current
1551 * estimate.
1552 */
1553 if (rtt < 50000)
1554 rtt += 50000;
1555 else if (rtt < 100000)
1556 rtt += 100000;
1557 else
1558 rtt += 200000;
1559
1560 /*
1561 * Always wait for at least the expected rtt.
1562 */
1563 if (us < rtt)
1564 us = rtt;
1565
1566 /*
1567 * But don't ever wait for more than 10 seconds.
1568 */
1569 if (us > MAX_SINGLE_QUERY_TIMEOUT_US)
1570 us = MAX_SINGLE_QUERY_TIMEOUT_US;
1571
1572 seconds = us / US_PER_SEC;
1573 us -= seconds * US_PER_SEC;
1574 isc_interval_set(&fctx->interval, seconds, us * 1000);
1575 }
1576
1577 static isc_result_t
fctx_query(fetchctx_t * fctx,dns_adbaddrinfo_t * addrinfo,unsigned int options)1578 fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
1579 unsigned int options)
1580 {
1581 dns_resolver_t *res;
1582 isc_task_t *task;
1583 isc_result_t result;
1584 resquery_t *query;
1585 isc_sockaddr_t addr;
1586 isc_boolean_t have_addr = ISC_FALSE;
1587 unsigned int srtt;
1588
1589 FCTXTRACE("query");
1590
1591 res = fctx->res;
1592 task = res->buckets[fctx->bucketnum].task;
1593
1594 srtt = addrinfo->srtt;
1595
1596 /*
1597 * A forwarder needs to make multiple queries. Give it at least
1598 * a second to do these in.
1599 */
1600 if (ISFORWARDER(addrinfo) && srtt < 1000000)
1601 srtt = 1000000;
1602
1603 fctx_setretryinterval(fctx, srtt);
1604 result = fctx_startidletimer(fctx, &fctx->interval);
1605 if (result != ISC_R_SUCCESS)
1606 return (result);
1607
1608 INSIST(ISC_LIST_EMPTY(fctx->validators));
1609
1610 dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE);
1611
1612 query = isc_mem_get(fctx->mctx, sizeof(*query));
1613 if (query == NULL) {
1614 result = ISC_R_NOMEMORY;
1615 goto stop_idle_timer;
1616 }
1617 query->mctx = fctx->mctx;
1618 query->options = options;
1619 query->attributes = 0;
1620 query->sends = 0;
1621 query->connects = 0;
1622 /*
1623 * Note that the caller MUST guarantee that 'addrinfo' will remain
1624 * valid until this query is canceled.
1625 */
1626 query->addrinfo = addrinfo;
1627 TIME_NOW(&query->start);
1628
1629 /*
1630 * If this is a TCP query, then we need to make a socket and
1631 * a dispatch for it here. Otherwise we use the resolver's
1632 * shared dispatch.
1633 */
1634 query->dispatchmgr = res->dispatchmgr;
1635 query->dispatch = NULL;
1636 query->exclusivesocket = ISC_FALSE;
1637 query->tcpsocket = NULL;
1638 if (res->view->peers != NULL) {
1639 dns_peer_t *peer = NULL;
1640 isc_netaddr_t dstip;
1641 isc_netaddr_fromsockaddr(&dstip, &addrinfo->sockaddr);
1642 result = dns_peerlist_peerbyaddr(res->view->peers,
1643 &dstip, &peer);
1644 if (result == ISC_R_SUCCESS) {
1645 result = dns_peer_getquerysource(peer, &addr);
1646 if (result == ISC_R_SUCCESS)
1647 have_addr = ISC_TRUE;
1648 }
1649 }
1650
1651 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1652 int pf;
1653
1654 pf = isc_sockaddr_pf(&addrinfo->sockaddr);
1655 if (!have_addr) {
1656 switch (pf) {
1657 case PF_INET:
1658 result = dns_dispatch_getlocaladdress(
1659 res->dispatches4->dispatches[0],
1660 &addr);
1661 break;
1662 case PF_INET6:
1663 result = dns_dispatch_getlocaladdress(
1664 res->dispatches6->dispatches[0],
1665 &addr);
1666 break;
1667 default:
1668 result = ISC_R_NOTIMPLEMENTED;
1669 break;
1670 }
1671 if (result != ISC_R_SUCCESS)
1672 goto cleanup_query;
1673 }
1674 isc_sockaddr_setport(&addr, 0);
1675
1676 result = isc_socket_create(res->socketmgr, pf,
1677 isc_sockettype_tcp,
1678 &query->tcpsocket);
1679 if (result != ISC_R_SUCCESS)
1680 goto cleanup_query;
1681
1682 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
1683 result = isc_socket_bind(query->tcpsocket, &addr, 0);
1684 if (result != ISC_R_SUCCESS)
1685 goto cleanup_socket;
1686 #endif
1687
1688 /*
1689 * A dispatch will be created once the connect succeeds.
1690 */
1691 } else {
1692 if (have_addr) {
1693 unsigned int attrs, attrmask;
1694 attrs = DNS_DISPATCHATTR_UDP;
1695 switch (isc_sockaddr_pf(&addr)) {
1696 case AF_INET:
1697 attrs |= DNS_DISPATCHATTR_IPV4;
1698 break;
1699 case AF_INET6:
1700 attrs |= DNS_DISPATCHATTR_IPV6;
1701 break;
1702 default:
1703 result = ISC_R_NOTIMPLEMENTED;
1704 goto cleanup_query;
1705 }
1706 attrmask = DNS_DISPATCHATTR_UDP;
1707 attrmask |= DNS_DISPATCHATTR_TCP;
1708 attrmask |= DNS_DISPATCHATTR_IPV4;
1709 attrmask |= DNS_DISPATCHATTR_IPV6;
1710 result = dns_dispatch_getudp(res->dispatchmgr,
1711 res->socketmgr,
1712 res->taskmgr, &addr,
1713 4096, 1000, 32768, 16411,
1714 16433, attrs, attrmask,
1715 &query->dispatch);
1716 if (result != ISC_R_SUCCESS)
1717 goto cleanup_query;
1718 } else {
1719 switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
1720 case PF_INET:
1721 dns_dispatch_attach(
1722 dns_resolver_dispatchv4(res),
1723 &query->dispatch);
1724 query->exclusivesocket = res->exclusivev4;
1725 break;
1726 case PF_INET6:
1727 dns_dispatch_attach(
1728 dns_resolver_dispatchv6(res),
1729 &query->dispatch);
1730 query->exclusivesocket = res->exclusivev6;
1731 break;
1732 default:
1733 result = ISC_R_NOTIMPLEMENTED;
1734 goto cleanup_query;
1735 }
1736 }
1737 /*
1738 * We should always have a valid dispatcher here. If we
1739 * don't support a protocol family, then its dispatcher
1740 * will be NULL, but we shouldn't be finding addresses for
1741 * protocol types we don't support, so the dispatcher
1742 * we found should never be NULL.
1743 */
1744 INSIST(query->dispatch != NULL);
1745 }
1746
1747 query->dispentry = NULL;
1748 query->fctx = fctx; /* reference added by caller */
1749 query->tsig = NULL;
1750 query->tsigkey = NULL;
1751 ISC_LINK_INIT(query, link);
1752 query->magic = QUERY_MAGIC;
1753
1754 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1755 /*
1756 * Connect to the remote server.
1757 *
1758 * XXXRTH Should we attach to the socket?
1759 */
1760 result = isc_socket_connect(query->tcpsocket,
1761 &addrinfo->sockaddr, task,
1762 resquery_connected, query);
1763 if (result != ISC_R_SUCCESS)
1764 goto cleanup_socket;
1765 query->connects++;
1766 QTRACE("connecting via TCP");
1767 } else {
1768 #ifdef ENABLE_FETCHLIMIT
1769 if (dns_adbentry_overquota(addrinfo->entry))
1770 goto cleanup_dispatch;
1771
1772 /* Inform the ADB that we're starting a fetch */
1773 dns_adb_beginudpfetch(fctx->adb, addrinfo);
1774 #endif /* ENABLE_FETCHLIMIT */
1775
1776 result = resquery_send(query);
1777 if (result != ISC_R_SUCCESS)
1778 goto cleanup_dispatch;
1779 }
1780
1781 fctx->querysent++;
1782
1783 ISC_LIST_APPEND(fctx->queries, query, link);
1784 query->fctx->nqueries++;
1785 if (isc_sockaddr_pf(&addrinfo->sockaddr) == PF_INET)
1786 inc_stats(res, dns_resstatscounter_queryv4);
1787 else
1788 inc_stats(res, dns_resstatscounter_queryv6);
1789 if (res->view->resquerystats != NULL)
1790 dns_rdatatypestats_increment(res->view->resquerystats,
1791 fctx->type);
1792
1793 return (ISC_R_SUCCESS);
1794
1795 cleanup_socket:
1796 isc_socket_detach(&query->tcpsocket);
1797
1798 cleanup_dispatch:
1799 if (query->dispatch != NULL)
1800 dns_dispatch_detach(&query->dispatch);
1801
1802 cleanup_query:
1803 if (query->connects == 0) {
1804 query->magic = 0;
1805 isc_mem_put(fctx->mctx, query, sizeof(*query));
1806 }
1807
1808 stop_idle_timer:
1809 RUNTIME_CHECK(fctx_stopidletimer(fctx) == ISC_R_SUCCESS);
1810
1811 return (result);
1812 }
1813
1814 static isc_boolean_t
bad_edns(fetchctx_t * fctx,isc_sockaddr_t * address)1815 bad_edns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1816 isc_sockaddr_t *sa;
1817
1818 for (sa = ISC_LIST_HEAD(fctx->bad_edns);
1819 sa != NULL;
1820 sa = ISC_LIST_NEXT(sa, link)) {
1821 if (isc_sockaddr_equal(sa, address))
1822 return (ISC_TRUE);
1823 }
1824
1825 return (ISC_FALSE);
1826 }
1827
1828 static void
add_bad_edns(fetchctx_t * fctx,isc_sockaddr_t * address)1829 add_bad_edns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1830 isc_sockaddr_t *sa;
1831
1832 if (bad_edns(fctx, address))
1833 return;
1834
1835 sa = isc_mem_get(fctx->mctx, sizeof(*sa));
1836 if (sa == NULL)
1837 return;
1838
1839 *sa = *address;
1840 ISC_LIST_INITANDAPPEND(fctx->bad_edns, sa, link);
1841 }
1842
1843 static isc_boolean_t
triededns(fetchctx_t * fctx,isc_sockaddr_t * address)1844 triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1845 isc_sockaddr_t *sa;
1846
1847 for (sa = ISC_LIST_HEAD(fctx->edns);
1848 sa != NULL;
1849 sa = ISC_LIST_NEXT(sa, link)) {
1850 if (isc_sockaddr_equal(sa, address))
1851 return (ISC_TRUE);
1852 }
1853
1854 return (ISC_FALSE);
1855 }
1856
1857 static void
add_triededns(fetchctx_t * fctx,isc_sockaddr_t * address)1858 add_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1859 isc_sockaddr_t *sa;
1860
1861 if (triededns(fctx, address))
1862 return;
1863
1864 sa = isc_mem_get(fctx->mctx, sizeof(*sa));
1865 if (sa == NULL)
1866 return;
1867
1868 *sa = *address;
1869 ISC_LIST_INITANDAPPEND(fctx->edns, sa, link);
1870 }
1871
1872 static isc_boolean_t
triededns512(fetchctx_t * fctx,isc_sockaddr_t * address)1873 triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
1874 isc_sockaddr_t *sa;
1875
1876 for (sa = ISC_LIST_HEAD(fctx->edns512);
1877 sa != NULL;
1878 sa = ISC_LIST_NEXT(sa, link)) {
1879 if (isc_sockaddr_equal(sa, address))
1880 return (ISC_TRUE);
1881 }
1882
1883 return (ISC_FALSE);
1884 }
1885
1886 static void
add_triededns512(fetchctx_t * fctx,isc_sockaddr_t * address)1887 add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
1888 isc_sockaddr_t *sa;
1889
1890 if (triededns512(fctx, address))
1891 return;
1892
1893 sa = isc_mem_get(fctx->mctx, sizeof(*sa));
1894 if (sa == NULL)
1895 return;
1896
1897 *sa = *address;
1898 ISC_LIST_INITANDAPPEND(fctx->edns512, sa, link);
1899 }
1900
1901 static isc_boolean_t
wouldvalidate(fetchctx_t * fctx)1902 wouldvalidate(fetchctx_t *fctx) {
1903 isc_boolean_t secure_domain;
1904 isc_result_t result;
1905
1906 if (!fctx->res->view->enablevalidation)
1907 return (ISC_FALSE);
1908
1909 if (fctx->res->view->dlv != NULL)
1910 return (ISC_TRUE);
1911
1912 result = dns_view_issecuredomain(fctx->res->view, &fctx->name,
1913 &secure_domain);
1914 if (result != ISC_R_SUCCESS)
1915 return (ISC_FALSE);
1916 return (secure_domain);
1917 }
1918
1919 static isc_result_t
resquery_send(resquery_t * query)1920 resquery_send(resquery_t *query) {
1921 fetchctx_t *fctx;
1922 isc_result_t result;
1923 dns_name_t *qname = NULL;
1924 dns_rdataset_t *qrdataset = NULL;
1925 isc_region_t r;
1926 dns_resolver_t *res;
1927 isc_task_t *task;
1928 isc_socket_t *sock;
1929 isc_buffer_t tcpbuffer;
1930 isc_sockaddr_t *address;
1931 isc_buffer_t *buffer;
1932 isc_netaddr_t ipaddr;
1933 dns_tsigkey_t *tsigkey = NULL;
1934 dns_peer_t *peer = NULL;
1935 isc_boolean_t useedns;
1936 dns_compress_t cctx;
1937 isc_boolean_t cleanup_cctx = ISC_FALSE;
1938 isc_boolean_t secure_domain;
1939 isc_boolean_t connecting = ISC_FALSE;
1940 dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
1941 unsigned ednsopt = 0;
1942
1943 fctx = query->fctx;
1944 QTRACE("send");
1945
1946 res = fctx->res;
1947 task = res->buckets[fctx->bucketnum].task;
1948 address = NULL;
1949
1950 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1951 /*
1952 * Reserve space for the TCP message length.
1953 */
1954 isc_buffer_init(&tcpbuffer, query->data, sizeof(query->data));
1955 isc_buffer_init(&query->buffer, query->data + 2,
1956 sizeof(query->data) - 2);
1957 buffer = &tcpbuffer;
1958 } else {
1959 isc_buffer_init(&query->buffer, query->data,
1960 sizeof(query->data));
1961 buffer = &query->buffer;
1962 }
1963
1964 result = dns_message_gettempname(fctx->qmessage, &qname);
1965 if (result != ISC_R_SUCCESS)
1966 goto cleanup_temps;
1967 result = dns_message_gettemprdataset(fctx->qmessage, &qrdataset);
1968 if (result != ISC_R_SUCCESS)
1969 goto cleanup_temps;
1970
1971 /*
1972 * Get a query id from the dispatch.
1973 */
1974 result = dns_dispatch_addresponse2(query->dispatch,
1975 &query->addrinfo->sockaddr,
1976 task,
1977 resquery_response,
1978 query,
1979 &query->id,
1980 &query->dispentry,
1981 res->socketmgr);
1982 if (result != ISC_R_SUCCESS)
1983 goto cleanup_temps;
1984
1985 fctx->qmessage->opcode = dns_opcode_query;
1986
1987 /*
1988 * Set up question.
1989 */
1990 dns_name_init(qname, NULL);
1991 dns_name_clone(&fctx->name, qname);
1992 dns_rdataset_init(qrdataset);
1993 dns_rdataset_makequestion(qrdataset, res->rdclass, fctx->type);
1994 ISC_LIST_APPEND(qname->list, qrdataset, link);
1995 dns_message_addname(fctx->qmessage, qname, DNS_SECTION_QUESTION);
1996 qname = NULL;
1997 qrdataset = NULL;
1998
1999 /*
2000 * Set RD if the client has requested that we do a recursive query,
2001 * or if we're sending to a forwarder.
2002 */
2003 if ((query->options & DNS_FETCHOPT_RECURSIVE) != 0 ||
2004 ISFORWARDER(query->addrinfo))
2005 fctx->qmessage->flags |= DNS_MESSAGEFLAG_RD;
2006
2007 /*
2008 * Set CD if the client says don't validate or the question is
2009 * under a secure entry point.
2010 */
2011 if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0) {
2012 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
2013 } else if (res->view->enablevalidation) {
2014 result = dns_view_issecuredomain(res->view, &fctx->name,
2015 &secure_domain);
2016 if (result != ISC_R_SUCCESS)
2017 secure_domain = ISC_FALSE;
2018 if (res->view->dlv != NULL)
2019 secure_domain = ISC_TRUE;
2020 if (secure_domain)
2021 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
2022 }
2023
2024 /*
2025 * We don't have to set opcode because it defaults to query.
2026 */
2027 fctx->qmessage->id = query->id;
2028
2029 /*
2030 * Convert the question to wire format.
2031 */
2032 result = dns_compress_init(&cctx, -1, fctx->res->mctx);
2033 if (result != ISC_R_SUCCESS)
2034 goto cleanup_message;
2035 cleanup_cctx = ISC_TRUE;
2036
2037 result = dns_message_renderbegin(fctx->qmessage, &cctx,
2038 &query->buffer);
2039 if (result != ISC_R_SUCCESS)
2040 goto cleanup_message;
2041
2042 result = dns_message_rendersection(fctx->qmessage,
2043 DNS_SECTION_QUESTION, 0);
2044 if (result != ISC_R_SUCCESS)
2045 goto cleanup_message;
2046
2047 peer = NULL;
2048 isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);
2049 (void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
2050
2051 /*
2052 * The ADB does not know about servers with "edns no". Check this,
2053 * and then inform the ADB for future use.
2054 */
2055 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0 &&
2056 peer != NULL &&
2057 dns_peer_getsupportedns(peer, &useedns) == ISC_R_SUCCESS &&
2058 !useedns)
2059 {
2060 query->options |= DNS_FETCHOPT_NOEDNS0;
2061 dns_adb_changeflags(fctx->adb, query->addrinfo,
2062 DNS_FETCHOPT_NOEDNS0,
2063 DNS_FETCHOPT_NOEDNS0);
2064 }
2065
2066 /* Sync NOEDNS0 flag in addrinfo->flags and options now. */
2067 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) != 0)
2068 query->options |= DNS_FETCHOPT_NOEDNS0;
2069
2070 /*
2071 * Handle timeouts by reducing the UDP response size to 512 bytes
2072 * then if that doesn't work disabling EDNS (includes DO) and CD.
2073 *
2074 * These timeout can be due to:
2075 * * broken nameservers that don't respond to EDNS queries.
2076 * * broken/misconfigured firewalls and NAT implementations
2077 * that don't handle IP fragmentation.
2078 * * broken/misconfigured firewalls that don't handle responses
2079 * greater than 512 bytes.
2080 * * broken/misconfigured firewalls that don't handle EDNS, DO
2081 * or CD.
2082 * * packet loss / link outage.
2083 */
2084 if (fctx->timeout) {
2085 if ((triededns512(fctx, &query->addrinfo->sockaddr) ||
2086 fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) &&
2087 (query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
2088 (!EDNSOK(query->addrinfo) || !wouldvalidate(fctx))) {
2089 query->options |= DNS_FETCHOPT_NOEDNS0;
2090 fctx->reason = "disabling EDNS";
2091 } else if ((triededns(fctx, &query->addrinfo->sockaddr) ||
2092 fctx->timeouts >= MAX_EDNS0_TIMEOUTS) &&
2093 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
2094 query->options |= DNS_FETCHOPT_EDNS512;
2095 fctx->reason = "reducing the advertised EDNS UDP "
2096 "packet size to 512 octets";
2097 }
2098 fctx->timeout = ISC_FALSE;
2099 }
2100
2101 /*
2102 * Use EDNS0, unless the caller doesn't want it, or we know that
2103 * the remote server doesn't like it.
2104 */
2105 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
2106 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {
2107 unsigned int version = 0; /* Default version. */
2108 unsigned int flags;
2109 isc_uint16_t udpsize = res->udpsize;
2110 isc_boolean_t reqnsid = res->view->requestnsid;
2111
2112 flags = query->addrinfo->flags;
2113 if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {
2114 version = flags & DNS_FETCHOPT_EDNSVERSIONMASK;
2115 version >>= DNS_FETCHOPT_EDNSVERSIONSHIFT;
2116 }
2117 if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
2118 udpsize = 512;
2119 else if (peer != NULL)
2120 (void)dns_peer_getudpsize(peer, &udpsize);
2121
2122 /* request NSID for current view or peer? */
2123 if (peer != NULL)
2124 (void) dns_peer_getrequestnsid(peer, &reqnsid);
2125 if (reqnsid) {
2126 INSIST(ednsopt < DNS_EDNSOPTIONS);
2127 ednsopts[ednsopt].code = DNS_OPT_NSID;
2128 ednsopts[ednsopt].length = 0;
2129 ednsopts[ednsopt].value = NULL;
2130 ednsopt++;
2131 }
2132 query->ednsversion = version;
2133 result = fctx_addopt(fctx->qmessage, version,
2134 udpsize, ednsopts, ednsopt);
2135 if (reqnsid && result == ISC_R_SUCCESS) {
2136 query->options |= DNS_FETCHOPT_WANTNSID;
2137 } else if (result != ISC_R_SUCCESS) {
2138 /*
2139 * We couldn't add the OPT, but we'll press on.
2140 * We're not using EDNS0, so set the NOEDNS0
2141 * bit.
2142 */
2143 query->options |= DNS_FETCHOPT_NOEDNS0;
2144 query->ednsversion = -1;
2145 }
2146 } else {
2147 /*
2148 * We know this server doesn't like EDNS0, so we
2149 * won't use it. Set the NOEDNS0 bit since we're
2150 * not using EDNS0.
2151 */
2152 query->options |= DNS_FETCHOPT_NOEDNS0;
2153 query->ednsversion = -1;
2154 }
2155 } else
2156 query->ednsversion = -1;
2157
2158 /*
2159 * If we need EDNS0 to do this query and aren't using it, we lose.
2160 */
2161 if (NEEDEDNS0(fctx) && (query->options & DNS_FETCHOPT_NOEDNS0) != 0) {
2162 result = DNS_R_SERVFAIL;
2163 goto cleanup_message;
2164 }
2165
2166 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0)
2167 add_triededns(fctx, &query->addrinfo->sockaddr);
2168
2169 if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
2170 add_triededns512(fctx, &query->addrinfo->sockaddr);
2171
2172 /*
2173 * Clear CD if EDNS is not in use.
2174 */
2175 if ((query->options & DNS_FETCHOPT_NOEDNS0) != 0)
2176 fctx->qmessage->flags &= ~DNS_MESSAGEFLAG_CD;
2177
2178 /*
2179 * Add TSIG record tailored to the current recipient.
2180 */
2181 result = dns_view_getpeertsig(fctx->res->view, &ipaddr, &tsigkey);
2182 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
2183 goto cleanup_message;
2184
2185 if (tsigkey != NULL) {
2186 result = dns_message_settsigkey(fctx->qmessage, tsigkey);
2187 dns_tsigkey_detach(&tsigkey);
2188 if (result != ISC_R_SUCCESS)
2189 goto cleanup_message;
2190 }
2191
2192 result = dns_message_rendersection(fctx->qmessage,
2193 DNS_SECTION_ADDITIONAL, 0);
2194 if (result != ISC_R_SUCCESS)
2195 goto cleanup_message;
2196
2197 result = dns_message_renderend(fctx->qmessage);
2198 if (result != ISC_R_SUCCESS)
2199 goto cleanup_message;
2200
2201 dns_compress_invalidate(&cctx);
2202 cleanup_cctx = ISC_FALSE;
2203
2204 if (dns_message_gettsigkey(fctx->qmessage) != NULL) {
2205 dns_tsigkey_attach(dns_message_gettsigkey(fctx->qmessage),
2206 &query->tsigkey);
2207 result = dns_message_getquerytsig(fctx->qmessage,
2208 fctx->res->mctx,
2209 &query->tsig);
2210 if (result != ISC_R_SUCCESS)
2211 goto cleanup_message;
2212 }
2213
2214 /*
2215 * If using TCP, write the length of the message at the beginning
2216 * of the buffer.
2217 */
2218 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
2219 isc_buffer_usedregion(&query->buffer, &r);
2220 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t)r.length);
2221 isc_buffer_add(&tcpbuffer, r.length);
2222 }
2223
2224 /*
2225 * We're now done with the query message.
2226 */
2227 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
2228
2229 if (query->exclusivesocket)
2230 sock = dns_dispatch_getentrysocket(query->dispentry);
2231 else
2232 sock = dns_dispatch_getsocket(query->dispatch);
2233 /*
2234 * Send the query!
2235 */
2236 if ((query->options & DNS_FETCHOPT_TCP) == 0) {
2237 address = &query->addrinfo->sockaddr;
2238 if (query->exclusivesocket) {
2239 result = isc_socket_connect(sock, address, task,
2240 resquery_udpconnected,
2241 query);
2242 if (result != ISC_R_SUCCESS)
2243 goto cleanup_message;
2244 connecting = ISC_TRUE;
2245 query->connects++;
2246 }
2247 }
2248 isc_buffer_usedregion(buffer, &r);
2249
2250 /*
2251 * XXXRTH Make sure we don't send to ourselves! We should probably
2252 * prune out these addresses when we get them from the ADB.
2253 */
2254 ISC_EVENT_INIT(&query->sendevent, sizeof(query->sendevent), 0, NULL,
2255 ISC_SOCKEVENT_SENDDONE, resquery_senddone, query,
2256 NULL, NULL, NULL);
2257 result = isc_socket_sendto2(sock, &r, task, address, NULL,
2258 &query->sendevent, 0);
2259 if (result != ISC_R_SUCCESS) {
2260 if (connecting) {
2261 /*
2262 * This query is still connecting.
2263 * Mark it as canceled so that it will just be
2264 * cleaned up when the connected event is received.
2265 * Keep fctx around until the event is processed.
2266 */
2267 query->fctx->nqueries++;
2268 query->attributes |= RESQUERY_ATTR_CANCELED;
2269 }
2270 goto cleanup_message;
2271 }
2272
2273 query->sends++;
2274
2275 QTRACE("sent");
2276
2277 return (ISC_R_SUCCESS);
2278
2279 cleanup_message:
2280 if (cleanup_cctx)
2281 dns_compress_invalidate(&cctx);
2282
2283 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
2284
2285 /*
2286 * Stop the dispatcher from listening.
2287 */
2288 dns_dispatch_removeresponse(&query->dispentry, NULL);
2289
2290 cleanup_temps:
2291 if (qname != NULL)
2292 dns_message_puttempname(fctx->qmessage, &qname);
2293 if (qrdataset != NULL)
2294 dns_message_puttemprdataset(fctx->qmessage, &qrdataset);
2295
2296 return (result);
2297 }
2298
2299 static void
resquery_connected(isc_task_t * task,isc_event_t * event)2300 resquery_connected(isc_task_t *task, isc_event_t *event) {
2301 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
2302 resquery_t *query = event->ev_arg;
2303 isc_boolean_t retry = ISC_FALSE;
2304 isc_interval_t interval;
2305 isc_result_t result;
2306 unsigned int attrs;
2307 fetchctx_t *fctx;
2308
2309 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
2310 REQUIRE(VALID_QUERY(query));
2311
2312 QTRACE("connected");
2313
2314 UNUSED(task);
2315
2316 /*
2317 * XXXRTH
2318 *
2319 * Currently we don't wait for the connect event before retrying
2320 * a query. This means that if we get really behind, we may end
2321 * up doing extra work!
2322 */
2323
2324 query->connects--;
2325 fctx = query->fctx;
2326
2327 if (RESQUERY_CANCELED(query)) {
2328 /*
2329 * This query was canceled while the connect() was in
2330 * progress.
2331 */
2332 isc_socket_detach(&query->tcpsocket);
2333 resquery_destroy(&query);
2334 } else {
2335 switch (sevent->result) {
2336 case ISC_R_SUCCESS:
2337
2338 /*
2339 * Extend the idle timer for TCP. 20 seconds
2340 * should be long enough for a TCP connection to be
2341 * established, a single DNS request to be sent,
2342 * and the response received.
2343 */
2344 isc_interval_set(&interval, 20, 0);
2345 result = fctx_startidletimer(query->fctx, &interval);
2346 if (result != ISC_R_SUCCESS) {
2347 FCTXTRACE("query canceled: idle timer failed; "
2348 "responding");
2349
2350 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE,
2351 ISC_FALSE);
2352 fctx_done(fctx, result, __LINE__);
2353 break;
2354 }
2355 /*
2356 * We are connected. Create a dispatcher and
2357 * send the query.
2358 */
2359 attrs = 0;
2360 attrs |= DNS_DISPATCHATTR_TCP;
2361 attrs |= DNS_DISPATCHATTR_PRIVATE;
2362 attrs |= DNS_DISPATCHATTR_CONNECTED;
2363 if (isc_sockaddr_pf(&query->addrinfo->sockaddr) ==
2364 AF_INET)
2365 attrs |= DNS_DISPATCHATTR_IPV4;
2366 else
2367 attrs |= DNS_DISPATCHATTR_IPV6;
2368 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
2369
2370 result = dns_dispatch_createtcp(query->dispatchmgr,
2371 query->tcpsocket,
2372 query->fctx->res->taskmgr,
2373 4096, 2, 1, 1, 3, attrs,
2374 &query->dispatch);
2375
2376 /*
2377 * Regardless of whether dns_dispatch_create()
2378 * succeeded or not, we don't need our reference
2379 * to the socket anymore.
2380 */
2381 isc_socket_detach(&query->tcpsocket);
2382
2383 if (result == ISC_R_SUCCESS)
2384 result = resquery_send(query);
2385
2386 if (result != ISC_R_SUCCESS) {
2387 FCTXTRACE("query canceled: "
2388 "resquery_send() failed; responding");
2389
2390 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE, ISC_FALSE);
2391 fctx_done(fctx, result, __LINE__);
2392 }
2393 break;
2394
2395 case ISC_R_NETUNREACH:
2396 case ISC_R_HOSTUNREACH:
2397 case ISC_R_CONNREFUSED:
2398 case ISC_R_NOPERM:
2399 case ISC_R_ADDRNOTAVAIL:
2400 case ISC_R_CONNECTIONRESET:
2401 FCTXTRACE3("query canceled in connected(): "
2402 "no route to host; no response",
2403 sevent->result);
2404
2405 /*
2406 * No route to remote.
2407 */
2408 isc_socket_detach(&query->tcpsocket);
2409 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE, ISC_FALSE);
2410 retry = ISC_TRUE;
2411 break;
2412
2413 default:
2414 FCTXTRACE3("query canceled in connected() due to "
2415 "unexpected event result; responding",
2416 sevent->result);
2417
2418 isc_socket_detach(&query->tcpsocket);
2419 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE, ISC_FALSE);
2420 break;
2421 }
2422 }
2423
2424 isc_event_free(&event);
2425
2426 if (retry) {
2427 /*
2428 * Behave as if the idle timer has expired. For TCP
2429 * connections this may not actually reflect the latest timer.
2430 */
2431 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
2432 result = fctx_stopidletimer(fctx);
2433 if (result != ISC_R_SUCCESS)
2434 fctx_done(fctx, result, __LINE__);
2435 else
2436 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
2437 }
2438 }
2439
2440 static void
fctx_finddone(isc_task_t * task,isc_event_t * event)2441 fctx_finddone(isc_task_t *task, isc_event_t *event) {
2442 fetchctx_t *fctx;
2443 dns_adbfind_t *find;
2444 dns_resolver_t *res;
2445 isc_boolean_t want_try = ISC_FALSE;
2446 isc_boolean_t want_done = ISC_FALSE;
2447 isc_boolean_t bucket_empty = ISC_FALSE;
2448 unsigned int bucketnum;
2449 isc_boolean_t dodestroy = ISC_FALSE;
2450
2451 find = event->ev_sender;
2452 fctx = event->ev_arg;
2453 REQUIRE(VALID_FCTX(fctx));
2454 res = fctx->res;
2455
2456 UNUSED(task);
2457
2458 FCTXTRACE("finddone");
2459
2460 bucketnum = fctx->bucketnum;
2461 LOCK(&res->buckets[bucketnum].lock);
2462
2463 INSIST(fctx->pending > 0);
2464 fctx->pending--;
2465
2466 if (ADDRWAIT(fctx)) {
2467 /*
2468 * The fetch is waiting for a name to be found.
2469 */
2470 INSIST(!SHUTTINGDOWN(fctx));
2471 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
2472 if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) {
2473 want_try = ISC_TRUE;
2474 } else {
2475 fctx->findfail++;
2476 if (fctx->pending == 0) {
2477 /*
2478 * We've got nothing else to wait for and don't
2479 * know the answer. There's nothing to do but
2480 * fail the fctx.
2481 */
2482 want_done = ISC_TRUE;
2483 }
2484 }
2485 } else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&
2486 fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
2487
2488 if (fctx->references == 0) {
2489 bucket_empty = fctx_unlink(fctx);
2490 dodestroy = ISC_TRUE;
2491 }
2492 }
2493 UNLOCK(&res->buckets[bucketnum].lock);
2494
2495 isc_event_free(&event);
2496 dns_adb_destroyfind(&find);
2497
2498 if (want_try) {
2499 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
2500 } else if (want_done) {
2501 FCTXTRACE("fetch failed in finddone(); return ISC_R_FAILURE");
2502 fctx_done(fctx, ISC_R_FAILURE, __LINE__);
2503 } else if (dodestroy) {
2504 fctx_destroy(fctx);
2505 if (bucket_empty)
2506 empty_bucket(res);
2507 }
2508 }
2509
2510
2511 static inline isc_boolean_t
bad_server(fetchctx_t * fctx,isc_sockaddr_t * address)2512 bad_server(fetchctx_t *fctx, isc_sockaddr_t *address) {
2513 isc_sockaddr_t *sa;
2514
2515 for (sa = ISC_LIST_HEAD(fctx->bad);
2516 sa != NULL;
2517 sa = ISC_LIST_NEXT(sa, link)) {
2518 if (isc_sockaddr_equal(sa, address))
2519 return (ISC_TRUE);
2520 }
2521
2522 return (ISC_FALSE);
2523 }
2524
2525 static inline isc_boolean_t
mark_bad(fetchctx_t * fctx)2526 mark_bad(fetchctx_t *fctx) {
2527 dns_adbfind_t *curr;
2528 dns_adbaddrinfo_t *addrinfo;
2529 isc_boolean_t all_bad = ISC_TRUE;
2530
2531 /*
2532 * Mark all known bad servers, so we don't try to talk to them
2533 * again.
2534 */
2535
2536 /*
2537 * Mark any bad nameservers.
2538 */
2539 for (curr = ISC_LIST_HEAD(fctx->finds);
2540 curr != NULL;
2541 curr = ISC_LIST_NEXT(curr, publink)) {
2542 for (addrinfo = ISC_LIST_HEAD(curr->list);
2543 addrinfo != NULL;
2544 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2545 if (bad_server(fctx, &addrinfo->sockaddr))
2546 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2547 else
2548 all_bad = ISC_FALSE;
2549 }
2550 }
2551
2552 /*
2553 * Mark any bad forwarders.
2554 */
2555 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
2556 addrinfo != NULL;
2557 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2558 if (bad_server(fctx, &addrinfo->sockaddr))
2559 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2560 else
2561 all_bad = ISC_FALSE;
2562 }
2563
2564 /*
2565 * Mark any bad alternates.
2566 */
2567 for (curr = ISC_LIST_HEAD(fctx->altfinds);
2568 curr != NULL;
2569 curr = ISC_LIST_NEXT(curr, publink)) {
2570 for (addrinfo = ISC_LIST_HEAD(curr->list);
2571 addrinfo != NULL;
2572 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2573 if (bad_server(fctx, &addrinfo->sockaddr))
2574 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2575 else
2576 all_bad = ISC_FALSE;
2577 }
2578 }
2579
2580 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
2581 addrinfo != NULL;
2582 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2583 if (bad_server(fctx, &addrinfo->sockaddr))
2584 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2585 else
2586 all_bad = ISC_FALSE;
2587 }
2588
2589 return (all_bad);
2590 }
2591
2592 static void
add_bad(fetchctx_t * fctx,dns_adbaddrinfo_t * addrinfo,isc_result_t reason,badnstype_t badtype)2593 add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason,
2594 badnstype_t badtype)
2595 {
2596 char namebuf[DNS_NAME_FORMATSIZE];
2597 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2598 char classbuf[64];
2599 char typebuf[64];
2600 char code[64];
2601 isc_buffer_t b;
2602 isc_sockaddr_t *sa;
2603 const char *spc = "";
2604 isc_sockaddr_t *address = &addrinfo->sockaddr;
2605
2606 if (reason == DNS_R_LAME)
2607 fctx->lamecount++;
2608 else {
2609 switch (badtype) {
2610 case badns_unreachable:
2611 fctx->neterr++;
2612 break;
2613 case badns_response:
2614 fctx->badresp++;
2615 break;
2616 case badns_validation:
2617 break; /* counted as 'valfail' */
2618 }
2619 }
2620
2621 if (bad_server(fctx, address)) {
2622 /*
2623 * We already know this server is bad.
2624 */
2625 return;
2626 }
2627
2628 FCTXTRACE("add_bad");
2629
2630 sa = isc_mem_get(fctx->mctx, sizeof(*sa));
2631 if (sa == NULL)
2632 return;
2633 *sa = *address;
2634 ISC_LIST_INITANDAPPEND(fctx->bad, sa, link);
2635
2636 if (reason == DNS_R_LAME) /* already logged */
2637 return;
2638
2639 if (reason == DNS_R_UNEXPECTEDRCODE &&
2640 fctx->rmessage->rcode == dns_rcode_servfail &&
2641 ISFORWARDER(addrinfo))
2642 return;
2643
2644 if (reason == DNS_R_UNEXPECTEDRCODE) {
2645 isc_buffer_init(&b, code, sizeof(code) - 1);
2646 dns_rcode_totext(fctx->rmessage->rcode, &b);
2647 code[isc_buffer_usedlength(&b)] = '\0';
2648 spc = " ";
2649 } else if (reason == DNS_R_UNEXPECTEDOPCODE) {
2650 isc_buffer_init(&b, code, sizeof(code) - 1);
2651 dns_opcode_totext((dns_opcode_t)fctx->rmessage->opcode, &b);
2652 code[isc_buffer_usedlength(&b)] = '\0';
2653 spc = " ";
2654 } else {
2655 code[0] = '\0';
2656 }
2657 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
2658 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
2659 dns_rdataclass_format(fctx->res->rdclass, classbuf, sizeof(classbuf));
2660 isc_sockaddr_format(address, addrbuf, sizeof(addrbuf));
2661 isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
2662 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
2663 "error (%s%s%s) resolving '%s/%s/%s': %s",
2664 dns_result_totext(reason), spc, code,
2665 namebuf, typebuf, classbuf, addrbuf);
2666 }
2667
2668 /*
2669 * Sort addrinfo list by RTT.
2670 */
2671 static void
sort_adbfind(dns_adbfind_t * find)2672 sort_adbfind(dns_adbfind_t *find) {
2673 dns_adbaddrinfo_t *best, *curr;
2674 dns_adbaddrinfolist_t sorted;
2675
2676 /* Lame N^2 bubble sort. */
2677 ISC_LIST_INIT(sorted);
2678 while (!ISC_LIST_EMPTY(find->list)) {
2679 best = ISC_LIST_HEAD(find->list);
2680 curr = ISC_LIST_NEXT(best, publink);
2681 while (curr != NULL) {
2682 if (curr->srtt < best->srtt)
2683 best = curr;
2684 curr = ISC_LIST_NEXT(curr, publink);
2685 }
2686 ISC_LIST_UNLINK(find->list, best, publink);
2687 ISC_LIST_APPEND(sorted, best, publink);
2688 }
2689 find->list = sorted;
2690 }
2691
2692 /*
2693 * Sort a list of finds by server RTT.
2694 */
2695 static void
sort_finds(dns_adbfindlist_t * findlist)2696 sort_finds(dns_adbfindlist_t *findlist) {
2697 dns_adbfind_t *best, *curr;
2698 dns_adbfindlist_t sorted;
2699 dns_adbaddrinfo_t *addrinfo, *bestaddrinfo;
2700
2701 /* Sort each find's addrinfo list by SRTT. */
2702 for (curr = ISC_LIST_HEAD(*findlist);
2703 curr != NULL;
2704 curr = ISC_LIST_NEXT(curr, publink))
2705 sort_adbfind(curr);
2706
2707 /* Lame N^2 bubble sort. */
2708 ISC_LIST_INIT(sorted);
2709 while (!ISC_LIST_EMPTY(*findlist)) {
2710 best = ISC_LIST_HEAD(*findlist);
2711 bestaddrinfo = ISC_LIST_HEAD(best->list);
2712 INSIST(bestaddrinfo != NULL);
2713 curr = ISC_LIST_NEXT(best, publink);
2714 while (curr != NULL) {
2715 addrinfo = ISC_LIST_HEAD(curr->list);
2716 INSIST(addrinfo != NULL);
2717 if (addrinfo->srtt < bestaddrinfo->srtt) {
2718 best = curr;
2719 bestaddrinfo = addrinfo;
2720 }
2721 curr = ISC_LIST_NEXT(curr, publink);
2722 }
2723 ISC_LIST_UNLINK(*findlist, best, publink);
2724 ISC_LIST_APPEND(sorted, best, publink);
2725 }
2726 *findlist = sorted;
2727 }
2728
2729 static void
findname(fetchctx_t * fctx,dns_name_t * name,in_port_t port,unsigned int options,unsigned int flags,isc_stdtime_t now,isc_boolean_t * overquota,isc_boolean_t * need_alternate)2730 findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
2731 unsigned int options, unsigned int flags, isc_stdtime_t now,
2732 isc_boolean_t *overquota, isc_boolean_t *need_alternate)
2733 {
2734 dns_adbaddrinfo_t *ai;
2735 dns_adbfind_t *find;
2736 dns_resolver_t *res;
2737 isc_boolean_t unshared;
2738 isc_result_t result;
2739
2740 #ifndef ENABLE_FETCHLIMIT
2741 UNUSED(overquota);
2742 #endif /* !ENABLE_FETCHLIMIT */
2743
2744 res = fctx->res;
2745 unshared = ISC_TF((fctx->options & DNS_FETCHOPT_UNSHARED) != 0);
2746 /*
2747 * If this name is a subdomain of the query domain, tell
2748 * the ADB to start looking using zone/hint data. This keeps us
2749 * from getting stuck if the nameserver is beneath the zone cut
2750 * and we don't know its address (e.g. because the A record has
2751 * expired).
2752 */
2753 if (dns_name_issubdomain(name, &fctx->domain))
2754 options |= DNS_ADBFIND_STARTATZONE;
2755 options |= DNS_ADBFIND_GLUEOK;
2756 options |= DNS_ADBFIND_HINTOK;
2757
2758 /*
2759 * See what we know about this address.
2760 */
2761 find = NULL;
2762 result = dns_adb_createfind2(fctx->adb,
2763 res->buckets[fctx->bucketnum].task,
2764 fctx_finddone, fctx, name,
2765 &fctx->name, fctx->type,
2766 options, now, NULL,
2767 res->view->dstport,
2768 fctx->depth + 1, fctx->qc, &find);
2769 if (result != ISC_R_SUCCESS) {
2770 if (result == DNS_R_ALIAS) {
2771 char namebuf[DNS_NAME_FORMATSIZE];
2772
2773 /*
2774 * XXXRTH Follow the CNAME/DNAME chain?
2775 */
2776 dns_adb_destroyfind(&find);
2777 fctx->adberr++;
2778 dns_name_format(name, namebuf, sizeof(namebuf));
2779 isc_log_write(dns_lctx, DNS_LOGCATEGORY_CNAME,
2780 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
2781 "skipping nameserver '%s' because it "
2782 "is a CNAME, while resolving '%s'",
2783 namebuf, fctx->info);
2784 }
2785 } else if (!ISC_LIST_EMPTY(find->list)) {
2786 /*
2787 * We have at least some of the addresses for the
2788 * name.
2789 */
2790 INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
2791 if (flags != 0 || port != 0) {
2792 for (ai = ISC_LIST_HEAD(find->list);
2793 ai != NULL;
2794 ai = ISC_LIST_NEXT(ai, publink)) {
2795 ai->flags |= flags;
2796 if (port != 0)
2797 isc_sockaddr_setport(&ai->sockaddr,
2798 port);
2799 }
2800 }
2801 if ((flags & FCTX_ADDRINFO_FORWARDER) != 0)
2802 ISC_LIST_APPEND(fctx->altfinds, find, publink);
2803 else
2804 ISC_LIST_APPEND(fctx->finds, find, publink);
2805 } else {
2806 /*
2807 * We don't know any of the addresses for this
2808 * name.
2809 */
2810 if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
2811 /*
2812 * We're looking for them and will get an
2813 * event about it later.
2814 */
2815 fctx->pending++;
2816 /*
2817 * Bootstrap.
2818 */
2819 if (need_alternate != NULL &&
2820 !*need_alternate && unshared &&
2821 ((res->dispatches4 == NULL &&
2822 find->result_v6 != DNS_R_NXDOMAIN) ||
2823 (res->dispatches6 == NULL &&
2824 find->result_v4 != DNS_R_NXDOMAIN)))
2825 *need_alternate = ISC_TRUE;
2826 } else {
2827 #ifdef ENABLE_FETCHLIMIT
2828 if ((find->options & DNS_ADBFIND_OVERQUOTA) != 0) {
2829 if (overquota != NULL)
2830 *overquota = ISC_TRUE;
2831 fctx->quotacount++; /* quota exceeded */
2832 }
2833 else
2834 #endif /* ENABLE_FETCHLIMIT */
2835 if ((find->options & DNS_ADBFIND_LAMEPRUNED) != 0)
2836 fctx->lamecount++; /* cached lame server */
2837 else
2838 fctx->adberr++; /* unreachable server, etc. */
2839
2840 /*
2841 * If we know there are no addresses for
2842 * the family we are using then try to add
2843 * an alternative server.
2844 */
2845 if (need_alternate != NULL && !*need_alternate &&
2846 ((res->dispatches4 == NULL &&
2847 find->result_v6 == DNS_R_NXRRSET) ||
2848 (res->dispatches6 == NULL &&
2849 find->result_v4 == DNS_R_NXRRSET)))
2850 *need_alternate = ISC_TRUE;
2851 dns_adb_destroyfind(&find);
2852 }
2853 }
2854 }
2855
2856 static isc_boolean_t
isstrictsubdomain(dns_name_t * name1,dns_name_t * name2)2857 isstrictsubdomain(dns_name_t *name1, dns_name_t *name2) {
2858 int order;
2859 unsigned int nlabels;
2860 dns_namereln_t namereln;
2861
2862 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
2863 return (ISC_TF(namereln == dns_namereln_subdomain));
2864 }
2865
2866 static isc_result_t
fctx_getaddresses(fetchctx_t * fctx,isc_boolean_t badcache)2867 fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
2868 dns_rdata_t rdata = DNS_RDATA_INIT;
2869 isc_result_t result;
2870 dns_resolver_t *res;
2871 isc_stdtime_t now;
2872 unsigned int stdoptions = 0;
2873 isc_sockaddr_t *sa;
2874 dns_adbaddrinfo_t *ai;
2875 isc_boolean_t all_bad;
2876 dns_rdata_ns_t ns;
2877 isc_boolean_t need_alternate = ISC_FALSE;
2878 #ifdef ENABLE_FETCHLIMIT
2879 isc_boolean_t all_spilled = ISC_TRUE;
2880 #endif /* ENABLE_FETCHLIMIT */
2881
2882 FCTXTRACE5("getaddresses", "fctx->depth=", fctx->depth);
2883
2884 /*
2885 * Don't pound on remote servers. (Failsafe!)
2886 */
2887 fctx->restarts++;
2888 if (fctx->restarts > 10) {
2889 FCTXTRACE("too many restarts");
2890 return (DNS_R_SERVFAIL);
2891 }
2892
2893 res = fctx->res;
2894
2895 if (fctx->depth > res->maxdepth) {
2896 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
2897 DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
2898 "too much NS indirection resolving '%s' "
2899 "(depth=%u, maxdepth=%u)",
2900 fctx->info, fctx->depth, res->maxdepth);
2901 return (DNS_R_SERVFAIL);
2902 }
2903
2904 /*
2905 * Forwarders.
2906 */
2907
2908 INSIST(ISC_LIST_EMPTY(fctx->forwaddrs));
2909 INSIST(ISC_LIST_EMPTY(fctx->altaddrs));
2910
2911 /*
2912 * If this fctx has forwarders, use them; otherwise use any
2913 * selective forwarders specified in the view; otherwise use the
2914 * resolver's forwarders (if any).
2915 */
2916 sa = ISC_LIST_HEAD(fctx->forwarders);
2917 if (sa == NULL) {
2918 dns_forwarders_t *forwarders = NULL;
2919 dns_name_t *name = &fctx->name;
2920 dns_name_t suffix;
2921 unsigned int labels;
2922 dns_fixedname_t fixed;
2923 dns_name_t *domain;
2924
2925 /*
2926 * DS records are found in the parent server.
2927 * Strip label to get the correct forwarder (if any).
2928 */
2929 if (dns_rdatatype_atparent(fctx->type) &&
2930 dns_name_countlabels(name) > 1) {
2931 dns_name_init(&suffix, NULL);
2932 labels = dns_name_countlabels(name);
2933 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
2934 name = &suffix;
2935 }
2936
2937 dns_fixedname_init(&fixed);
2938 domain = dns_fixedname_name(&fixed);
2939 result = dns_fwdtable_find2(res->view->fwdtable, name,
2940 domain, &forwarders);
2941 if (result == ISC_R_SUCCESS) {
2942 sa = ISC_LIST_HEAD(forwarders->addrs);
2943 fctx->fwdpolicy = forwarders->fwdpolicy;
2944 if (fctx->fwdpolicy == dns_fwdpolicy_only &&
2945 isstrictsubdomain(domain, &fctx->domain)) {
2946 #ifdef ENABLE_FETCHLIMIT
2947 fcount_decr(fctx);
2948 #endif /* ENABLE_FETCHLIMIT */
2949 dns_name_free(&fctx->domain, fctx->mctx);
2950 dns_name_init(&fctx->domain, NULL);
2951 result = dns_name_dup(domain, fctx->mctx,
2952 &fctx->domain);
2953 if (result != ISC_R_SUCCESS)
2954 return (result);
2955 #ifdef ENABLE_FETCHLIMIT
2956 result = fcount_incr(fctx, ISC_TRUE);
2957 if (result != ISC_R_SUCCESS)
2958 return (result);
2959 #endif /* ENABLE_FETCHLIMIT */
2960 }
2961 }
2962 }
2963
2964 while (sa != NULL) {
2965 if ((isc_sockaddr_pf(sa) == AF_INET &&
2966 fctx->res->dispatches4 == NULL) ||
2967 (isc_sockaddr_pf(sa) == AF_INET6 &&
2968 fctx->res->dispatches6 == NULL)) {
2969 sa = ISC_LIST_NEXT(sa, link);
2970 continue;
2971 }
2972 ai = NULL;
2973 result = dns_adb_findaddrinfo(fctx->adb,
2974 sa, &ai, 0); /* XXXMLG */
2975 if (result == ISC_R_SUCCESS) {
2976 dns_adbaddrinfo_t *cur;
2977 ai->flags |= FCTX_ADDRINFO_FORWARDER;
2978 cur = ISC_LIST_HEAD(fctx->forwaddrs);
2979 while (cur != NULL && cur->srtt < ai->srtt)
2980 cur = ISC_LIST_NEXT(cur, publink);
2981 if (cur != NULL)
2982 ISC_LIST_INSERTBEFORE(fctx->forwaddrs, cur,
2983 ai, publink);
2984 else
2985 ISC_LIST_APPEND(fctx->forwaddrs, ai, publink);
2986 }
2987 sa = ISC_LIST_NEXT(sa, link);
2988 }
2989
2990 /*
2991 * If the forwarding policy is "only", we don't need the addresses
2992 * of the nameservers.
2993 */
2994 if (fctx->fwdpolicy == dns_fwdpolicy_only)
2995 goto out;
2996
2997 /*
2998 * Normal nameservers.
2999 */
3000
3001 stdoptions = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
3002 if (fctx->restarts == 1) {
3003 /*
3004 * To avoid sending out a flood of queries likely to
3005 * result in NXRRSET, we suppress fetches for address
3006 * families we don't have the first time through,
3007 * provided that we have addresses in some family we
3008 * can use.
3009 *
3010 * We don't want to set this option all the time, since
3011 * if fctx->restarts > 1, we've clearly been having trouble
3012 * with the addresses we had, so getting more could help.
3013 */
3014 stdoptions |= DNS_ADBFIND_AVOIDFETCHES;
3015 }
3016 if (res->dispatches4 != NULL)
3017 stdoptions |= DNS_ADBFIND_INET;
3018 if (res->dispatches6 != NULL)
3019 stdoptions |= DNS_ADBFIND_INET6;
3020
3021 if ((stdoptions & DNS_ADBFIND_ADDRESSMASK) == 0)
3022 return (DNS_R_SERVFAIL);
3023
3024 isc_stdtime_get(&now);
3025
3026 INSIST(ISC_LIST_EMPTY(fctx->finds));
3027 INSIST(ISC_LIST_EMPTY(fctx->altfinds));
3028
3029 for (result = dns_rdataset_first(&fctx->nameservers);
3030 result == ISC_R_SUCCESS;
3031 result = dns_rdataset_next(&fctx->nameservers))
3032 {
3033 isc_boolean_t overquota = ISC_FALSE;
3034
3035 dns_rdataset_current(&fctx->nameservers, &rdata);
3036 /*
3037 * Extract the name from the NS record.
3038 */
3039 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3040 if (result != ISC_R_SUCCESS)
3041 continue;
3042
3043 findname(fctx, &ns.name, 0, stdoptions, 0, now,
3044 &overquota, &need_alternate);
3045
3046 #ifdef ENABLE_FETCHLIMIT
3047 if (!overquota)
3048 all_spilled = ISC_FALSE;
3049 #endif /* ENABLE_FETCHLIMIT */
3050
3051 dns_rdata_reset(&rdata);
3052 dns_rdata_freestruct(&ns);
3053 }
3054 if (result != ISC_R_NOMORE)
3055 return (result);
3056
3057 /*
3058 * Do we need to use 6 to 4?
3059 */
3060 if (need_alternate) {
3061 int family;
3062 alternate_t *a;
3063 family = (res->dispatches6 != NULL) ? AF_INET6 : AF_INET;
3064 for (a = ISC_LIST_HEAD(res->alternates);
3065 a != NULL;
3066 a = ISC_LIST_NEXT(a, link)) {
3067 if (!a->isaddress) {
3068 findname(fctx, &a->_u._n.name, a->_u._n.port,
3069 stdoptions, FCTX_ADDRINFO_FORWARDER,
3070 now, NULL, NULL);
3071 continue;
3072 }
3073 if (isc_sockaddr_pf(&a->_u.addr) != family)
3074 continue;
3075 ai = NULL;
3076 result = dns_adb_findaddrinfo(fctx->adb, &a->_u.addr,
3077 &ai, 0);
3078 if (result == ISC_R_SUCCESS) {
3079 dns_adbaddrinfo_t *cur;
3080 ai->flags |= FCTX_ADDRINFO_FORWARDER;
3081 cur = ISC_LIST_HEAD(fctx->altaddrs);
3082 while (cur != NULL && cur->srtt < ai->srtt)
3083 cur = ISC_LIST_NEXT(cur, publink);
3084 if (cur != NULL)
3085 ISC_LIST_INSERTBEFORE(fctx->altaddrs,
3086 cur, ai, publink);
3087 else
3088 ISC_LIST_APPEND(fctx->altaddrs, ai,
3089 publink);
3090 }
3091 }
3092 }
3093
3094 out:
3095 /*
3096 * Mark all known bad servers.
3097 */
3098 all_bad = mark_bad(fctx);
3099
3100 /*
3101 * How are we doing?
3102 */
3103 if (all_bad) {
3104 /*
3105 * We've got no addresses.
3106 */
3107 if (fctx->pending > 0) {
3108 /*
3109 * We're fetching the addresses, but don't have any
3110 * yet. Tell the caller to wait for an answer.
3111 */
3112 result = DNS_R_WAIT;
3113 } else {
3114 isc_time_t expire;
3115 isc_interval_t i;
3116 /*
3117 * We've lost completely. We don't know any
3118 * addresses, and the ADB has told us it can't get
3119 * them.
3120 */
3121 FCTXTRACE("no addresses");
3122 isc_interval_set(&i, DNS_BADCACHE_TTL(fctx), 0);
3123 result = isc_time_nowplusinterval(&expire, &i);
3124 if (badcache &&
3125 (fctx->type == dns_rdatatype_dnskey ||
3126 fctx->type == dns_rdatatype_dlv ||
3127 fctx->type == dns_rdatatype_ds) &&
3128 result == ISC_R_SUCCESS)
3129 dns_resolver_addbadcache(res, &fctx->name,
3130 fctx->type, &expire);
3131
3132 #ifdef ENABLE_FETCHLIMIT
3133 /*
3134 * If all of the addresses found were over the
3135 * fetches-per-server quota, return the configured
3136 * response.
3137 */
3138 if (all_spilled) {
3139 result = res->quotaresp[dns_quotatype_server];
3140 inc_stats(res, dns_resstatscounter_serverquota);
3141 } else
3142 result = ISC_R_FAILURE;
3143 #endif /* ENABLE_FETCHLIMIT */
3144 }
3145 } else {
3146 /*
3147 * We've found some addresses. We might still be looking
3148 * for more addresses.
3149 */
3150 sort_finds(&fctx->finds);
3151 sort_finds(&fctx->altfinds);
3152 result = ISC_R_SUCCESS;
3153 }
3154
3155 return (result);
3156 }
3157
3158 static inline void
possibly_mark(fetchctx_t * fctx,dns_adbaddrinfo_t * addr)3159 possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr)
3160 {
3161 isc_netaddr_t na;
3162 char buf[ISC_NETADDR_FORMATSIZE];
3163 isc_sockaddr_t *sa;
3164 isc_boolean_t aborted = ISC_FALSE;
3165 isc_boolean_t bogus;
3166 dns_acl_t *blackhole;
3167 isc_netaddr_t ipaddr;
3168 dns_peer_t *peer = NULL;
3169 dns_resolver_t *res;
3170 const char *msg = NULL;
3171
3172 sa = &addr->sockaddr;
3173
3174 res = fctx->res;
3175 isc_netaddr_fromsockaddr(&ipaddr, sa);
3176 blackhole = dns_dispatchmgr_getblackhole(res->dispatchmgr);
3177 (void) dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
3178
3179 if (blackhole != NULL) {
3180 int match;
3181
3182 if (dns_acl_match(&ipaddr, NULL, blackhole,
3183 &res->view->aclenv,
3184 &match, NULL) == ISC_R_SUCCESS &&
3185 match > 0)
3186 aborted = ISC_TRUE;
3187 }
3188
3189 if (peer != NULL &&
3190 dns_peer_getbogus(peer, &bogus) == ISC_R_SUCCESS &&
3191 bogus)
3192 aborted = ISC_TRUE;
3193
3194 if (aborted) {
3195 addr->flags |= FCTX_ADDRINFO_MARK;
3196 msg = "ignoring blackholed / bogus server: ";
3197 } else if (isc_sockaddr_isnetzero(sa)) {
3198 addr->flags |= FCTX_ADDRINFO_MARK;
3199 msg = "ignoring net zero address: ";
3200 } else if (isc_sockaddr_ismulticast(sa)) {
3201 addr->flags |= FCTX_ADDRINFO_MARK;
3202 msg = "ignoring multicast address: ";
3203 } else if (isc_sockaddr_isexperimental(sa)) {
3204 addr->flags |= FCTX_ADDRINFO_MARK;
3205 msg = "ignoring experimental address: ";
3206 } else if (sa->type.sa.sa_family != AF_INET6) {
3207 return;
3208 } else if (IN6_IS_ADDR_V4MAPPED(&sa->type.sin6.sin6_addr)) {
3209 addr->flags |= FCTX_ADDRINFO_MARK;
3210 msg = "ignoring IPv6 mapped IPV4 address: ";
3211 } else if (IN6_IS_ADDR_V4COMPAT(&sa->type.sin6.sin6_addr)) {
3212 addr->flags |= FCTX_ADDRINFO_MARK;
3213 msg = "ignoring IPv6 compatibility IPV4 address: ";
3214 } else
3215 return;
3216
3217 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
3218 isc_netaddr_fromsockaddr(&na, sa);
3219 isc_netaddr_format(&na, buf, sizeof(buf));
3220 FCTXTRACE2(msg, buf);
3221 }
3222 }
3223
3224 static inline dns_adbaddrinfo_t *
fctx_nextaddress(fetchctx_t * fctx)3225 fctx_nextaddress(fetchctx_t *fctx) {
3226 dns_adbfind_t *find, *start;
3227 dns_adbaddrinfo_t *addrinfo;
3228 dns_adbaddrinfo_t *faddrinfo;
3229
3230 /*
3231 * Return the next untried address, if any.
3232 */
3233
3234 /*
3235 * Find the first unmarked forwarder (if any).
3236 */
3237 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
3238 addrinfo != NULL;
3239 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
3240 if (!UNMARKED(addrinfo))
3241 continue;
3242 possibly_mark(fctx, addrinfo);
3243 if (UNMARKED(addrinfo)) {
3244 addrinfo->flags |= FCTX_ADDRINFO_MARK;
3245 fctx->find = NULL;
3246 return (addrinfo);
3247 }
3248 }
3249
3250 /*
3251 * No forwarders. Move to the next find.
3252 */
3253
3254 fctx->attributes |= FCTX_ATTR_TRIEDFIND;
3255
3256 find = fctx->find;
3257 if (find == NULL)
3258 find = ISC_LIST_HEAD(fctx->finds);
3259 else {
3260 find = ISC_LIST_NEXT(find, publink);
3261 if (find == NULL)
3262 find = ISC_LIST_HEAD(fctx->finds);
3263 }
3264
3265 /*
3266 * Find the first unmarked addrinfo.
3267 */
3268 addrinfo = NULL;
3269 if (find != NULL) {
3270 start = find;
3271 do {
3272 for (addrinfo = ISC_LIST_HEAD(find->list);
3273 addrinfo != NULL;
3274 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
3275 if (!UNMARKED(addrinfo))
3276 continue;
3277 possibly_mark(fctx, addrinfo);
3278 if (UNMARKED(addrinfo)) {
3279 addrinfo->flags |= FCTX_ADDRINFO_MARK;
3280 break;
3281 }
3282 }
3283 if (addrinfo != NULL)
3284 break;
3285 find = ISC_LIST_NEXT(find, publink);
3286 if (find == NULL)
3287 find = ISC_LIST_HEAD(fctx->finds);
3288 } while (find != start);
3289 }
3290
3291 fctx->find = find;
3292 if (addrinfo != NULL)
3293 return (addrinfo);
3294
3295 /*
3296 * No nameservers left. Try alternates.
3297 */
3298
3299 fctx->attributes |= FCTX_ATTR_TRIEDALT;
3300
3301 find = fctx->altfind;
3302 if (find == NULL)
3303 find = ISC_LIST_HEAD(fctx->altfinds);
3304 else {
3305 find = ISC_LIST_NEXT(find, publink);
3306 if (find == NULL)
3307 find = ISC_LIST_HEAD(fctx->altfinds);
3308 }
3309
3310 /*
3311 * Find the first unmarked addrinfo.
3312 */
3313 addrinfo = NULL;
3314 if (find != NULL) {
3315 start = find;
3316 do {
3317 for (addrinfo = ISC_LIST_HEAD(find->list);
3318 addrinfo != NULL;
3319 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
3320 if (!UNMARKED(addrinfo))
3321 continue;
3322 possibly_mark(fctx, addrinfo);
3323 if (UNMARKED(addrinfo)) {
3324 addrinfo->flags |= FCTX_ADDRINFO_MARK;
3325 break;
3326 }
3327 }
3328 if (addrinfo != NULL)
3329 break;
3330 find = ISC_LIST_NEXT(find, publink);
3331 if (find == NULL)
3332 find = ISC_LIST_HEAD(fctx->altfinds);
3333 } while (find != start);
3334 }
3335
3336 faddrinfo = addrinfo;
3337
3338 /*
3339 * See if we have a better alternate server by address.
3340 */
3341
3342 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
3343 addrinfo != NULL;
3344 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
3345 if (!UNMARKED(addrinfo))
3346 continue;
3347 possibly_mark(fctx, addrinfo);
3348 if (UNMARKED(addrinfo) &&
3349 (faddrinfo == NULL ||
3350 addrinfo->srtt < faddrinfo->srtt)) {
3351 if (faddrinfo != NULL)
3352 faddrinfo->flags &= ~FCTX_ADDRINFO_MARK;
3353 addrinfo->flags |= FCTX_ADDRINFO_MARK;
3354 break;
3355 }
3356 }
3357
3358 if (addrinfo == NULL) {
3359 addrinfo = faddrinfo;
3360 fctx->altfind = find;
3361 }
3362
3363 return (addrinfo);
3364 }
3365
3366 static void
fctx_try(fetchctx_t * fctx,isc_boolean_t retrying,isc_boolean_t badcache)3367 fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
3368 isc_result_t result;
3369 dns_adbaddrinfo_t *addrinfo = NULL;
3370 dns_resolver_t *res;
3371 unsigned int bucketnum;
3372 isc_boolean_t bucket_empty;
3373
3374 FCTXTRACE5("try", "fctx->qc=", isc_counter_used(fctx->qc));
3375
3376 REQUIRE(!ADDRWAIT(fctx));
3377
3378 res = fctx->res;
3379
3380 /* We've already exceeded maximum query count */
3381 if (isc_counter_used(fctx->qc) > res->maxqueries) {
3382 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
3383 DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
3384 "exceeded max queries resolving '%s' "
3385 "(querycount=%u, maxqueries=%u)",
3386 fctx->info,
3387 isc_counter_used(fctx->qc), res->maxqueries);
3388 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
3389 return;
3390 }
3391
3392 #ifdef ENABLE_FETCHLIMIT
3393 /* Try to find an address that isn't over quota */
3394 while ((addrinfo = fctx_nextaddress(fctx)) != NULL)
3395 if (! dns_adbentry_overquota(addrinfo->entry))
3396 break;
3397 #endif /* ENABLE_FETCHLIMIT */
3398
3399 if (addrinfo == NULL) {
3400 /* We have no more addresses. Start over. */
3401 fctx_cancelqueries(fctx, ISC_TRUE, ISC_FALSE);
3402 fctx_cleanupfinds(fctx);
3403 fctx_cleanupaltfinds(fctx);
3404 fctx_cleanupforwaddrs(fctx);
3405 fctx_cleanupaltaddrs(fctx);
3406 result = fctx_getaddresses(fctx, badcache);
3407 if (result == DNS_R_WAIT) {
3408 /*
3409 * Sleep waiting for addresses.
3410 */
3411 FCTXTRACE("addrwait");
3412 fctx->attributes |= FCTX_ATTR_ADDRWAIT;
3413 return;
3414 } else if (result != ISC_R_SUCCESS) {
3415 /*
3416 * Something bad happened.
3417 */
3418 fctx_done(fctx, result, __LINE__);
3419 return;
3420 }
3421
3422 #ifdef ENABLE_FETCHLIMIT
3423 while ((addrinfo = fctx_nextaddress(fctx)) != NULL) {
3424 if (! dns_adbentry_overquota(addrinfo->entry))
3425 break;
3426 }
3427 #else
3428 addrinfo = fctx_nextaddress(fctx);
3429 #endif /* !ENABLE_FETCHLIMIT */
3430
3431 /*
3432 * While we may have addresses from the ADB, they
3433 * might be bad ones. In this case, return SERVFAIL.
3434 */
3435 if (addrinfo == NULL) {
3436 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
3437 return;
3438 }
3439 }
3440
3441 if (dns_name_countlabels(&fctx->domain) > 2) {
3442 result = isc_counter_increment(fctx->qc);
3443 if (result != ISC_R_SUCCESS) {
3444 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
3445 DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
3446 "exceeded max queries resolving '%s'",
3447 fctx->info);
3448 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
3449 return;
3450 }
3451 }
3452
3453 bucketnum = fctx->bucketnum;
3454 fctx_increference(fctx);
3455 result = fctx_query(fctx, addrinfo, fctx->options);
3456 if (result != ISC_R_SUCCESS) {
3457 fctx_done(fctx, result, __LINE__);
3458 LOCK(&res->buckets[bucketnum].lock);
3459 bucket_empty = fctx_decreference(fctx);
3460 UNLOCK(&res->buckets[bucketnum].lock);
3461 if (bucket_empty)
3462 empty_bucket(res);
3463 } else if (retrying)
3464 inc_stats(res, dns_resstatscounter_retry);
3465 }
3466
3467 static isc_boolean_t
fctx_unlink(fetchctx_t * fctx)3468 fctx_unlink(fetchctx_t *fctx) {
3469 dns_resolver_t *res;
3470 unsigned int bucketnum;
3471
3472 /*
3473 * Caller must be holding the bucket lock.
3474 */
3475
3476 REQUIRE(VALID_FCTX(fctx));
3477 REQUIRE(fctx->state == fetchstate_done ||
3478 fctx->state == fetchstate_init);
3479 REQUIRE(ISC_LIST_EMPTY(fctx->events));
3480 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
3481 REQUIRE(ISC_LIST_EMPTY(fctx->finds));
3482 REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
3483 REQUIRE(fctx->pending == 0);
3484 REQUIRE(fctx->references == 0);
3485 REQUIRE(ISC_LIST_EMPTY(fctx->validators));
3486
3487 FCTXTRACE("unlink");
3488
3489 res = fctx->res;
3490 bucketnum = fctx->bucketnum;
3491
3492 ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link);
3493
3494 LOCK(&res->nlock);
3495 res->nfctx--;
3496 UNLOCK(&res->nlock);
3497
3498 if (res->buckets[bucketnum].exiting &&
3499 ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs))
3500 return (ISC_TRUE);
3501
3502 return (ISC_FALSE);
3503 }
3504
3505 static void
fctx_destroy(fetchctx_t * fctx)3506 fctx_destroy(fetchctx_t *fctx) {
3507 isc_sockaddr_t *sa, *next_sa;
3508
3509 REQUIRE(VALID_FCTX(fctx));
3510 REQUIRE(fctx->state == fetchstate_done ||
3511 fctx->state == fetchstate_init);
3512 REQUIRE(ISC_LIST_EMPTY(fctx->events));
3513 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
3514 REQUIRE(ISC_LIST_EMPTY(fctx->finds));
3515 REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
3516 REQUIRE(fctx->pending == 0);
3517 REQUIRE(fctx->references == 0);
3518 REQUIRE(ISC_LIST_EMPTY(fctx->validators));
3519 REQUIRE(!ISC_LINK_LINKED(fctx, link));
3520
3521 FCTXTRACE("destroy");
3522
3523 /*
3524 * Free bad.
3525 */
3526 for (sa = ISC_LIST_HEAD(fctx->bad);
3527 sa != NULL;
3528 sa = next_sa) {
3529 next_sa = ISC_LIST_NEXT(sa, link);
3530 ISC_LIST_UNLINK(fctx->bad, sa, link);
3531 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
3532 }
3533
3534 for (sa = ISC_LIST_HEAD(fctx->edns);
3535 sa != NULL;
3536 sa = next_sa) {
3537 next_sa = ISC_LIST_NEXT(sa, link);
3538 ISC_LIST_UNLINK(fctx->edns, sa, link);
3539 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
3540 }
3541
3542 for (sa = ISC_LIST_HEAD(fctx->edns512);
3543 sa != NULL;
3544 sa = next_sa) {
3545 next_sa = ISC_LIST_NEXT(sa, link);
3546 ISC_LIST_UNLINK(fctx->edns512, sa, link);
3547 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
3548 }
3549
3550 for (sa = ISC_LIST_HEAD(fctx->bad_edns);
3551 sa != NULL;
3552 sa = next_sa) {
3553 next_sa = ISC_LIST_NEXT(sa, link);
3554 ISC_LIST_UNLINK(fctx->bad_edns, sa, link);
3555 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
3556 }
3557
3558 isc_counter_detach(&fctx->qc);
3559
3560 #ifdef ENABLE_FETCHLIMIT
3561 fcount_decr(fctx);
3562 #endif /* ENABLE_FETCHLIMIT */
3563
3564 isc_timer_detach(&fctx->timer);
3565 dns_message_destroy(&fctx->rmessage);
3566 dns_message_destroy(&fctx->qmessage);
3567 if (dns_name_countlabels(&fctx->domain) > 0)
3568 dns_name_free(&fctx->domain, fctx->mctx);
3569 if (dns_rdataset_isassociated(&fctx->nameservers))
3570 dns_rdataset_disassociate(&fctx->nameservers);
3571 dns_name_free(&fctx->name, fctx->mctx);
3572 dns_db_detach(&fctx->cache);
3573 dns_adb_detach(&fctx->adb);
3574 isc_mem_free(fctx->mctx, fctx->info);
3575 isc_mem_putanddetach(&fctx->mctx, fctx, sizeof(*fctx));
3576 }
3577
3578 /*
3579 * Fetch event handlers.
3580 */
3581
3582 static void
fctx_timeout(isc_task_t * task,isc_event_t * event)3583 fctx_timeout(isc_task_t *task, isc_event_t *event) {
3584 fetchctx_t *fctx = event->ev_arg;
3585 isc_timerevent_t *tevent = (isc_timerevent_t *)event;
3586 resquery_t *query;
3587
3588 REQUIRE(VALID_FCTX(fctx));
3589
3590 UNUSED(task);
3591
3592 FCTXTRACE("timeout");
3593
3594 inc_stats(fctx->res, dns_resstatscounter_querytimeout);
3595
3596 if (event->ev_type == ISC_TIMEREVENT_LIFE) {
3597 fctx->reason = NULL;
3598 fctx_done(fctx, ISC_R_TIMEDOUT, __LINE__);
3599 } else {
3600 isc_result_t result;
3601
3602 fctx->timeouts++;
3603 fctx->timeout = ISC_TRUE;
3604
3605 /*
3606 * We could cancel the running queries here, or we could let
3607 * them keep going. Since we normally use separate sockets for
3608 * different queries, we adopt the former approach to reduce
3609 * the number of open sockets: cancel the oldest query if it
3610 * expired after the query had started (this is usually the
3611 * case but is not always so, depending on the task schedule
3612 * timing).
3613 */
3614 query = ISC_LIST_HEAD(fctx->queries);
3615 if (query != NULL &&
3616 isc_time_compare(&tevent->due, &query->start) >= 0)
3617 {
3618 FCTXTRACE("query timed out; no response");
3619 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE, ISC_FALSE);
3620 }
3621 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
3622
3623 /*
3624 * Our timer has triggered. Reestablish the fctx lifetime
3625 * timer.
3626 */
3627 result = fctx_starttimer(fctx);
3628 if (result != ISC_R_SUCCESS)
3629 fctx_done(fctx, result, __LINE__);
3630 else
3631 /*
3632 * Keep trying.
3633 */
3634 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
3635 }
3636
3637 isc_event_free(&event);
3638 }
3639
3640 static void
fctx_shutdown(fetchctx_t * fctx)3641 fctx_shutdown(fetchctx_t *fctx) {
3642 isc_event_t *cevent;
3643
3644 /*
3645 * Start the shutdown process for fctx, if it isn't already underway.
3646 */
3647
3648 FCTXTRACE("shutdown");
3649
3650 /*
3651 * The caller must be holding the appropriate bucket lock.
3652 */
3653
3654 if (fctx->want_shutdown)
3655 return;
3656
3657 fctx->want_shutdown = ISC_TRUE;
3658
3659 /*
3660 * Unless we're still initializing (in which case the
3661 * control event is still outstanding), we need to post
3662 * the control event to tell the fetch we want it to
3663 * exit.
3664 */
3665 if (fctx->state != fetchstate_init) {
3666 cevent = &fctx->control_event;
3667 isc_task_send(fctx->res->buckets[fctx->bucketnum].task,
3668 &cevent);
3669 }
3670 }
3671
3672 static void
fctx_doshutdown(isc_task_t * task,isc_event_t * event)3673 fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
3674 fetchctx_t *fctx = event->ev_arg;
3675 isc_boolean_t bucket_empty = ISC_FALSE;
3676 dns_resolver_t *res;
3677 unsigned int bucketnum;
3678 dns_validator_t *validator;
3679 isc_boolean_t dodestroy = ISC_FALSE;
3680
3681 REQUIRE(VALID_FCTX(fctx));
3682
3683 UNUSED(task);
3684
3685 res = fctx->res;
3686 bucketnum = fctx->bucketnum;
3687
3688 FCTXTRACE("doshutdown");
3689
3690 /*
3691 * An fctx that is shutting down is no longer in ADDRWAIT mode.
3692 */
3693 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
3694
3695 /*
3696 * Cancel all pending validators. Note that this must be done
3697 * without the bucket lock held, since that could cause deadlock.
3698 */
3699 validator = ISC_LIST_HEAD(fctx->validators);
3700 while (validator != NULL) {
3701 dns_validator_cancel(validator);
3702 validator = ISC_LIST_NEXT(validator, link);
3703 }
3704
3705 if (fctx->nsfetch != NULL)
3706 dns_resolver_cancelfetch(fctx->nsfetch);
3707
3708 /*
3709 * Shut down anything that is still running on behalf of this
3710 * fetch. To avoid deadlock with the ADB, we must do this
3711 * before we lock the bucket lock.
3712 */
3713 fctx_stopeverything(fctx, ISC_FALSE, ISC_FALSE);
3714
3715 LOCK(&res->buckets[bucketnum].lock);
3716
3717 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
3718
3719 INSIST(fctx->state == fetchstate_active ||
3720 fctx->state == fetchstate_done);
3721 INSIST(fctx->want_shutdown);
3722
3723 if (fctx->state != fetchstate_done) {
3724 fctx->state = fetchstate_done;
3725 fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
3726 }
3727
3728 if (fctx->references == 0 && fctx->pending == 0 &&
3729 fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
3730 bucket_empty = fctx_unlink(fctx);
3731 dodestroy = ISC_TRUE;
3732 }
3733
3734 UNLOCK(&res->buckets[bucketnum].lock);
3735
3736 if (dodestroy) {
3737 fctx_destroy(fctx);
3738 if (bucket_empty)
3739 empty_bucket(res);
3740 }
3741 }
3742
3743 static void
fctx_start(isc_task_t * task,isc_event_t * event)3744 fctx_start(isc_task_t *task, isc_event_t *event) {
3745 fetchctx_t *fctx = event->ev_arg;
3746 isc_boolean_t done = ISC_FALSE, bucket_empty = ISC_FALSE;
3747 dns_resolver_t *res;
3748 unsigned int bucketnum;
3749 isc_boolean_t dodestroy = ISC_FALSE;
3750
3751 REQUIRE(VALID_FCTX(fctx));
3752
3753 UNUSED(task);
3754
3755 res = fctx->res;
3756 bucketnum = fctx->bucketnum;
3757
3758 FCTXTRACE("start");
3759
3760 LOCK(&res->buckets[bucketnum].lock);
3761
3762 INSIST(fctx->state == fetchstate_init);
3763 if (fctx->want_shutdown) {
3764 /*
3765 * We haven't started this fctx yet, and we've been requested
3766 * to shut it down.
3767 */
3768 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
3769 fctx->state = fetchstate_done;
3770 fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
3771 /*
3772 * Since we haven't started, we INSIST that we have no
3773 * pending ADB finds and no pending validations.
3774 */
3775 INSIST(fctx->pending == 0);
3776 INSIST(fctx->nqueries == 0);
3777 INSIST(ISC_LIST_EMPTY(fctx->validators));
3778 if (fctx->references == 0) {
3779 /*
3780 * It's now safe to destroy this fctx.
3781 */
3782 bucket_empty = fctx_unlink(fctx);
3783 dodestroy = ISC_TRUE;
3784 }
3785 done = ISC_TRUE;
3786 } else {
3787 /*
3788 * Normal fctx startup.
3789 */
3790 fctx->state = fetchstate_active;
3791 /*
3792 * Reset the control event for later use in shutting down
3793 * the fctx.
3794 */
3795 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
3796 DNS_EVENT_FETCHCONTROL, fctx_doshutdown, fctx,
3797 NULL, NULL, NULL);
3798 }
3799
3800 UNLOCK(&res->buckets[bucketnum].lock);
3801
3802 if (!done) {
3803 isc_result_t result;
3804
3805 INSIST(!dodestroy);
3806
3807 /*
3808 * All is well. Start working on the fetch.
3809 */
3810 result = fctx_starttimer(fctx);
3811 if (result != ISC_R_SUCCESS)
3812 fctx_done(fctx, result, __LINE__);
3813 else
3814 fctx_try(fctx, ISC_FALSE, ISC_FALSE);
3815 } else if (dodestroy) {
3816 fctx_destroy(fctx);
3817 if (bucket_empty)
3818 empty_bucket(res);
3819 }
3820 }
3821
3822 /*
3823 * Fetch Creation, Joining, and Cancelation.
3824 */
3825
3826 static inline isc_result_t
fctx_join(fetchctx_t * fctx,isc_task_t * task,isc_sockaddr_t * client,dns_messageid_t id,isc_taskaction_t action,void * arg,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset,dns_fetch_t * fetch)3827 fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_sockaddr_t *client,
3828 dns_messageid_t id, isc_taskaction_t action, void *arg,
3829 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
3830 dns_fetch_t *fetch)
3831 {
3832 isc_task_t *clone;
3833 dns_fetchevent_t *event;
3834
3835 FCTXTRACE("join");
3836
3837 /*
3838 * We store the task we're going to send this event to in the
3839 * sender field. We'll make the fetch the sender when we actually
3840 * send the event.
3841 */
3842 clone = NULL;
3843 isc_task_attach(task, &clone);
3844 event = (dns_fetchevent_t *)
3845 isc_event_allocate(fctx->res->mctx, clone, DNS_EVENT_FETCHDONE,
3846 action, arg, sizeof(*event));
3847 if (event == NULL) {
3848 isc_task_detach(&clone);
3849 return (ISC_R_NOMEMORY);
3850 }
3851 event->result = DNS_R_SERVFAIL;
3852 event->qtype = fctx->type;
3853 event->db = NULL;
3854 event->node = NULL;
3855 event->rdataset = rdataset;
3856 event->sigrdataset = sigrdataset;
3857 event->fetch = fetch;
3858 event->client = client;
3859 event->id = id;
3860 dns_fixedname_init(&event->foundname);
3861
3862 /*
3863 * Make sure that we can store the sigrdataset in the
3864 * first event if it is needed by any of the events.
3865 */
3866 if (event->sigrdataset != NULL)
3867 ISC_LIST_PREPEND(fctx->events, event, ev_link);
3868 else
3869 ISC_LIST_APPEND(fctx->events, event, ev_link);
3870 fctx->references++;
3871 fctx->client = client;
3872
3873 fetch->magic = DNS_FETCH_MAGIC;
3874 fetch->private = fctx;
3875
3876 return (ISC_R_SUCCESS);
3877 }
3878
3879 static inline void
log_ns_ttl(fetchctx_t * fctx,const char * where)3880 log_ns_ttl(fetchctx_t *fctx, const char *where) {
3881 char namebuf[DNS_NAME_FORMATSIZE];
3882 char domainbuf[DNS_NAME_FORMATSIZE];
3883
3884 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
3885 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
3886 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
3887 DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
3888 "log_ns_ttl: fctx %p: %s: %s (in '%s'?): %u %u",
3889 fctx, where, namebuf, domainbuf,
3890 fctx->ns_ttl_ok, fctx->ns_ttl);
3891 }
3892
3893 static isc_result_t
fctx_create(dns_resolver_t * res,dns_name_t * name,dns_rdatatype_t type,dns_name_t * domain,dns_rdataset_t * nameservers,unsigned int options,unsigned int bucketnum,unsigned int depth,isc_counter_t * qc,fetchctx_t ** fctxp)3894 fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
3895 dns_name_t *domain, dns_rdataset_t *nameservers,
3896 unsigned int options, unsigned int bucketnum, unsigned int depth,
3897 isc_counter_t *qc, fetchctx_t **fctxp)
3898 {
3899 fetchctx_t *fctx;
3900 isc_result_t result;
3901 isc_result_t iresult;
3902 isc_interval_t interval;
3903 dns_fixedname_t fixed;
3904 unsigned int findoptions = 0;
3905 char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
3906 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3907 isc_mem_t *mctx;
3908
3909 /*
3910 * Caller must be holding the lock for bucket number 'bucketnum'.
3911 */
3912 REQUIRE(fctxp != NULL && *fctxp == NULL);
3913
3914 mctx = res->buckets[bucketnum].mctx;
3915 fctx = isc_mem_get(mctx, sizeof(*fctx));
3916 if (fctx == NULL)
3917 return (ISC_R_NOMEMORY);
3918
3919 fctx->qc = NULL;
3920 if (qc != NULL) {
3921 isc_counter_attach(qc, &fctx->qc);
3922 } else {
3923 result = isc_counter_create(res->mctx,
3924 res->maxqueries, &fctx->qc);
3925 if (result != ISC_R_SUCCESS)
3926 goto cleanup_fetch;
3927 }
3928
3929 /*
3930 * Make fctx->info point to a copy of a formatted string
3931 * "name/type".
3932 */
3933 dns_name_format(name, buf, sizeof(buf));
3934 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
3935 strcat(buf, "/"); /* checked */
3936 strcat(buf, typebuf); /* checked */
3937 fctx->info = isc_mem_strdup(mctx, buf);
3938 if (fctx->info == NULL) {
3939 result = ISC_R_NOMEMORY;
3940 goto cleanup_counter;
3941 }
3942
3943 FCTXTRACE("create");
3944 dns_name_init(&fctx->name, NULL);
3945 result = dns_name_dup(name, mctx, &fctx->name);
3946 if (result != ISC_R_SUCCESS)
3947 goto cleanup_info;
3948 dns_name_init(&fctx->domain, NULL);
3949 dns_rdataset_init(&fctx->nameservers);
3950
3951 fctx->type = type;
3952 fctx->options = options;
3953 /*
3954 * Note! We do not attach to the task. We are relying on the
3955 * resolver to ensure that this task doesn't go away while we are
3956 * using it.
3957 */
3958 fctx->res = res;
3959 fctx->references = 0;
3960 fctx->bucketnum = bucketnum;
3961 fctx->dbucketnum = RES_NOBUCKET;
3962 fctx->state = fetchstate_init;
3963 fctx->want_shutdown = ISC_FALSE;
3964 fctx->cloned = ISC_FALSE;
3965 fctx->depth = depth;
3966 ISC_LIST_INIT(fctx->queries);
3967 ISC_LIST_INIT(fctx->finds);
3968 ISC_LIST_INIT(fctx->altfinds);
3969 ISC_LIST_INIT(fctx->forwaddrs);
3970 ISC_LIST_INIT(fctx->altaddrs);
3971 ISC_LIST_INIT(fctx->forwarders);
3972 fctx->fwdpolicy = dns_fwdpolicy_none;
3973 ISC_LIST_INIT(fctx->bad);
3974 ISC_LIST_INIT(fctx->edns);
3975 ISC_LIST_INIT(fctx->edns512);
3976 ISC_LIST_INIT(fctx->bad_edns);
3977 ISC_LIST_INIT(fctx->validators);
3978 fctx->validator = NULL;
3979 fctx->find = NULL;
3980 fctx->altfind = NULL;
3981 fctx->pending = 0;
3982 fctx->restarts = 0;
3983 fctx->querysent = 0;
3984 fctx->referrals = 0;
3985 TIME_NOW(&fctx->start);
3986 fctx->timeouts = 0;
3987 fctx->lamecount = 0;
3988 fctx->quotacount = 0;
3989 fctx->adberr = 0;
3990 fctx->neterr = 0;
3991 fctx->badresp = 0;
3992 fctx->findfail = 0;
3993 fctx->valfail = 0;
3994 fctx->result = ISC_R_FAILURE;
3995 fctx->vresult = ISC_R_SUCCESS;
3996 fctx->exitline = -1; /* sentinel */
3997 fctx->logged = ISC_FALSE;
3998 fctx->attributes = 0;
3999 fctx->spilled = ISC_FALSE;
4000 fctx->nqueries = 0;
4001 fctx->reason = NULL;
4002 fctx->rand_buf = 0;
4003 fctx->rand_bits = 0;
4004 fctx->timeout = ISC_FALSE;
4005 fctx->addrinfo = NULL;
4006 fctx->client = NULL;
4007 fctx->ns_ttl = 0;
4008 fctx->ns_ttl_ok = ISC_FALSE;
4009
4010 dns_name_init(&fctx->nsname, NULL);
4011 fctx->nsfetch = NULL;
4012 dns_rdataset_init(&fctx->nsrrset);
4013
4014 if (domain == NULL) {
4015 dns_forwarders_t *forwarders = NULL;
4016 unsigned int labels;
4017 dns_name_t *fwdname = name;
4018 dns_name_t suffix;
4019
4020 /*
4021 * DS records are found in the parent server. Strip one
4022 * leading label from the name (to be used in finding
4023 * the forwarder).
4024 */
4025 if (dns_rdatatype_atparent(fctx->type) &&
4026 dns_name_countlabels(name) > 1) {
4027 dns_name_init(&suffix, NULL);
4028 labels = dns_name_countlabels(name);
4029 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
4030 fwdname = &suffix;
4031 }
4032
4033 /* Find the forwarder for this name. */
4034 dns_fixedname_init(&fixed);
4035 domain = dns_fixedname_name(&fixed);
4036 result = dns_fwdtable_find2(fctx->res->view->fwdtable, fwdname,
4037 domain, &forwarders);
4038 if (result == ISC_R_SUCCESS)
4039 fctx->fwdpolicy = forwarders->fwdpolicy;
4040
4041 if (fctx->fwdpolicy != dns_fwdpolicy_only) {
4042 /*
4043 * The caller didn't supply a query domain and
4044 * nameservers, and we're not in forward-only mode,
4045 * so find the best nameservers to use.
4046 */
4047 if (dns_rdatatype_atparent(fctx->type))
4048 findoptions |= DNS_DBFIND_NOEXACT;
4049 result = dns_view_findzonecut(res->view, name,
4050 domain, 0, findoptions,
4051 ISC_TRUE,
4052 &fctx->nameservers,
4053 NULL);
4054 if (result != ISC_R_SUCCESS)
4055 goto cleanup_nameservers;
4056
4057 result = dns_name_dup(domain, mctx, &fctx->domain);
4058 if (result != ISC_R_SUCCESS)
4059 goto cleanup_nameservers;
4060
4061 fctx->ns_ttl = fctx->nameservers.ttl;
4062 fctx->ns_ttl_ok = ISC_TRUE;
4063 } else {
4064 /*
4065 * We're in forward-only mode. Set the query domain.
4066 */
4067 result = dns_name_dup(domain, mctx, &fctx->domain);
4068 if (result != ISC_R_SUCCESS)
4069 goto cleanup_name;
4070 }
4071 } else {
4072 result = dns_name_dup(domain, mctx, &fctx->domain);
4073 if (result != ISC_R_SUCCESS)
4074 goto cleanup_name;
4075 dns_rdataset_clone(nameservers, &fctx->nameservers);
4076 fctx->ns_ttl = fctx->nameservers.ttl;
4077 fctx->ns_ttl_ok = ISC_TRUE;
4078 }
4079
4080 #ifdef ENABLE_FETCHLIMIT
4081 /*
4082 * Are there too many simultaneous queries for this domain?
4083 */
4084 result = fcount_incr(fctx, ISC_FALSE);
4085 if (result != ISC_R_SUCCESS) {
4086 result = fctx->res->quotaresp[dns_quotatype_zone];
4087 inc_stats(res, dns_resstatscounter_zonequota);
4088 goto cleanup_domain;
4089 }
4090 #endif /* ENABLE_FETCHLIMIT */
4091
4092 log_ns_ttl(fctx, "fctx_create");
4093
4094 INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
4095
4096 fctx->qmessage = NULL;
4097 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
4098 &fctx->qmessage);
4099
4100 if (result != ISC_R_SUCCESS)
4101 #ifdef ENABLE_FETCHLIMIT
4102 goto cleanup_fcount;
4103 #else
4104 goto cleanup_domain;
4105 #endif /* !ENABLE_FETCHLIMIT */
4106
4107 fctx->rmessage = NULL;
4108 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
4109 &fctx->rmessage);
4110
4111 if (result != ISC_R_SUCCESS)
4112 goto cleanup_qmessage;
4113
4114 /*
4115 * Compute an expiration time for the entire fetch.
4116 */
4117 isc_interval_set(&interval, res->query_timeout, 0);
4118 iresult = isc_time_nowplusinterval(&fctx->expires, &interval);
4119 if (iresult != ISC_R_SUCCESS) {
4120 UNEXPECTED_ERROR(__FILE__, __LINE__,
4121 "isc_time_nowplusinterval: %s",
4122 isc_result_totext(iresult));
4123 result = ISC_R_UNEXPECTED;
4124 goto cleanup_rmessage;
4125 }
4126
4127 /*
4128 * Default retry interval initialization. We set the interval now
4129 * mostly so it won't be uninitialized. It will be set to the
4130 * correct value before a query is issued.
4131 */
4132 isc_interval_set(&fctx->interval, 2, 0);
4133
4134 /*
4135 * Create an inactive timer. It will be made active when the fetch
4136 * is actually started.
4137 */
4138 fctx->timer = NULL;
4139 iresult = isc_timer_create(res->timermgr, isc_timertype_inactive,
4140 NULL, NULL,
4141 res->buckets[bucketnum].task, fctx_timeout,
4142 fctx, &fctx->timer);
4143 if (iresult != ISC_R_SUCCESS) {
4144 UNEXPECTED_ERROR(__FILE__, __LINE__,
4145 "isc_timer_create: %s",
4146 isc_result_totext(iresult));
4147 result = ISC_R_UNEXPECTED;
4148 goto cleanup_rmessage;
4149 }
4150
4151 /*
4152 * Attach to the view's cache and adb.
4153 */
4154 fctx->cache = NULL;
4155 dns_db_attach(res->view->cachedb, &fctx->cache);
4156 fctx->adb = NULL;
4157 dns_adb_attach(res->view->adb, &fctx->adb);
4158 fctx->mctx = NULL;
4159 isc_mem_attach(mctx, &fctx->mctx);
4160
4161 ISC_LIST_INIT(fctx->events);
4162 ISC_LINK_INIT(fctx, link);
4163 fctx->magic = FCTX_MAGIC;
4164
4165 ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link);
4166
4167 LOCK(&res->nlock);
4168 res->nfctx++;
4169 UNLOCK(&res->nlock);
4170
4171 *fctxp = fctx;
4172
4173 return (ISC_R_SUCCESS);
4174
4175 cleanup_rmessage:
4176 dns_message_destroy(&fctx->rmessage);
4177
4178 cleanup_qmessage:
4179 dns_message_destroy(&fctx->qmessage);
4180
4181 #ifdef ENABLE_FETCHLIMIT
4182 cleanup_fcount:
4183 fcount_decr(fctx);
4184 #endif /* ENABLE_FETCHLIMIT */
4185
4186 cleanup_domain:
4187 if (dns_name_countlabels(&fctx->domain) > 0)
4188 dns_name_free(&fctx->domain, mctx);
4189
4190 cleanup_nameservers:
4191 if (dns_rdataset_isassociated(&fctx->nameservers))
4192 dns_rdataset_disassociate(&fctx->nameservers);
4193
4194 cleanup_name:
4195 dns_name_free(&fctx->name, mctx);
4196
4197 cleanup_info:
4198 isc_mem_free(mctx, fctx->info);
4199
4200 cleanup_counter:
4201 isc_counter_detach(&fctx->qc);
4202
4203 cleanup_fetch:
4204 isc_mem_put(mctx, fctx, sizeof(*fctx));
4205
4206 return (result);
4207 }
4208
4209 /*
4210 * Handle Responses
4211 */
4212 static inline isc_boolean_t
is_lame(fetchctx_t * fctx)4213 is_lame(fetchctx_t *fctx) {
4214 dns_message_t *message = fctx->rmessage;
4215 dns_name_t *name;
4216 dns_rdataset_t *rdataset;
4217 isc_result_t result;
4218
4219 if (message->rcode != dns_rcode_noerror &&
4220 message->rcode != dns_rcode_nxdomain)
4221 return (ISC_FALSE);
4222
4223 if (message->counts[DNS_SECTION_ANSWER] != 0)
4224 return (ISC_FALSE);
4225
4226 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
4227 return (ISC_FALSE);
4228
4229 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
4230 while (result == ISC_R_SUCCESS) {
4231 name = NULL;
4232 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
4233 for (rdataset = ISC_LIST_HEAD(name->list);
4234 rdataset != NULL;
4235 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4236 dns_namereln_t namereln;
4237 int order;
4238 unsigned int labels;
4239 if (rdataset->type != dns_rdatatype_ns)
4240 continue;
4241 namereln = dns_name_fullcompare(name, &fctx->domain,
4242 &order, &labels);
4243 if (namereln == dns_namereln_equal &&
4244 (message->flags & DNS_MESSAGEFLAG_AA) != 0)
4245 return (ISC_FALSE);
4246 if (namereln == dns_namereln_subdomain)
4247 return (ISC_FALSE);
4248 return (ISC_TRUE);
4249 }
4250 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
4251 }
4252
4253 return (ISC_FALSE);
4254 }
4255
4256 static inline void
log_lame(fetchctx_t * fctx,dns_adbaddrinfo_t * addrinfo)4257 log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
4258 char namebuf[DNS_NAME_FORMATSIZE];
4259 char domainbuf[DNS_NAME_FORMATSIZE];
4260 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
4261
4262 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
4263 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
4264 isc_sockaddr_format(&addrinfo->sockaddr, addrbuf, sizeof(addrbuf));
4265 isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
4266 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
4267 "lame server resolving '%s' (in '%s'?): %s",
4268 namebuf, domainbuf, addrbuf);
4269 }
4270
4271 static inline void
log_formerr(fetchctx_t * fctx,const char * format,...)4272 log_formerr(fetchctx_t *fctx, const char *format, ...) {
4273 char nsbuf[ISC_SOCKADDR_FORMATSIZE];
4274 char clbuf[ISC_SOCKADDR_FORMATSIZE];
4275 const char *clmsg = "";
4276 char msgbuf[2048];
4277 va_list args;
4278
4279 va_start(args, format);
4280 vsnprintf(msgbuf, sizeof(msgbuf), format, args);
4281 va_end(args);
4282
4283 isc_sockaddr_format(&fctx->addrinfo->sockaddr, nsbuf, sizeof(nsbuf));
4284
4285 if (fctx->client != NULL) {
4286 clmsg = " for client ";
4287 isc_sockaddr_format(fctx->client, clbuf, sizeof(clbuf));
4288 } else {
4289 clbuf[0] = '\0';
4290 }
4291
4292 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
4293 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
4294 "DNS format error from %s resolving %s%s%s: %s",
4295 nsbuf, fctx->info, clmsg, clbuf, msgbuf);
4296 }
4297
4298 static inline isc_result_t
same_question(fetchctx_t * fctx)4299 same_question(fetchctx_t *fctx) {
4300 isc_result_t result;
4301 dns_message_t *message = fctx->rmessage;
4302 dns_name_t *name;
4303 dns_rdataset_t *rdataset;
4304
4305 /*
4306 * Caller must be holding the fctx lock.
4307 */
4308
4309 /*
4310 * XXXRTH Currently we support only one question.
4311 */
4312 if (message->counts[DNS_SECTION_QUESTION] != 1) {
4313 log_formerr(fctx, "too many questions");
4314 return (DNS_R_FORMERR);
4315 }
4316
4317 result = dns_message_firstname(message, DNS_SECTION_QUESTION);
4318 if (result != ISC_R_SUCCESS)
4319 return (result);
4320 name = NULL;
4321 dns_message_currentname(message, DNS_SECTION_QUESTION, &name);
4322 rdataset = ISC_LIST_HEAD(name->list);
4323 INSIST(rdataset != NULL);
4324 INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);
4325
4326 if (fctx->type != rdataset->type ||
4327 fctx->res->rdclass != rdataset->rdclass ||
4328 !dns_name_equal(&fctx->name, name)) {
4329 char namebuf[DNS_NAME_FORMATSIZE];
4330 char class[DNS_RDATACLASS_FORMATSIZE];
4331 char type[DNS_RDATATYPE_FORMATSIZE];
4332
4333 dns_name_format(name, namebuf, sizeof(namebuf));
4334 dns_rdataclass_format(rdataset->rdclass, class, sizeof(class));
4335 dns_rdatatype_format(rdataset->type, type, sizeof(type));
4336 log_formerr(fctx, "question section mismatch: got %s/%s/%s",
4337 namebuf, class, type);
4338 return (DNS_R_FORMERR);
4339 }
4340
4341 return (ISC_R_SUCCESS);
4342 }
4343
4344 static void
clone_results(fetchctx_t * fctx)4345 clone_results(fetchctx_t *fctx) {
4346 dns_fetchevent_t *event, *hevent;
4347 isc_result_t result;
4348 dns_name_t *name, *hname;
4349
4350 FCTXTRACE("clone_results");
4351
4352 /*
4353 * Set up any other events to have the same data as the first
4354 * event.
4355 *
4356 * Caller must be holding the appropriate lock.
4357 */
4358
4359 fctx->cloned = ISC_TRUE;
4360 hevent = ISC_LIST_HEAD(fctx->events);
4361 if (hevent == NULL)
4362 return;
4363 hname = dns_fixedname_name(&hevent->foundname);
4364 for (event = ISC_LIST_NEXT(hevent, ev_link);
4365 event != NULL;
4366 event = ISC_LIST_NEXT(event, ev_link)) {
4367 name = dns_fixedname_name(&event->foundname);
4368 result = dns_name_copy(hname, name, NULL);
4369 if (result != ISC_R_SUCCESS)
4370 event->result = result;
4371 else
4372 event->result = hevent->result;
4373 dns_db_attach(hevent->db, &event->db);
4374 dns_db_attachnode(hevent->db, hevent->node, &event->node);
4375 INSIST(hevent->rdataset != NULL);
4376 INSIST(event->rdataset != NULL);
4377 if (dns_rdataset_isassociated(hevent->rdataset))
4378 dns_rdataset_clone(hevent->rdataset, event->rdataset);
4379 INSIST(! (hevent->sigrdataset == NULL &&
4380 event->sigrdataset != NULL));
4381 if (hevent->sigrdataset != NULL &&
4382 dns_rdataset_isassociated(hevent->sigrdataset) &&
4383 event->sigrdataset != NULL)
4384 dns_rdataset_clone(hevent->sigrdataset,
4385 event->sigrdataset);
4386 }
4387 }
4388
4389 #define CACHE(r) (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
4390 #define ANSWER(r) (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
4391 #define ANSWERSIG(r) (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
4392 #define EXTERNAL(r) (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
4393 #define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
4394 #define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
4395 #define CHECKNAMES(r) (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
4396
4397
4398 /*
4399 * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has
4400 * no references and is no longer waiting for any events).
4401 *
4402 * Requires:
4403 * '*fctx' is shutting down.
4404 *
4405 * Returns:
4406 * true if the resolver is exiting and this is the last fctx in the bucket.
4407 */
4408 static isc_boolean_t
maybe_destroy(fetchctx_t * fctx,isc_boolean_t locked)4409 maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked) {
4410 unsigned int bucketnum;
4411 isc_boolean_t bucket_empty = ISC_FALSE;
4412 dns_resolver_t *res = fctx->res;
4413 dns_validator_t *validator, *next_validator;
4414 isc_boolean_t dodestroy = ISC_FALSE;
4415
4416 REQUIRE(SHUTTINGDOWN(fctx));
4417
4418 bucketnum = fctx->bucketnum;
4419 if (!locked)
4420 LOCK(&res->buckets[bucketnum].lock);
4421 if (fctx->pending != 0 || fctx->nqueries != 0)
4422 goto unlock;
4423
4424 for (validator = ISC_LIST_HEAD(fctx->validators);
4425 validator != NULL; validator = next_validator) {
4426 next_validator = ISC_LIST_NEXT(validator, link);
4427 dns_validator_cancel(validator);
4428 }
4429
4430 if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators)) {
4431 bucket_empty = fctx_unlink(fctx);
4432 dodestroy = ISC_TRUE;
4433 }
4434 unlock:
4435 if (!locked)
4436 UNLOCK(&res->buckets[bucketnum].lock);
4437 if (dodestroy)
4438 fctx_destroy(fctx);
4439 return (bucket_empty);
4440 }
4441
4442 /*
4443 * The validator has finished.
4444 */
4445 static void
validated(isc_task_t * task,isc_event_t * event)4446 validated(isc_task_t *task, isc_event_t *event) {
4447 dns_adbaddrinfo_t *addrinfo;
4448 dns_dbnode_t *node = NULL;
4449 dns_dbnode_t *nsnode = NULL;
4450 dns_fetchevent_t *hevent;
4451 dns_name_t *name;
4452 dns_rdataset_t *ardataset = NULL;
4453 dns_rdataset_t *asigrdataset = NULL;
4454 dns_rdataset_t *rdataset;
4455 dns_rdataset_t *sigrdataset;
4456 dns_resolver_t *res;
4457 dns_valarg_t *valarg;
4458 dns_validatorevent_t *vevent;
4459 fetchctx_t *fctx;
4460 isc_boolean_t chaining;
4461 isc_boolean_t negative;
4462 isc_boolean_t sentresponse;
4463 isc_result_t eresult = ISC_R_SUCCESS;
4464 isc_result_t result = ISC_R_SUCCESS;
4465 isc_stdtime_t now;
4466 isc_uint32_t ttl;
4467 isc_uint32_t bucketnum;
4468
4469 UNUSED(task); /* for now */
4470
4471 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE);
4472 valarg = event->ev_arg;
4473 fctx = valarg->fctx;
4474 res = fctx->res;
4475 addrinfo = valarg->addrinfo;
4476 REQUIRE(VALID_FCTX(fctx));
4477 REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
4478
4479 vevent = (dns_validatorevent_t *)event;
4480 fctx->vresult = vevent->result;
4481
4482 FCTXTRACE("received validation completion event");
4483
4484 bucketnum = fctx->bucketnum;
4485 LOCK(&res->buckets[bucketnum].lock);
4486
4487 ISC_LIST_UNLINK(fctx->validators, vevent->validator, link);
4488 fctx->validator = NULL;
4489
4490 /*
4491 * Destroy the validator early so that we can
4492 * destroy the fctx if necessary.
4493 */
4494 dns_validator_destroy(&vevent->validator);
4495 isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
4496
4497 negative = ISC_TF(vevent->rdataset == NULL);
4498
4499 sentresponse = ISC_TF((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0);
4500
4501 /*
4502 * If shutting down, ignore the results. Check to see if we're
4503 * done waiting for validator completions and ADB pending events; if
4504 * so, destroy the fctx.
4505 */
4506 if (SHUTTINGDOWN(fctx) && !sentresponse) {
4507 isc_boolean_t bucket_empty;
4508 bucket_empty = maybe_destroy(fctx, ISC_TRUE);
4509 UNLOCK(&res->buckets[bucketnum].lock);
4510 if (bucket_empty)
4511 empty_bucket(res);
4512 goto cleanup_event;
4513 }
4514
4515 isc_stdtime_get(&now);
4516
4517 /*
4518 * If chaining, we need to make sure that the right result code is
4519 * returned, and that the rdatasets are bound.
4520 */
4521 if (vevent->result == ISC_R_SUCCESS &&
4522 !negative &&
4523 vevent->rdataset != NULL &&
4524 CHAINING(vevent->rdataset))
4525 {
4526 if (vevent->rdataset->type == dns_rdatatype_cname)
4527 eresult = DNS_R_CNAME;
4528 else {
4529 INSIST(vevent->rdataset->type == dns_rdatatype_dname);
4530 eresult = DNS_R_DNAME;
4531 }
4532 chaining = ISC_TRUE;
4533 } else
4534 chaining = ISC_FALSE;
4535
4536 /*
4537 * Either we're not shutting down, or we are shutting down but want
4538 * to cache the result anyway (if this was a validation started by
4539 * a query with cd set)
4540 */
4541
4542 hevent = ISC_LIST_HEAD(fctx->events);
4543 if (hevent != NULL) {
4544 if (!negative && !chaining &&
4545 (fctx->type == dns_rdatatype_any ||
4546 fctx->type == dns_rdatatype_rrsig ||
4547 fctx->type == dns_rdatatype_sig)) {
4548 /*
4549 * Don't bind rdatasets; the caller
4550 * will iterate the node.
4551 */
4552 } else {
4553 ardataset = hevent->rdataset;
4554 asigrdataset = hevent->sigrdataset;
4555 }
4556 }
4557
4558 if (vevent->result != ISC_R_SUCCESS) {
4559 FCTXTRACE("validation failed");
4560 inc_stats(res, dns_resstatscounter_valfail);
4561 fctx->valfail++;
4562 fctx->vresult = vevent->result;
4563 if (fctx->vresult != DNS_R_BROKENCHAIN) {
4564 result = ISC_R_NOTFOUND;
4565 if (vevent->rdataset != NULL)
4566 result = dns_db_findnode(fctx->cache,
4567 vevent->name,
4568 ISC_TRUE, &node);
4569 if (result == ISC_R_SUCCESS)
4570 (void)dns_db_deleterdataset(fctx->cache, node,
4571 NULL,
4572 vevent->type, 0);
4573 if (result == ISC_R_SUCCESS &&
4574 vevent->sigrdataset != NULL)
4575 (void)dns_db_deleterdataset(fctx->cache, node,
4576 NULL,
4577 dns_rdatatype_rrsig,
4578 vevent->type);
4579 if (result == ISC_R_SUCCESS)
4580 dns_db_detachnode(fctx->cache, &node);
4581 }
4582 if (fctx->vresult == DNS_R_BROKENCHAIN && !negative) {
4583 /*
4584 * Cache the data as pending for later validation.
4585 */
4586 result = ISC_R_NOTFOUND;
4587 if (vevent->rdataset != NULL)
4588 result = dns_db_findnode(fctx->cache,
4589 vevent->name,
4590 ISC_TRUE, &node);
4591 if (result == ISC_R_SUCCESS) {
4592 (void)dns_db_addrdataset(fctx->cache, node,
4593 NULL, now,
4594 vevent->rdataset, 0,
4595 NULL);
4596 }
4597 if (result == ISC_R_SUCCESS &&
4598 vevent->sigrdataset != NULL)
4599 (void)dns_db_addrdataset(fctx->cache, node,
4600 NULL, now,
4601 vevent->sigrdataset,
4602 0, NULL);
4603 if (result == ISC_R_SUCCESS)
4604 dns_db_detachnode(fctx->cache, &node);
4605 }
4606 result = fctx->vresult;
4607 add_bad(fctx, addrinfo, result, badns_validation);
4608 isc_event_free(&event);
4609 UNLOCK(&res->buckets[bucketnum].lock);
4610 INSIST(fctx->validator == NULL);
4611 fctx->validator = ISC_LIST_HEAD(fctx->validators);
4612 if (fctx->validator != NULL)
4613 dns_validator_send(fctx->validator);
4614 else if (sentresponse)
4615 fctx_done(fctx, result, __LINE__); /* Locks bucket. */
4616 else if (result == DNS_R_BROKENCHAIN) {
4617 isc_result_t tresult;
4618 isc_time_t expire;
4619 isc_interval_t i;
4620
4621 isc_interval_set(&i, DNS_BADCACHE_TTL(fctx), 0);
4622 tresult = isc_time_nowplusinterval(&expire, &i);
4623 if (negative &&
4624 (fctx->type == dns_rdatatype_dnskey ||
4625 fctx->type == dns_rdatatype_dlv ||
4626 fctx->type == dns_rdatatype_ds) &&
4627 tresult == ISC_R_SUCCESS)
4628 dns_resolver_addbadcache(res, &fctx->name,
4629 fctx->type, &expire);
4630 fctx_done(fctx, result, __LINE__); /* Locks bucket. */
4631 } else
4632 fctx_try(fctx, ISC_TRUE, ISC_TRUE); /* Locks bucket. */
4633 return;
4634 }
4635
4636
4637 if (negative) {
4638 dns_rdatatype_t covers;
4639 FCTXTRACE("nonexistence validation OK");
4640
4641 inc_stats(res, dns_resstatscounter_valnegsuccess);
4642
4643 /*
4644 * Cache DS NXDOMAIN seperately to other types.
4645 */
4646 if (fctx->rmessage->rcode == dns_rcode_nxdomain &&
4647 fctx->type != dns_rdatatype_ds)
4648 covers = dns_rdatatype_any;
4649 else
4650 covers = fctx->type;
4651
4652 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE,
4653 &node);
4654 if (result != ISC_R_SUCCESS)
4655 goto noanswer_response;
4656
4657 /*
4658 * If we are asking for a SOA record set the cache time
4659 * to zero to facilitate locating the containing zone of
4660 * a arbitrary zone.
4661 */
4662 ttl = res->view->maxncachettl;
4663 if (fctx->type == dns_rdatatype_soa &&
4664 covers == dns_rdatatype_any && res->zero_no_soa_ttl)
4665 ttl = 0;
4666
4667 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
4668 covers, now, ttl, vevent->optout,
4669 vevent->secure, ardataset, &eresult);
4670 if (result != ISC_R_SUCCESS)
4671 goto noanswer_response;
4672 goto answer_response;
4673 } else
4674 inc_stats(res, dns_resstatscounter_valsuccess);
4675
4676 FCTXTRACE("validation OK");
4677
4678 if (vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
4679 result = dns_rdataset_addnoqname(vevent->rdataset,
4680 vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
4681 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4682 INSIST(vevent->sigrdataset != NULL);
4683 vevent->sigrdataset->ttl = vevent->rdataset->ttl;
4684 if (vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER] != NULL) {
4685 result = dns_rdataset_addclosest(vevent->rdataset,
4686 vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]);
4687 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4688 }
4689 } else if (vevent->rdataset->trust == dns_trust_answer &&
4690 vevent->rdataset->type != dns_rdatatype_rrsig)
4691 {
4692 isc_result_t tresult;
4693 dns_name_t *noqname = NULL;
4694 tresult = findnoqname(fctx, vevent->name,
4695 vevent->rdataset->type, &noqname);
4696 if (tresult == ISC_R_SUCCESS && noqname != NULL) {
4697 tresult = dns_rdataset_addnoqname(vevent->rdataset,
4698 noqname);
4699 RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
4700 }
4701 }
4702
4703 /*
4704 * The data was already cached as pending data.
4705 * Re-cache it as secure and bind the cached
4706 * rdatasets to the first event on the fetch
4707 * event list.
4708 */
4709 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE, &node);
4710 if (result != ISC_R_SUCCESS)
4711 goto noanswer_response;
4712
4713 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
4714 vevent->rdataset, 0, ardataset);
4715 if (result != ISC_R_SUCCESS &&
4716 result != DNS_R_UNCHANGED)
4717 goto noanswer_response;
4718 if (ardataset != NULL && NEGATIVE(ardataset)) {
4719 if (NXDOMAIN(ardataset))
4720 eresult = DNS_R_NCACHENXDOMAIN;
4721 else
4722 eresult = DNS_R_NCACHENXRRSET;
4723 } else if (vevent->sigrdataset != NULL) {
4724 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
4725 vevent->sigrdataset, 0,
4726 asigrdataset);
4727 if (result != ISC_R_SUCCESS &&
4728 result != DNS_R_UNCHANGED)
4729 goto noanswer_response;
4730 }
4731
4732 if (sentresponse) {
4733 isc_boolean_t bucket_empty = ISC_FALSE;
4734 /*
4735 * If we only deferred the destroy because we wanted to cache
4736 * the data, destroy now.
4737 */
4738 dns_db_detachnode(fctx->cache, &node);
4739 if (SHUTTINGDOWN(fctx))
4740 bucket_empty = maybe_destroy(fctx, ISC_TRUE);
4741 UNLOCK(&res->buckets[bucketnum].lock);
4742 if (bucket_empty)
4743 empty_bucket(res);
4744 goto cleanup_event;
4745 }
4746
4747 if (!ISC_LIST_EMPTY(fctx->validators)) {
4748 INSIST(!negative);
4749 INSIST(fctx->type == dns_rdatatype_any ||
4750 fctx->type == dns_rdatatype_rrsig ||
4751 fctx->type == dns_rdatatype_sig);
4752 /*
4753 * Don't send a response yet - we have
4754 * more rdatasets that still need to
4755 * be validated.
4756 */
4757 dns_db_detachnode(fctx->cache, &node);
4758 UNLOCK(&res->buckets[bucketnum].lock);
4759 dns_validator_send(ISC_LIST_HEAD(fctx->validators));
4760 goto cleanup_event;
4761 }
4762
4763 answer_response:
4764 /*
4765 * Cache any NS/NSEC records that happened to be validated.
4766 */
4767 result = dns_message_firstname(fctx->rmessage, DNS_SECTION_AUTHORITY);
4768 while (result == ISC_R_SUCCESS) {
4769 name = NULL;
4770 dns_message_currentname(fctx->rmessage, DNS_SECTION_AUTHORITY,
4771 &name);
4772 for (rdataset = ISC_LIST_HEAD(name->list);
4773 rdataset != NULL;
4774 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4775 if ((rdataset->type != dns_rdatatype_ns &&
4776 rdataset->type != dns_rdatatype_nsec) ||
4777 rdataset->trust != dns_trust_secure)
4778 continue;
4779 for (sigrdataset = ISC_LIST_HEAD(name->list);
4780 sigrdataset != NULL;
4781 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
4782 if (sigrdataset->type != dns_rdatatype_rrsig ||
4783 sigrdataset->covers != rdataset->type)
4784 continue;
4785 break;
4786 }
4787 if (sigrdataset == NULL ||
4788 sigrdataset->trust != dns_trust_secure)
4789 continue;
4790 result = dns_db_findnode(fctx->cache, name, ISC_TRUE,
4791 &nsnode);
4792 if (result != ISC_R_SUCCESS)
4793 continue;
4794
4795 result = dns_db_addrdataset(fctx->cache, nsnode, NULL,
4796 now, rdataset, 0, NULL);
4797 if (result == ISC_R_SUCCESS)
4798 result = dns_db_addrdataset(fctx->cache, nsnode,
4799 NULL, now,
4800 sigrdataset, 0,
4801 NULL);
4802 dns_db_detachnode(fctx->cache, &nsnode);
4803 if (result != ISC_R_SUCCESS)
4804 continue;
4805 }
4806 result = dns_message_nextname(fctx->rmessage,
4807 DNS_SECTION_AUTHORITY);
4808 }
4809
4810 result = ISC_R_SUCCESS;
4811
4812 /*
4813 * Respond with an answer, positive or negative,
4814 * as opposed to an error. 'node' must be non-NULL.
4815 */
4816
4817 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
4818
4819 if (hevent != NULL) {
4820 /*
4821 * Negative results must be indicated in event->result.
4822 */
4823 if (dns_rdataset_isassociated(hevent->rdataset) &&
4824 NEGATIVE(hevent->rdataset)) {
4825 INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
4826 eresult == DNS_R_NCACHENXRRSET);
4827 }
4828 hevent->result = eresult;
4829 RUNTIME_CHECK(dns_name_copy(vevent->name,
4830 dns_fixedname_name(&hevent->foundname), NULL)
4831 == ISC_R_SUCCESS);
4832 dns_db_attach(fctx->cache, &hevent->db);
4833 dns_db_transfernode(fctx->cache, &node, &hevent->node);
4834 clone_results(fctx);
4835 }
4836
4837 noanswer_response:
4838 if (node != NULL)
4839 dns_db_detachnode(fctx->cache, &node);
4840
4841 UNLOCK(&res->buckets[bucketnum].lock);
4842 fctx_done(fctx, result, __LINE__); /* Locks bucket. */
4843
4844 cleanup_event:
4845 INSIST(node == NULL);
4846 isc_event_free(&event);
4847 }
4848
4849 static void
fctx_log(void * arg,int level,const char * fmt,...)4850 fctx_log(void *arg, int level, const char *fmt, ...) {
4851 char msgbuf[2048];
4852 va_list args;
4853 fetchctx_t *fctx = arg;
4854
4855 va_start(args, fmt);
4856 vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
4857 va_end(args);
4858
4859 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
4860 DNS_LOGMODULE_RESOLVER, level,
4861 "fctx %p(%s): %s", fctx, fctx->info, msgbuf);
4862 }
4863
4864 static inline isc_result_t
findnoqname(fetchctx_t * fctx,dns_name_t * name,dns_rdatatype_t type,dns_name_t ** noqnamep)4865 findnoqname(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
4866 dns_name_t **noqnamep)
4867 {
4868 dns_rdataset_t *nrdataset, *next, *sigrdataset;
4869 dns_rdata_rrsig_t rrsig;
4870 isc_result_t result;
4871 unsigned int labels;
4872 dns_section_t section;
4873 dns_name_t *zonename;
4874 dns_fixedname_t fzonename;
4875 dns_name_t *closest;
4876 dns_fixedname_t fclosest;
4877 dns_name_t *nearest;
4878 dns_fixedname_t fnearest;
4879 dns_rdatatype_t found = dns_rdatatype_none;
4880 dns_name_t *noqname = NULL;
4881
4882 FCTXTRACE("findnoqname");
4883
4884 REQUIRE(noqnamep != NULL && *noqnamep == NULL);
4885
4886 /*
4887 * Find the SIG for this rdataset, if we have it.
4888 */
4889 for (sigrdataset = ISC_LIST_HEAD(name->list);
4890 sigrdataset != NULL;
4891 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
4892 if (sigrdataset->type == dns_rdatatype_rrsig &&
4893 sigrdataset->covers == type)
4894 break;
4895 }
4896
4897 if (sigrdataset == NULL)
4898 return (ISC_R_NOTFOUND);
4899
4900 labels = dns_name_countlabels(name);
4901
4902 for (result = dns_rdataset_first(sigrdataset);
4903 result == ISC_R_SUCCESS;
4904 result = dns_rdataset_next(sigrdataset)) {
4905 dns_rdata_t rdata = DNS_RDATA_INIT;
4906 dns_rdataset_current(sigrdataset, &rdata);
4907 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
4908 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4909 /* Wildcard has rrsig.labels < labels - 1. */
4910 if (rrsig.labels + 1U >= labels)
4911 continue;
4912 break;
4913 }
4914
4915 if (result == ISC_R_NOMORE)
4916 return (ISC_R_NOTFOUND);
4917 if (result != ISC_R_SUCCESS)
4918 return (result);
4919
4920 dns_fixedname_init(&fzonename);
4921 zonename = dns_fixedname_name(&fzonename);
4922 dns_fixedname_init(&fclosest);
4923 closest = dns_fixedname_name(&fclosest);
4924 dns_fixedname_init(&fnearest);
4925 nearest = dns_fixedname_name(&fnearest);
4926
4927 #define NXND(x) ((x) == ISC_R_SUCCESS)
4928
4929 section = DNS_SECTION_AUTHORITY;
4930 for (result = dns_message_firstname(fctx->rmessage, section);
4931 result == ISC_R_SUCCESS;
4932 result = dns_message_nextname(fctx->rmessage, section)) {
4933 dns_name_t *nsec = NULL;
4934 dns_message_currentname(fctx->rmessage, section, &nsec);
4935 for (nrdataset = ISC_LIST_HEAD(nsec->list);
4936 nrdataset != NULL; nrdataset = next) {
4937 isc_boolean_t data = ISC_FALSE, exists = ISC_FALSE;
4938 isc_boolean_t optout = ISC_FALSE, unknown = ISC_FALSE;
4939 isc_boolean_t setclosest = ISC_FALSE;
4940 isc_boolean_t setnearest = ISC_FALSE;
4941
4942 next = ISC_LIST_NEXT(nrdataset, link);
4943 if (nrdataset->type != dns_rdatatype_nsec &&
4944 nrdataset->type != dns_rdatatype_nsec3)
4945 continue;
4946
4947 if (nrdataset->type == dns_rdatatype_nsec &&
4948 NXND(dns_nsec_noexistnodata(type, name, nsec,
4949 nrdataset, &exists,
4950 &data, NULL, fctx_log,
4951 fctx)))
4952 {
4953 if (!exists) {
4954 noqname = nsec;
4955 found = dns_rdatatype_nsec;
4956 }
4957 }
4958
4959 if (nrdataset->type == dns_rdatatype_nsec3 &&
4960 NXND(dns_nsec3_noexistnodata(type, name, nsec,
4961 nrdataset, zonename,
4962 &exists, &data,
4963 &optout, &unknown,
4964 &setclosest,
4965 &setnearest,
4966 closest, nearest,
4967 fctx_log, fctx)))
4968 {
4969 if (!exists && setnearest) {
4970 noqname = nsec;
4971 found = dns_rdatatype_nsec3;
4972 }
4973 }
4974 }
4975 }
4976 if (result == ISC_R_NOMORE)
4977 result = ISC_R_SUCCESS;
4978 if (noqname != NULL) {
4979 for (sigrdataset = ISC_LIST_HEAD(noqname->list);
4980 sigrdataset != NULL;
4981 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
4982 if (sigrdataset->type == dns_rdatatype_rrsig &&
4983 sigrdataset->covers == found)
4984 break;
4985 }
4986 if (sigrdataset != NULL)
4987 *noqnamep = noqname;
4988 }
4989 return (result);
4990 }
4991
4992 static inline isc_result_t
cache_name(fetchctx_t * fctx,dns_name_t * name,dns_adbaddrinfo_t * addrinfo,isc_stdtime_t now)4993 cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
4994 isc_stdtime_t now)
4995 {
4996 dns_rdataset_t *rdataset, *sigrdataset;
4997 dns_rdataset_t *addedrdataset, *ardataset, *asigrdataset;
4998 dns_rdataset_t *valrdataset = NULL, *valsigrdataset = NULL;
4999 dns_dbnode_t *node, **anodep;
5000 dns_db_t **adbp;
5001 dns_name_t *aname;
5002 dns_resolver_t *res;
5003 isc_boolean_t need_validation, secure_domain, have_answer;
5004 isc_result_t result, eresult;
5005 dns_fetchevent_t *event;
5006 unsigned int options;
5007 isc_task_t *task;
5008 isc_boolean_t fail;
5009 unsigned int valoptions = 0;
5010
5011 /*
5012 * The appropriate bucket lock must be held.
5013 */
5014
5015 res = fctx->res;
5016 need_validation = ISC_FALSE;
5017 POST(need_validation);
5018 secure_domain = ISC_FALSE;
5019 have_answer = ISC_FALSE;
5020 eresult = ISC_R_SUCCESS;
5021 task = res->buckets[fctx->bucketnum].task;
5022
5023 /*
5024 * Is DNSSEC validation required for this name?
5025 */
5026 if (res->view->enablevalidation) {
5027 result = dns_view_issecuredomain(res->view, name,
5028 &secure_domain);
5029 if (result != ISC_R_SUCCESS)
5030 return (result);
5031
5032 if (!secure_domain && res->view->dlv != NULL) {
5033 valoptions = DNS_VALIDATOR_DLV;
5034 secure_domain = ISC_TRUE;
5035 }
5036 }
5037
5038 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
5039 need_validation = ISC_FALSE;
5040 else
5041 need_validation = secure_domain;
5042
5043 adbp = NULL;
5044 aname = NULL;
5045 anodep = NULL;
5046 ardataset = NULL;
5047 asigrdataset = NULL;
5048 event = NULL;
5049 if ((name->attributes & DNS_NAMEATTR_ANSWER) != 0 &&
5050 !need_validation) {
5051 have_answer = ISC_TRUE;
5052 event = ISC_LIST_HEAD(fctx->events);
5053 if (event != NULL) {
5054 adbp = &event->db;
5055 aname = dns_fixedname_name(&event->foundname);
5056 result = dns_name_copy(name, aname, NULL);
5057 if (result != ISC_R_SUCCESS)
5058 return (result);
5059 anodep = &event->node;
5060 /*
5061 * If this is an ANY, SIG or RRSIG query, we're not
5062 * going to return any rdatasets, unless we encountered
5063 * a CNAME or DNAME as "the answer". In this case,
5064 * we're going to return DNS_R_CNAME or DNS_R_DNAME
5065 * and we must set up the rdatasets.
5066 */
5067 if ((fctx->type != dns_rdatatype_any &&
5068 fctx->type != dns_rdatatype_rrsig &&
5069 fctx->type != dns_rdatatype_sig) ||
5070 (name->attributes & DNS_NAMEATTR_CHAINING) != 0) {
5071 ardataset = event->rdataset;
5072 asigrdataset = event->sigrdataset;
5073 }
5074 }
5075 }
5076
5077 /*
5078 * Find or create the cache node.
5079 */
5080 node = NULL;
5081 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
5082 if (result != ISC_R_SUCCESS)
5083 return (result);
5084
5085 /*
5086 * Cache or validate each cacheable rdataset.
5087 */
5088 fail = ISC_TF((fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0);
5089 for (rdataset = ISC_LIST_HEAD(name->list);
5090 rdataset != NULL;
5091 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5092 if (!CACHE(rdataset))
5093 continue;
5094 if (CHECKNAMES(rdataset)) {
5095 char namebuf[DNS_NAME_FORMATSIZE];
5096 char typebuf[DNS_RDATATYPE_FORMATSIZE];
5097 char classbuf[DNS_RDATATYPE_FORMATSIZE];
5098
5099 dns_name_format(name, namebuf, sizeof(namebuf));
5100 dns_rdatatype_format(rdataset->type, typebuf,
5101 sizeof(typebuf));
5102 dns_rdataclass_format(rdataset->rdclass, classbuf,
5103 sizeof(classbuf));
5104 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5105 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
5106 "check-names %s %s/%s/%s",
5107 fail ? "failure" : "warning",
5108 namebuf, typebuf, classbuf);
5109 if (fail) {
5110 if (ANSWER(rdataset)) {
5111 dns_db_detachnode(fctx->cache, &node);
5112 return (DNS_R_BADNAME);
5113 }
5114 continue;
5115 }
5116 }
5117
5118 /*
5119 * Enforce the configure maximum cache TTL.
5120 */
5121 if (rdataset->ttl > res->view->maxcachettl)
5122 rdataset->ttl = res->view->maxcachettl;
5123
5124 /*
5125 * Find the SIG for this rdataset, if we have it.
5126 */
5127 for (sigrdataset = ISC_LIST_HEAD(name->list);
5128 sigrdataset != NULL;
5129 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
5130 if (sigrdataset->type == dns_rdatatype_rrsig &&
5131 sigrdataset->covers == rdataset->type)
5132 break;
5133 }
5134
5135 /*
5136 * If this RRset is in a secure domain, is in bailiwick,
5137 * and is not glue, attempt DNSSEC validation. (We do not
5138 * attempt to validate glue or out-of-bailiwick data--even
5139 * though there might be some performance benefit to doing
5140 * so--because it makes it simpler and safer to ensure that
5141 * records from a secure domain are only cached if validated
5142 * within the context of a query to the domain that owns
5143 * them.)
5144 */
5145 if (secure_domain && rdataset->trust != dns_trust_glue &&
5146 !EXTERNAL(rdataset)) {
5147 dns_trust_t trust;
5148
5149 /*
5150 * RRSIGs are validated as part of validating the
5151 * type they cover.
5152 */
5153 if (rdataset->type == dns_rdatatype_rrsig)
5154 continue;
5155
5156 if (sigrdataset == NULL) {
5157 if (!ANSWER(rdataset) && need_validation) {
5158 /*
5159 * Ignore non-answer rdatasets that
5160 * are missing signatures.
5161 */
5162 continue;
5163 }
5164 }
5165
5166 /*
5167 * Normalize the rdataset and sigrdataset TTLs.
5168 */
5169 if (sigrdataset != NULL) {
5170 rdataset->ttl = ISC_MIN(rdataset->ttl,
5171 sigrdataset->ttl);
5172 sigrdataset->ttl = rdataset->ttl;
5173 }
5174
5175 /*
5176 * Cache this rdataset/sigrdataset pair as
5177 * pending data. Track whether it was additional
5178 * or not.
5179 */
5180 if (rdataset->trust == dns_trust_additional)
5181 trust = dns_trust_pending_additional;
5182 else
5183 trust = dns_trust_pending_answer;
5184
5185 rdataset->trust = trust;
5186 if (sigrdataset != NULL)
5187 sigrdataset->trust = trust;
5188 if (!need_validation || !ANSWER(rdataset)) {
5189 if (ANSWER(rdataset) &&
5190 rdataset->type != dns_rdatatype_rrsig) {
5191 isc_result_t tresult;
5192 dns_name_t *noqname = NULL;
5193 tresult = findnoqname(fctx, name,
5194 rdataset->type,
5195 &noqname);
5196 if (tresult == ISC_R_SUCCESS &&
5197 noqname != NULL) {
5198 tresult =
5199 dns_rdataset_addnoqname(
5200 rdataset, noqname);
5201 RUNTIME_CHECK(tresult ==
5202 ISC_R_SUCCESS);
5203 }
5204 }
5205 addedrdataset = ardataset;
5206 result = dns_db_addrdataset(fctx->cache, node,
5207 NULL, now, rdataset,
5208 0, addedrdataset);
5209 if (result == DNS_R_UNCHANGED) {
5210 result = ISC_R_SUCCESS;
5211 if (!need_validation &&
5212 ardataset != NULL &&
5213 NEGATIVE(ardataset)) {
5214 /*
5215 * The answer in the cache is
5216 * better than the answer we
5217 * found, and is a negative
5218 * cache entry, so we must set
5219 * eresult appropriately.
5220 */
5221 if (NXDOMAIN(ardataset))
5222 eresult =
5223 DNS_R_NCACHENXDOMAIN;
5224 else
5225 eresult =
5226 DNS_R_NCACHENXRRSET;
5227 /*
5228 * We have a negative response
5229 * from the cache so don't
5230 * attempt to add the RRSIG
5231 * rrset.
5232 */
5233 continue;
5234 }
5235 }
5236 if (result != ISC_R_SUCCESS)
5237 break;
5238 if (sigrdataset != NULL) {
5239 addedrdataset = asigrdataset;
5240 result = dns_db_addrdataset(fctx->cache,
5241 node, NULL, now,
5242 sigrdataset, 0,
5243 addedrdataset);
5244 if (result == DNS_R_UNCHANGED)
5245 result = ISC_R_SUCCESS;
5246 if (result != ISC_R_SUCCESS)
5247 break;
5248 } else if (!ANSWER(rdataset))
5249 continue;
5250 }
5251
5252 if (ANSWER(rdataset) && need_validation) {
5253 if (fctx->type != dns_rdatatype_any &&
5254 fctx->type != dns_rdatatype_rrsig &&
5255 fctx->type != dns_rdatatype_sig) {
5256 /*
5257 * This is The Answer. We will
5258 * validate it, but first we cache
5259 * the rest of the response - it may
5260 * contain useful keys.
5261 */
5262 INSIST(valrdataset == NULL &&
5263 valsigrdataset == NULL);
5264 valrdataset = rdataset;
5265 valsigrdataset = sigrdataset;
5266 } else {
5267 /*
5268 * This is one of (potentially)
5269 * multiple answers to an ANY
5270 * or SIG query. To keep things
5271 * simple, we just start the
5272 * validator right away rather
5273 * than caching first and
5274 * having to remember which
5275 * rdatasets needed validation.
5276 */
5277 result = valcreate(fctx, addrinfo,
5278 name, rdataset->type,
5279 rdataset,
5280 sigrdataset,
5281 valoptions, task);
5282 }
5283 } else if (CHAINING(rdataset)) {
5284 if (rdataset->type == dns_rdatatype_cname)
5285 eresult = DNS_R_CNAME;
5286 else {
5287 INSIST(rdataset->type ==
5288 dns_rdatatype_dname);
5289 eresult = DNS_R_DNAME;
5290 }
5291 }
5292 } else if (!EXTERNAL(rdataset)) {
5293 /*
5294 * It's OK to cache this rdataset now.
5295 */
5296 if (ANSWER(rdataset))
5297 addedrdataset = ardataset;
5298 else if (ANSWERSIG(rdataset))
5299 addedrdataset = asigrdataset;
5300 else
5301 addedrdataset = NULL;
5302 if (CHAINING(rdataset)) {
5303 if (rdataset->type == dns_rdatatype_cname)
5304 eresult = DNS_R_CNAME;
5305 else {
5306 INSIST(rdataset->type ==
5307 dns_rdatatype_dname);
5308 eresult = DNS_R_DNAME;
5309 }
5310 }
5311 if (rdataset->trust == dns_trust_glue &&
5312 (rdataset->type == dns_rdatatype_ns ||
5313 (rdataset->type == dns_rdatatype_rrsig &&
5314 rdataset->covers == dns_rdatatype_ns))) {
5315 /*
5316 * If the trust level is 'dns_trust_glue'
5317 * then we are adding data from a referral
5318 * we got while executing the search algorithm.
5319 * New referral data always takes precedence
5320 * over the existing cache contents.
5321 */
5322 options = DNS_DBADD_FORCE;
5323 } else
5324 options = 0;
5325
5326 if (ANSWER(rdataset) &&
5327 rdataset->type != dns_rdatatype_rrsig) {
5328 isc_result_t tresult;
5329 dns_name_t *noqname = NULL;
5330 tresult = findnoqname(fctx, name,
5331 rdataset->type, &noqname);
5332 if (tresult == ISC_R_SUCCESS &&
5333 noqname != NULL) {
5334 tresult = dns_rdataset_addnoqname(
5335 rdataset, noqname);
5336 RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
5337 }
5338 }
5339
5340 /*
5341 * Now we can add the rdataset.
5342 */
5343 result = dns_db_addrdataset(fctx->cache,
5344 node, NULL, now,
5345 rdataset,
5346 options,
5347 addedrdataset);
5348
5349 if (result == DNS_R_UNCHANGED) {
5350 if (ANSWER(rdataset) &&
5351 ardataset != NULL &&
5352 NEGATIVE(ardataset)) {
5353 /*
5354 * The answer in the cache is better
5355 * than the answer we found, and is
5356 * a negative cache entry, so we
5357 * must set eresult appropriately.
5358 */
5359 if (NXDOMAIN(ardataset))
5360 eresult = DNS_R_NCACHENXDOMAIN;
5361 else
5362 eresult = DNS_R_NCACHENXRRSET;
5363 }
5364 result = ISC_R_SUCCESS;
5365 } else if (result != ISC_R_SUCCESS)
5366 break;
5367 }
5368 }
5369
5370 if (valrdataset != NULL) {
5371 dns_rdatatype_t vtype = fctx->type;
5372 if (CHAINING(valrdataset)) {
5373 if (valrdataset->type == dns_rdatatype_cname)
5374 vtype = dns_rdatatype_cname;
5375 else
5376 vtype = dns_rdatatype_dname;
5377 }
5378 result = valcreate(fctx, addrinfo, name, vtype, valrdataset,
5379 valsigrdataset, valoptions, task);
5380 }
5381
5382 if (result == ISC_R_SUCCESS && have_answer) {
5383 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
5384 if (event != NULL) {
5385 /*
5386 * Negative results must be indicated in event->result.
5387 */
5388 if (dns_rdataset_isassociated(event->rdataset) &&
5389 NEGATIVE(event->rdataset)) {
5390 INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
5391 eresult == DNS_R_NCACHENXRRSET);
5392 }
5393 event->result = eresult;
5394 if (adbp != NULL && *adbp != NULL) {
5395 if (anodep != NULL && *anodep != NULL)
5396 dns_db_detachnode(*adbp, anodep);
5397 dns_db_detach(adbp);
5398 }
5399 dns_db_attach(fctx->cache, adbp);
5400 dns_db_transfernode(fctx->cache, &node, anodep);
5401 clone_results(fctx);
5402 }
5403 }
5404
5405 if (node != NULL)
5406 dns_db_detachnode(fctx->cache, &node);
5407
5408 return (result);
5409 }
5410
5411 static inline isc_result_t
cache_message(fetchctx_t * fctx,dns_adbaddrinfo_t * addrinfo,isc_stdtime_t now)5412 cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now)
5413 {
5414 isc_result_t result;
5415 dns_section_t section;
5416 dns_name_t *name;
5417
5418 FCTXTRACE("cache_message");
5419
5420 fctx->attributes &= ~FCTX_ATTR_WANTCACHE;
5421
5422 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
5423
5424 for (section = DNS_SECTION_ANSWER;
5425 section <= DNS_SECTION_ADDITIONAL;
5426 section++) {
5427 result = dns_message_firstname(fctx->rmessage, section);
5428 while (result == ISC_R_SUCCESS) {
5429 name = NULL;
5430 dns_message_currentname(fctx->rmessage, section,
5431 &name);
5432 if ((name->attributes & DNS_NAMEATTR_CACHE) != 0) {
5433 result = cache_name(fctx, name, addrinfo, now);
5434 if (result != ISC_R_SUCCESS)
5435 break;
5436 }
5437 result = dns_message_nextname(fctx->rmessage, section);
5438 }
5439 if (result != ISC_R_NOMORE)
5440 break;
5441 }
5442 if (result == ISC_R_NOMORE)
5443 result = ISC_R_SUCCESS;
5444
5445 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
5446
5447 return (result);
5448 }
5449
5450 /*
5451 * Do what dns_ncache_addoptout() does, and then compute an appropriate eresult.
5452 */
5453 static isc_result_t
ncache_adderesult(dns_message_t * message,dns_db_t * cache,dns_dbnode_t * node,dns_rdatatype_t covers,isc_stdtime_t now,dns_ttl_t maxttl,isc_boolean_t optout,isc_boolean_t secure,dns_rdataset_t * ardataset,isc_result_t * eresultp)5454 ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
5455 dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
5456 isc_boolean_t optout, isc_boolean_t secure,
5457 dns_rdataset_t *ardataset, isc_result_t *eresultp)
5458 {
5459 isc_result_t result;
5460 dns_rdataset_t rdataset;
5461
5462 if (ardataset == NULL) {
5463 dns_rdataset_init(&rdataset);
5464 ardataset = &rdataset;
5465 }
5466 if (secure)
5467 result = dns_ncache_addoptout(message, cache, node, covers,
5468 now, maxttl, optout, ardataset);
5469 else
5470 result = dns_ncache_add(message, cache, node, covers, now,
5471 maxttl, ardataset);
5472 if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) {
5473 /*
5474 * If the cache now contains a negative entry and we
5475 * care about whether it is DNS_R_NCACHENXDOMAIN or
5476 * DNS_R_NCACHENXRRSET then extract it.
5477 */
5478 if (NEGATIVE(ardataset)) {
5479 /*
5480 * The cache data is a negative cache entry.
5481 */
5482 if (NXDOMAIN(ardataset))
5483 *eresultp = DNS_R_NCACHENXDOMAIN;
5484 else
5485 *eresultp = DNS_R_NCACHENXRRSET;
5486 } else {
5487 /*
5488 * Either we don't care about the nature of the
5489 * cache rdataset (because no fetch is interested
5490 * in the outcome), or the cache rdataset is not
5491 * a negative cache entry. Whichever case it is,
5492 * we can return success.
5493 *
5494 * XXXRTH There's a CNAME/DNAME problem here.
5495 */
5496 *eresultp = ISC_R_SUCCESS;
5497 }
5498 result = ISC_R_SUCCESS;
5499 }
5500 if (ardataset == &rdataset && dns_rdataset_isassociated(ardataset))
5501 dns_rdataset_disassociate(ardataset);
5502
5503 return (result);
5504 }
5505
5506 static inline isc_result_t
ncache_message(fetchctx_t * fctx,dns_adbaddrinfo_t * addrinfo,dns_rdatatype_t covers,isc_stdtime_t now)5507 ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
5508 dns_rdatatype_t covers, isc_stdtime_t now)
5509 {
5510 isc_result_t result, eresult;
5511 dns_name_t *name;
5512 dns_resolver_t *res;
5513 dns_db_t **adbp;
5514 dns_dbnode_t *node, **anodep;
5515 dns_rdataset_t *ardataset;
5516 isc_boolean_t need_validation, secure_domain;
5517 dns_name_t *aname;
5518 dns_fetchevent_t *event;
5519 isc_uint32_t ttl;
5520 unsigned int valoptions = 0;
5521
5522 FCTXTRACE("ncache_message");
5523
5524 fctx->attributes &= ~FCTX_ATTR_WANTNCACHE;
5525
5526 res = fctx->res;
5527 need_validation = ISC_FALSE;
5528 POST(need_validation);
5529 secure_domain = ISC_FALSE;
5530 eresult = ISC_R_SUCCESS;
5531 name = &fctx->name;
5532 node = NULL;
5533
5534 /*
5535 * XXXMPA remove when we follow cnames and adjust the setting
5536 * of FCTX_ATTR_WANTNCACHE in noanswer_response().
5537 */
5538 INSIST(fctx->rmessage->counts[DNS_SECTION_ANSWER] == 0);
5539
5540 /*
5541 * Is DNSSEC validation required for this name?
5542 */
5543 if (fctx->res->view->enablevalidation) {
5544 result = dns_view_issecuredomain(res->view, name,
5545 &secure_domain);
5546 if (result != ISC_R_SUCCESS)
5547 return (result);
5548
5549 if (!secure_domain && res->view->dlv != NULL) {
5550 valoptions = DNS_VALIDATOR_DLV;
5551 secure_domain = ISC_TRUE;
5552 }
5553 }
5554
5555 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
5556 need_validation = ISC_FALSE;
5557 else
5558 need_validation = secure_domain;
5559
5560 if (secure_domain) {
5561 /*
5562 * Mark all rdatasets as pending.
5563 */
5564 dns_rdataset_t *trdataset;
5565 dns_name_t *tname;
5566
5567 result = dns_message_firstname(fctx->rmessage,
5568 DNS_SECTION_AUTHORITY);
5569 while (result == ISC_R_SUCCESS) {
5570 tname = NULL;
5571 dns_message_currentname(fctx->rmessage,
5572 DNS_SECTION_AUTHORITY,
5573 &tname);
5574 for (trdataset = ISC_LIST_HEAD(tname->list);
5575 trdataset != NULL;
5576 trdataset = ISC_LIST_NEXT(trdataset, link))
5577 trdataset->trust = dns_trust_pending_answer;
5578 result = dns_message_nextname(fctx->rmessage,
5579 DNS_SECTION_AUTHORITY);
5580 }
5581 if (result != ISC_R_NOMORE)
5582 return (result);
5583
5584 }
5585
5586 if (need_validation) {
5587 /*
5588 * Do negative response validation.
5589 */
5590 result = valcreate(fctx, addrinfo, name, fctx->type,
5591 NULL, NULL, valoptions,
5592 res->buckets[fctx->bucketnum].task);
5593 /*
5594 * If validation is necessary, return now. Otherwise continue
5595 * to process the message, letting the validation complete
5596 * in its own good time.
5597 */
5598 return (result);
5599 }
5600
5601 LOCK(&res->buckets[fctx->bucketnum].lock);
5602
5603 adbp = NULL;
5604 aname = NULL;
5605 anodep = NULL;
5606 ardataset = NULL;
5607 if (!HAVE_ANSWER(fctx)) {
5608 event = ISC_LIST_HEAD(fctx->events);
5609 if (event != NULL) {
5610 adbp = &event->db;
5611 aname = dns_fixedname_name(&event->foundname);
5612 result = dns_name_copy(name, aname, NULL);
5613 if (result != ISC_R_SUCCESS)
5614 goto unlock;
5615 anodep = &event->node;
5616 ardataset = event->rdataset;
5617 }
5618 } else
5619 event = NULL;
5620
5621 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
5622 if (result != ISC_R_SUCCESS)
5623 goto unlock;
5624
5625 /*
5626 * If we are asking for a SOA record set the cache time
5627 * to zero to facilitate locating the containing zone of
5628 * a arbitrary zone.
5629 */
5630 ttl = fctx->res->view->maxncachettl;
5631 if (fctx->type == dns_rdatatype_soa &&
5632 covers == dns_rdatatype_any &&
5633 fctx->res->zero_no_soa_ttl)
5634 ttl = 0;
5635
5636 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
5637 covers, now, ttl, ISC_FALSE,
5638 ISC_FALSE, ardataset, &eresult);
5639 if (result != ISC_R_SUCCESS)
5640 goto unlock;
5641
5642 if (!HAVE_ANSWER(fctx)) {
5643 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
5644 if (event != NULL) {
5645 event->result = eresult;
5646 if (adbp != NULL && *adbp != NULL) {
5647 if (anodep != NULL && *anodep != NULL)
5648 dns_db_detachnode(*adbp, anodep);
5649 dns_db_detach(adbp);
5650 }
5651 dns_db_attach(fctx->cache, adbp);
5652 dns_db_transfernode(fctx->cache, &node, anodep);
5653 clone_results(fctx);
5654 }
5655 }
5656
5657 unlock:
5658 UNLOCK(&res->buckets[fctx->bucketnum].lock);
5659
5660 if (node != NULL)
5661 dns_db_detachnode(fctx->cache, &node);
5662
5663 return (result);
5664 }
5665
5666 static inline void
mark_related(dns_name_t * name,dns_rdataset_t * rdataset,isc_boolean_t external,isc_boolean_t gluing)5667 mark_related(dns_name_t *name, dns_rdataset_t *rdataset,
5668 isc_boolean_t external, isc_boolean_t gluing)
5669 {
5670 name->attributes |= DNS_NAMEATTR_CACHE;
5671 if (gluing) {
5672 rdataset->trust = dns_trust_glue;
5673 /*
5674 * Glue with 0 TTL causes problems. We force the TTL to
5675 * 1 second to prevent this.
5676 */
5677 if (rdataset->ttl == 0)
5678 rdataset->ttl = 1;
5679 } else
5680 rdataset->trust = dns_trust_additional;
5681 /*
5682 * Avoid infinite loops by only marking new rdatasets.
5683 */
5684 if (!CACHE(rdataset)) {
5685 name->attributes |= DNS_NAMEATTR_CHASE;
5686 rdataset->attributes |= DNS_RDATASETATTR_CHASE;
5687 }
5688 rdataset->attributes |= DNS_RDATASETATTR_CACHE;
5689 if (external)
5690 rdataset->attributes |= DNS_RDATASETATTR_EXTERNAL;
5691 }
5692
5693 static isc_result_t
check_section(void * arg,dns_name_t * addname,dns_rdatatype_t type,dns_section_t section)5694 check_section(void *arg, dns_name_t *addname, dns_rdatatype_t type,
5695 dns_section_t section)
5696 {
5697 fetchctx_t *fctx = arg;
5698 isc_result_t result;
5699 dns_name_t *name;
5700 dns_rdataset_t *rdataset;
5701 isc_boolean_t external;
5702 dns_rdatatype_t rtype;
5703 isc_boolean_t gluing;
5704
5705 REQUIRE(VALID_FCTX(fctx));
5706
5707 #if CHECK_FOR_GLUE_IN_ANSWER
5708 if (section == DNS_SECTION_ANSWER && type != dns_rdatatype_a)
5709 return (ISC_R_SUCCESS);
5710 #endif
5711
5712 if (GLUING(fctx))
5713 gluing = ISC_TRUE;
5714 else
5715 gluing = ISC_FALSE;
5716 name = NULL;
5717 rdataset = NULL;
5718 result = dns_message_findname(fctx->rmessage, section, addname,
5719 dns_rdatatype_any, 0, &name, NULL);
5720 if (result == ISC_R_SUCCESS) {
5721 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
5722 if (type == dns_rdatatype_a) {
5723 for (rdataset = ISC_LIST_HEAD(name->list);
5724 rdataset != NULL;
5725 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5726 if (rdataset->type == dns_rdatatype_rrsig)
5727 rtype = rdataset->covers;
5728 else
5729 rtype = rdataset->type;
5730 if (rtype == dns_rdatatype_a ||
5731 rtype == dns_rdatatype_aaaa)
5732 mark_related(name, rdataset, external,
5733 gluing);
5734 }
5735 } else {
5736 result = dns_message_findtype(name, type, 0,
5737 &rdataset);
5738 if (result == ISC_R_SUCCESS) {
5739 mark_related(name, rdataset, external, gluing);
5740 /*
5741 * Do we have its SIG too?
5742 */
5743 rdataset = NULL;
5744 result = dns_message_findtype(name,
5745 dns_rdatatype_rrsig,
5746 type, &rdataset);
5747 if (result == ISC_R_SUCCESS)
5748 mark_related(name, rdataset, external,
5749 gluing);
5750 }
5751 }
5752 }
5753
5754 return (ISC_R_SUCCESS);
5755 }
5756
5757 static isc_result_t
check_related(void * arg,dns_name_t * addname,dns_rdatatype_t type)5758 check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
5759 return (check_section(arg, addname, type, DNS_SECTION_ADDITIONAL));
5760 }
5761
5762 #ifndef CHECK_FOR_GLUE_IN_ANSWER
5763 #define CHECK_FOR_GLUE_IN_ANSWER 0
5764 #endif
5765 #if CHECK_FOR_GLUE_IN_ANSWER
5766 static isc_result_t
check_answer(void * arg,dns_name_t * addname,dns_rdatatype_t type)5767 check_answer(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
5768 return (check_section(arg, addname, type, DNS_SECTION_ANSWER));
5769 }
5770 #endif
5771
5772 static void
chase_additional(fetchctx_t * fctx)5773 chase_additional(fetchctx_t *fctx) {
5774 isc_boolean_t rescan;
5775 dns_section_t section = DNS_SECTION_ADDITIONAL;
5776 isc_result_t result;
5777
5778 again:
5779 rescan = ISC_FALSE;
5780
5781 for (result = dns_message_firstname(fctx->rmessage, section);
5782 result == ISC_R_SUCCESS;
5783 result = dns_message_nextname(fctx->rmessage, section)) {
5784 dns_name_t *name = NULL;
5785 dns_rdataset_t *rdataset;
5786 dns_message_currentname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
5787 &name);
5788 if ((name->attributes & DNS_NAMEATTR_CHASE) == 0)
5789 continue;
5790 name->attributes &= ~DNS_NAMEATTR_CHASE;
5791 for (rdataset = ISC_LIST_HEAD(name->list);
5792 rdataset != NULL;
5793 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5794 if (CHASE(rdataset)) {
5795 rdataset->attributes &= ~DNS_RDATASETATTR_CHASE;
5796 (void)dns_rdataset_additionaldata(rdataset,
5797 check_related,
5798 fctx);
5799 rescan = ISC_TRUE;
5800 }
5801 }
5802 }
5803 if (rescan)
5804 goto again;
5805 }
5806
5807 static inline isc_result_t
cname_target(dns_rdataset_t * rdataset,dns_name_t * tname)5808 cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) {
5809 isc_result_t result;
5810 dns_rdata_t rdata = DNS_RDATA_INIT;
5811 dns_rdata_cname_t cname;
5812
5813 result = dns_rdataset_first(rdataset);
5814 if (result != ISC_R_SUCCESS)
5815 return (result);
5816 dns_rdataset_current(rdataset, &rdata);
5817 result = dns_rdata_tostruct(&rdata, &cname, NULL);
5818 if (result != ISC_R_SUCCESS)
5819 return (result);
5820 dns_name_init(tname, NULL);
5821 dns_name_clone(&cname.cname, tname);
5822 dns_rdata_freestruct(&cname);
5823
5824 return (ISC_R_SUCCESS);
5825 }
5826
5827 static inline isc_result_t
dname_target(dns_rdataset_t * rdataset,dns_name_t * qname,unsigned int nlabels,dns_fixedname_t * fixeddname)5828 dname_target(dns_rdataset_t *rdataset, dns_name_t *qname,
5829 unsigned int nlabels, dns_fixedname_t *fixeddname)
5830 {
5831 isc_result_t result;
5832 dns_rdata_t rdata = DNS_RDATA_INIT;
5833 dns_rdata_dname_t dname;
5834 dns_fixedname_t prefix;
5835
5836 /*
5837 * Get the target name of the DNAME.
5838 */
5839 result = dns_rdataset_first(rdataset);
5840 if (result != ISC_R_SUCCESS)
5841 return (result);
5842 dns_rdataset_current(rdataset, &rdata);
5843 result = dns_rdata_tostruct(&rdata, &dname, NULL);
5844 if (result != ISC_R_SUCCESS)
5845 return (result);
5846
5847 dns_fixedname_init(&prefix);
5848 dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
5849 dns_fixedname_init(fixeddname);
5850 result = dns_name_concatenate(dns_fixedname_name(&prefix),
5851 &dname.dname,
5852 dns_fixedname_name(fixeddname), NULL);
5853 dns_rdata_freestruct(&dname);
5854 return (result);
5855 }
5856
5857 static isc_boolean_t
is_answeraddress_allowed(dns_view_t * view,dns_name_t * name,dns_rdataset_t * rdataset)5858 is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
5859 dns_rdataset_t *rdataset)
5860 {
5861 isc_result_t result;
5862 dns_rdata_t rdata = DNS_RDATA_INIT;
5863 struct in_addr ina;
5864 struct in6_addr in6a;
5865 isc_netaddr_t netaddr;
5866 char addrbuf[ISC_NETADDR_FORMATSIZE];
5867 char namebuf[DNS_NAME_FORMATSIZE];
5868 char classbuf[64];
5869 char typebuf[64];
5870 int match;
5871
5872 /* By default, we allow any addresses. */
5873 if (view->denyansweracl == NULL)
5874 return (ISC_TRUE);
5875
5876 /*
5877 * If the owner name matches one in the exclusion list, either exactly
5878 * or partially, allow it.
5879 */
5880 if (view->answeracl_exclude != NULL) {
5881 dns_rbtnode_t *node = NULL;
5882
5883 result = dns_rbt_findnode(view->answeracl_exclude, name, NULL,
5884 &node, NULL, 0, NULL, NULL);
5885
5886 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
5887 return (ISC_TRUE);
5888 }
5889
5890 /*
5891 * Otherwise, search the filter list for a match for each address
5892 * record. If a match is found, the address should be filtered,
5893 * so should the entire answer.
5894 */
5895 for (result = dns_rdataset_first(rdataset);
5896 result == ISC_R_SUCCESS;
5897 result = dns_rdataset_next(rdataset)) {
5898 dns_rdata_reset(&rdata);
5899 dns_rdataset_current(rdataset, &rdata);
5900 if (rdataset->type == dns_rdatatype_a) {
5901 INSIST(rdata.length == sizeof(ina.s_addr));
5902 memmove(&ina.s_addr, rdata.data, sizeof(ina.s_addr));
5903 isc_netaddr_fromin(&netaddr, &ina);
5904 } else {
5905 INSIST(rdata.length == sizeof(in6a.s6_addr));
5906 memmove(in6a.s6_addr, rdata.data, sizeof(in6a.s6_addr));
5907 isc_netaddr_fromin6(&netaddr, &in6a);
5908 }
5909
5910 result = dns_acl_match(&netaddr, NULL, view->denyansweracl,
5911 &view->aclenv, &match, NULL);
5912
5913 if (result == ISC_R_SUCCESS && match > 0) {
5914 isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
5915 dns_name_format(name, namebuf, sizeof(namebuf));
5916 dns_rdatatype_format(rdataset->type, typebuf,
5917 sizeof(typebuf));
5918 dns_rdataclass_format(rdataset->rdclass, classbuf,
5919 sizeof(classbuf));
5920 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5921 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
5922 "answer address %s denied for %s/%s/%s",
5923 addrbuf, namebuf, typebuf, classbuf);
5924 return (ISC_FALSE);
5925 }
5926 }
5927
5928 return (ISC_TRUE);
5929 }
5930
5931 static isc_boolean_t
is_answertarget_allowed(dns_view_t * view,dns_name_t * name,dns_rdatatype_t type,dns_name_t * tname,dns_name_t * domain)5932 is_answertarget_allowed(dns_view_t *view, dns_name_t *name,
5933 dns_rdatatype_t type, dns_name_t *tname,
5934 dns_name_t *domain)
5935 {
5936 isc_result_t result;
5937 dns_rbtnode_t *node = NULL;
5938 char qnamebuf[DNS_NAME_FORMATSIZE];
5939 char tnamebuf[DNS_NAME_FORMATSIZE];
5940 char classbuf[64];
5941 char typebuf[64];
5942
5943 /* By default, we allow any target name. */
5944 if (view->denyanswernames == NULL)
5945 return (ISC_TRUE);
5946
5947 /*
5948 * If the owner name matches one in the exclusion list, either exactly
5949 * or partially, allow it.
5950 */
5951 if (view->answernames_exclude != NULL) {
5952 result = dns_rbt_findnode(view->answernames_exclude, name, NULL,
5953 &node, NULL, 0, NULL, NULL);
5954 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
5955 return (ISC_TRUE);
5956 }
5957
5958 /*
5959 * If the target name is a subdomain of the search domain, allow it.
5960 */
5961 if (dns_name_issubdomain(tname, domain))
5962 return (ISC_TRUE);
5963
5964 /*
5965 * Otherwise, apply filters.
5966 */
5967 result = dns_rbt_findnode(view->denyanswernames, tname, NULL, &node,
5968 NULL, 0, NULL, NULL);
5969 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
5970 dns_name_format(name, qnamebuf, sizeof(qnamebuf));
5971 dns_name_format(tname, tnamebuf, sizeof(tnamebuf));
5972 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
5973 dns_rdataclass_format(view->rdclass, classbuf,
5974 sizeof(classbuf));
5975 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5976 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
5977 "%s target %s denied for %s/%s",
5978 typebuf, tnamebuf, qnamebuf, classbuf);
5979 return (ISC_FALSE);
5980 }
5981
5982 return (ISC_TRUE);
5983 }
5984
5985 static void
trim_ns_ttl(fetchctx_t * fctx,dns_name_t * name,dns_rdataset_t * rdataset)5986 trim_ns_ttl(fetchctx_t *fctx, dns_name_t *name, dns_rdataset_t *rdataset) {
5987 char ns_namebuf[DNS_NAME_FORMATSIZE];
5988 char namebuf[DNS_NAME_FORMATSIZE];
5989 char tbuf[DNS_RDATATYPE_FORMATSIZE];
5990
5991 if (fctx->ns_ttl_ok && rdataset->ttl > fctx->ns_ttl) {
5992 dns_name_format(name, ns_namebuf, sizeof(ns_namebuf));
5993 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
5994 dns_rdatatype_format(fctx->type, tbuf, sizeof(tbuf));
5995
5996 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5997 DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
5998 "fctx %p: trimming ttl of %s/NS for %s/%s: "
5999 "%u -> %u", fctx, ns_namebuf, namebuf, tbuf,
6000 rdataset->ttl, fctx->ns_ttl);
6001 rdataset->ttl = fctx->ns_ttl;
6002 }
6003 }
6004
6005 /*
6006 * Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
6007 * If look_in_options has LOOK_FOR_NS_IN_ANSWER then we look in the answer
6008 * section for the NS RRset if the query type is NS; if it has
6009 * LOOK_FOR_GLUE_IN_ANSWER we look for glue incorrectly returned in the answer
6010 * section for A and AAAA queries.
6011 */
6012 #define LOOK_FOR_NS_IN_ANSWER 0x1
6013 #define LOOK_FOR_GLUE_IN_ANSWER 0x2
6014
6015 static isc_result_t
noanswer_response(fetchctx_t * fctx,dns_name_t * oqname,unsigned int look_in_options)6016 noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
6017 unsigned int look_in_options)
6018 {
6019 isc_result_t result;
6020 dns_message_t *message;
6021 dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name, *save_name;
6022 dns_rdataset_t *rdataset, *ns_rdataset;
6023 isc_boolean_t aa, negative_response;
6024 dns_rdatatype_t type, save_type;
6025 dns_section_t section;
6026
6027 FCTXTRACE("noanswer_response");
6028
6029 if ((look_in_options & LOOK_FOR_NS_IN_ANSWER) != 0) {
6030 INSIST(fctx->type == dns_rdatatype_ns);
6031 section = DNS_SECTION_ANSWER;
6032 } else
6033 section = DNS_SECTION_AUTHORITY;
6034
6035 message = fctx->rmessage;
6036
6037 /*
6038 * Setup qname.
6039 */
6040 if (oqname == NULL) {
6041 /*
6042 * We have a normal, non-chained negative response or
6043 * referral.
6044 */
6045 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
6046 aa = ISC_TRUE;
6047 else
6048 aa = ISC_FALSE;
6049 qname = &fctx->name;
6050 } else {
6051 /*
6052 * We're being invoked by answer_response() after it has
6053 * followed a CNAME/DNAME chain.
6054 */
6055 qname = oqname;
6056 aa = ISC_FALSE;
6057 /*
6058 * If the current qname is not a subdomain of the query
6059 * domain, there's no point in looking at the authority
6060 * section without doing DNSSEC validation.
6061 *
6062 * Until we do that validation, we'll just return success
6063 * in this case.
6064 */
6065 if (!dns_name_issubdomain(qname, &fctx->domain))
6066 return (ISC_R_SUCCESS);
6067 }
6068
6069 /*
6070 * We have to figure out if this is a negative response, or a
6071 * referral.
6072 */
6073
6074 /*
6075 * Sometimes we can tell if its a negative response by looking at
6076 * the message header.
6077 */
6078 negative_response = ISC_FALSE;
6079 if (message->rcode == dns_rcode_nxdomain ||
6080 (message->counts[DNS_SECTION_ANSWER] == 0 &&
6081 message->counts[DNS_SECTION_AUTHORITY] == 0))
6082 negative_response = ISC_TRUE;
6083
6084 /*
6085 * Process the authority section.
6086 */
6087 ns_name = NULL;
6088 ns_rdataset = NULL;
6089 soa_name = NULL;
6090 ds_name = NULL;
6091 save_name = NULL;
6092 save_type = dns_rdatatype_none;
6093 result = dns_message_firstname(message, section);
6094 while (result == ISC_R_SUCCESS) {
6095 name = NULL;
6096 dns_message_currentname(message, section, &name);
6097 if (dns_name_issubdomain(name, &fctx->domain)) {
6098 /*
6099 * Look for NS/SOA RRsets first.
6100 */
6101 for (rdataset = ISC_LIST_HEAD(name->list);
6102 rdataset != NULL;
6103 rdataset = ISC_LIST_NEXT(rdataset, link)) {
6104 type = rdataset->type;
6105 if (type == dns_rdatatype_rrsig)
6106 type = rdataset->covers;
6107 if (((type == dns_rdatatype_ns ||
6108 type == dns_rdatatype_soa) &&
6109 !dns_name_issubdomain(qname, name))) {
6110 char qbuf[DNS_NAME_FORMATSIZE];
6111 char nbuf[DNS_NAME_FORMATSIZE];
6112 char tbuf[DNS_RDATATYPE_FORMATSIZE];
6113 dns_rdatatype_format(type, tbuf,
6114 sizeof(tbuf));
6115 dns_name_format(name, nbuf,
6116 sizeof(nbuf));
6117 dns_name_format(qname, qbuf,
6118 sizeof(qbuf));
6119 log_formerr(fctx,
6120 "unrelated %s %s in "
6121 "%s authority section",
6122 tbuf, nbuf, qbuf);
6123 goto nextname;
6124 }
6125 if (type == dns_rdatatype_ns) {
6126 /*
6127 * NS or RRSIG NS.
6128 *
6129 * Only one set of NS RRs is allowed.
6130 */
6131 if (rdataset->type ==
6132 dns_rdatatype_ns) {
6133 if (ns_name != NULL &&
6134 name != ns_name) {
6135 log_formerr(fctx,
6136 "multiple NS "
6137 "RRsets in "
6138 "authority "
6139 "section");
6140 return (DNS_R_FORMERR);
6141 }
6142 ns_name = name;
6143 ns_rdataset = rdataset;
6144 }
6145 name->attributes |=
6146 DNS_NAMEATTR_CACHE;
6147 rdataset->attributes |=
6148 DNS_RDATASETATTR_CACHE;
6149 rdataset->trust = dns_trust_glue;
6150 }
6151 if (type == dns_rdatatype_soa) {
6152 /*
6153 * SOA, or RRSIG SOA.
6154 *
6155 * Only one SOA is allowed.
6156 */
6157 if (rdataset->type ==
6158 dns_rdatatype_soa) {
6159 if (soa_name != NULL &&
6160 name != soa_name) {
6161 log_formerr(fctx,
6162 "multiple SOA "
6163 "RRs in "
6164 "authority "
6165 "section");
6166 return (DNS_R_FORMERR);
6167 }
6168 soa_name = name;
6169 }
6170 name->attributes |=
6171 DNS_NAMEATTR_NCACHE;
6172 rdataset->attributes |=
6173 DNS_RDATASETATTR_NCACHE;
6174 if (aa)
6175 rdataset->trust =
6176 dns_trust_authauthority;
6177 else if (ISFORWARDER(fctx->addrinfo))
6178 rdataset->trust =
6179 dns_trust_answer;
6180 else
6181 rdataset->trust =
6182 dns_trust_additional;
6183 }
6184 }
6185 }
6186 nextname:
6187 result = dns_message_nextname(message, section);
6188 if (result == ISC_R_NOMORE)
6189 break;
6190 else if (result != ISC_R_SUCCESS)
6191 return (result);
6192 }
6193
6194 log_ns_ttl(fctx, "noanswer_response");
6195
6196 if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
6197 !dns_name_equal(ns_name, dns_rootname))
6198 trim_ns_ttl(fctx, ns_name, ns_rdataset);
6199
6200 /*
6201 * A negative response has a SOA record (Type 2)
6202 * and a optional NS RRset (Type 1) or it has neither
6203 * a SOA or a NS RRset (Type 3, handled above) or
6204 * rcode is NXDOMAIN (handled above) in which case
6205 * the NS RRset is allowed (Type 4).
6206 */
6207 if (soa_name != NULL)
6208 negative_response = ISC_TRUE;
6209
6210 result = dns_message_firstname(message, section);
6211 while (result == ISC_R_SUCCESS) {
6212 name = NULL;
6213 dns_message_currentname(message, section, &name);
6214 if (dns_name_issubdomain(name, &fctx->domain)) {
6215 for (rdataset = ISC_LIST_HEAD(name->list);
6216 rdataset != NULL;
6217 rdataset = ISC_LIST_NEXT(rdataset, link)) {
6218 type = rdataset->type;
6219 if (type == dns_rdatatype_rrsig)
6220 type = rdataset->covers;
6221 if (type == dns_rdatatype_nsec ||
6222 type == dns_rdatatype_nsec3) {
6223 /*
6224 * NSEC or RRSIG NSEC.
6225 */
6226 if (negative_response) {
6227 name->attributes |=
6228 DNS_NAMEATTR_NCACHE;
6229 rdataset->attributes |=
6230 DNS_RDATASETATTR_NCACHE;
6231 } else if (type == dns_rdatatype_nsec) {
6232 name->attributes |=
6233 DNS_NAMEATTR_CACHE;
6234 rdataset->attributes |=
6235 DNS_RDATASETATTR_CACHE;
6236 }
6237 if (aa)
6238 rdataset->trust =
6239 dns_trust_authauthority;
6240 else if (ISFORWARDER(fctx->addrinfo))
6241 rdataset->trust =
6242 dns_trust_answer;
6243 else
6244 rdataset->trust =
6245 dns_trust_additional;
6246 /*
6247 * No additional data needs to be
6248 * marked.
6249 */
6250 } else if (type == dns_rdatatype_ds) {
6251 /*
6252 * DS or SIG DS.
6253 *
6254 * These should only be here if
6255 * this is a referral, and there
6256 * should only be one DS RRset.
6257 */
6258 if (ns_name == NULL) {
6259 log_formerr(fctx,
6260 "DS with no "
6261 "referral");
6262 return (DNS_R_FORMERR);
6263 }
6264 if (rdataset->type ==
6265 dns_rdatatype_ds) {
6266 if (ds_name != NULL &&
6267 name != ds_name) {
6268 log_formerr(fctx,
6269 "DS doesn't "
6270 "match "
6271 "referral "
6272 "(NS)");
6273 return (DNS_R_FORMERR);
6274 }
6275 ds_name = name;
6276 }
6277 name->attributes |=
6278 DNS_NAMEATTR_CACHE;
6279 rdataset->attributes |=
6280 DNS_RDATASETATTR_CACHE;
6281 if (aa)
6282 rdataset->trust =
6283 dns_trust_authauthority;
6284 else if (ISFORWARDER(fctx->addrinfo))
6285 rdataset->trust =
6286 dns_trust_answer;
6287 else
6288 rdataset->trust =
6289 dns_trust_additional;
6290 }
6291 }
6292 } else {
6293 save_name = name;
6294 save_type = ISC_LIST_HEAD(name->list)->type;
6295 }
6296 result = dns_message_nextname(message, section);
6297 if (result == ISC_R_NOMORE)
6298 break;
6299 else if (result != ISC_R_SUCCESS)
6300 return (result);
6301 }
6302
6303 /*
6304 * Trigger lookups for DNS nameservers.
6305 */
6306 if (negative_response && message->rcode == dns_rcode_noerror &&
6307 fctx->type == dns_rdatatype_ds && soa_name != NULL &&
6308 dns_name_equal(soa_name, qname) &&
6309 !dns_name_equal(qname, dns_rootname))
6310 return (DNS_R_CHASEDSSERVERS);
6311
6312 /*
6313 * Did we find anything?
6314 */
6315 if (!negative_response && ns_name == NULL) {
6316 /*
6317 * Nope.
6318 */
6319 if (oqname != NULL) {
6320 /*
6321 * We've already got a partial CNAME/DNAME chain,
6322 * and haven't found else anything useful here, but
6323 * no error has occurred since we have an answer.
6324 */
6325 return (ISC_R_SUCCESS);
6326 } else {
6327 /*
6328 * The responder is insane.
6329 */
6330 if (save_name == NULL) {
6331 log_formerr(fctx, "invalid response");
6332 return (DNS_R_FORMERR);
6333 }
6334 if (!dns_name_issubdomain(save_name, &fctx->domain)) {
6335 char nbuf[DNS_NAME_FORMATSIZE];
6336 char dbuf[DNS_NAME_FORMATSIZE];
6337 char tbuf[DNS_RDATATYPE_FORMATSIZE];
6338
6339 dns_rdatatype_format(save_type, tbuf,
6340 sizeof(tbuf));
6341 dns_name_format(save_name, nbuf, sizeof(nbuf));
6342 dns_name_format(&fctx->domain, dbuf,
6343 sizeof(dbuf));
6344
6345 log_formerr(fctx, "Name %s (%s) not subdomain"
6346 " of zone %s -- invalid response",
6347 nbuf, tbuf, dbuf);
6348 } else {
6349 log_formerr(fctx, "invalid response");
6350 }
6351 return (DNS_R_FORMERR);
6352 }
6353 }
6354
6355 /*
6356 * If we found both NS and SOA, they should be the same name.
6357 */
6358 if (ns_name != NULL && soa_name != NULL && ns_name != soa_name) {
6359 log_formerr(fctx, "NS/SOA mismatch");
6360 return (DNS_R_FORMERR);
6361 }
6362
6363 /*
6364 * Do we have a referral? (We only want to follow a referral if
6365 * we're not following a chain.)
6366 */
6367 if (!negative_response && ns_name != NULL && oqname == NULL) {
6368 /*
6369 * We already know ns_name is a subdomain of fctx->domain.
6370 * If ns_name is equal to fctx->domain, we're not making
6371 * progress. We return DNS_R_FORMERR so that we'll keep
6372 * trying other servers.
6373 */
6374 if (dns_name_equal(ns_name, &fctx->domain)) {
6375 log_formerr(fctx, "non-improving referral");
6376 return (DNS_R_FORMERR);
6377 }
6378
6379 /*
6380 * If the referral name is not a parent of the query
6381 * name, consider the responder insane.
6382 */
6383 if (! dns_name_issubdomain(&fctx->name, ns_name)) {
6384 /* Logged twice */
6385 log_formerr(fctx, "referral to non-parent");
6386 FCTXTRACE("referral to non-parent");
6387 return (DNS_R_FORMERR);
6388 }
6389
6390 /*
6391 * Mark any additional data related to this rdataset.
6392 * It's important that we do this before we change the
6393 * query domain.
6394 */
6395 INSIST(ns_rdataset != NULL);
6396 fctx->attributes |= FCTX_ATTR_GLUING;
6397 (void)dns_rdataset_additionaldata(ns_rdataset, check_related,
6398 fctx);
6399 #if CHECK_FOR_GLUE_IN_ANSWER
6400 /*
6401 * Look in the answer section for "glue" that is incorrectly
6402 * returned as a answer. This is needed if the server also
6403 * minimizes the response size by not adding records to the
6404 * additional section that are in the answer section or if
6405 * the record gets dropped due to message size constraints.
6406 */
6407 if ((look_in_options & LOOK_FOR_GLUE_IN_ANSWER) != 0 &&
6408 (fctx->type == dns_rdatatype_aaaa ||
6409 fctx->type == dns_rdatatype_a))
6410 (void)dns_rdataset_additionaldata(ns_rdataset,
6411 check_answer, fctx);
6412 #endif
6413 fctx->attributes &= ~FCTX_ATTR_GLUING;
6414 /*
6415 * NS rdatasets with 0 TTL cause problems.
6416 * dns_view_findzonecut() will not find them when we
6417 * try to follow the referral, and we'll SERVFAIL
6418 * because the best nameservers are now above QDOMAIN.
6419 * We force the TTL to 1 second to prevent this.
6420 */
6421 if (ns_rdataset->ttl == 0)
6422 ns_rdataset->ttl = 1;
6423 /*
6424 * Set the current query domain to the referral name.
6425 *
6426 * XXXRTH We should check if we're in forward-only mode, and
6427 * if so we should bail out.
6428 */
6429 INSIST(dns_name_countlabels(&fctx->domain) > 0);
6430
6431 #ifdef ENABLE_FETCHLIMIT
6432 fcount_decr(fctx);
6433 #endif /* ENABLE_FETCHLIMIT */
6434
6435 dns_name_free(&fctx->domain, fctx->mctx);
6436 if (dns_rdataset_isassociated(&fctx->nameservers))
6437 dns_rdataset_disassociate(&fctx->nameservers);
6438 dns_name_init(&fctx->domain, NULL);
6439 result = dns_name_dup(ns_name, fctx->mctx, &fctx->domain);
6440 if (result != ISC_R_SUCCESS)
6441 return (result);
6442
6443 #ifdef ENABLE_FETCHLIMIT
6444 result = fcount_incr(fctx, ISC_TRUE);
6445 if (result != ISC_R_SUCCESS)
6446 return (result);
6447 #endif /* ENABLE_FETCHLIMIT */
6448
6449 fctx->attributes |= FCTX_ATTR_WANTCACHE;
6450 fctx->ns_ttl_ok = ISC_FALSE;
6451 log_ns_ttl(fctx, "DELEGATION");
6452 return (DNS_R_DELEGATION);
6453 }
6454
6455 /*
6456 * Since we're not doing a referral, we don't want to cache any
6457 * NS RRs we may have found.
6458 */
6459 if (ns_name != NULL)
6460 ns_name->attributes &= ~DNS_NAMEATTR_CACHE;
6461
6462 if (negative_response && oqname == NULL)
6463 fctx->attributes |= FCTX_ATTR_WANTNCACHE;
6464
6465 return (ISC_R_SUCCESS);
6466 }
6467
6468 static isc_result_t
answer_response(fetchctx_t * fctx)6469 answer_response(fetchctx_t *fctx) {
6470 isc_result_t result;
6471 dns_message_t *message;
6472 dns_name_t *name, *dname = NULL, *qname, *dqname, tname, *ns_name;
6473 dns_name_t *cname = NULL;
6474 dns_rdataset_t *rdataset, *ns_rdataset;
6475 isc_boolean_t done, external, chaining, aa, found, want_chaining;
6476 isc_boolean_t have_answer, found_cname, found_dname, found_type;
6477 isc_boolean_t wanted_chaining;
6478 unsigned int aflag;
6479 dns_rdatatype_t type;
6480 dns_fixedname_t fdname, fqname, fqdname;
6481 dns_view_t *view;
6482
6483 FCTXTRACE("answer_response");
6484
6485 message = fctx->rmessage;
6486
6487 /*
6488 * Examine the answer section, marking those rdatasets which are
6489 * part of the answer and should be cached.
6490 */
6491
6492 done = ISC_FALSE;
6493 found_cname = ISC_FALSE;
6494 found_dname = ISC_FALSE;
6495 found_type = ISC_FALSE;
6496 chaining = ISC_FALSE;
6497 have_answer = ISC_FALSE;
6498 want_chaining = ISC_FALSE;
6499 POST(want_chaining);
6500 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
6501 aa = ISC_TRUE;
6502 else
6503 aa = ISC_FALSE;
6504 dqname = qname = &fctx->name;
6505 type = fctx->type;
6506 view = fctx->res->view;
6507 dns_fixedname_init(&fqdname);
6508 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
6509 while (!done && result == ISC_R_SUCCESS) {
6510 dns_namereln_t namereln, dnamereln;
6511 int order;
6512 unsigned int nlabels;
6513
6514 name = NULL;
6515 dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
6516 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
6517 namereln = dns_name_fullcompare(qname, name, &order, &nlabels);
6518 dnamereln = dns_name_fullcompare(dqname, name, &order,
6519 &nlabels);
6520 if (namereln == dns_namereln_equal) {
6521 wanted_chaining = ISC_FALSE;
6522 for (rdataset = ISC_LIST_HEAD(name->list);
6523 rdataset != NULL;
6524 rdataset = ISC_LIST_NEXT(rdataset, link)) {
6525 found = ISC_FALSE;
6526 want_chaining = ISC_FALSE;
6527 aflag = 0;
6528 if (rdataset->type == dns_rdatatype_nsec3) {
6529 /*
6530 * NSEC3 records are not allowed to
6531 * appear in the answer section.
6532 */
6533 log_formerr(fctx, "NSEC3 in answer");
6534 return (DNS_R_FORMERR);
6535 }
6536
6537 /*
6538 * Apply filters, if given, on answers to reject
6539 * a malicious attempt of rebinding.
6540 */
6541 if ((rdataset->type == dns_rdatatype_a ||
6542 rdataset->type == dns_rdatatype_aaaa) &&
6543 !is_answeraddress_allowed(view, name,
6544 rdataset)) {
6545 return (DNS_R_SERVFAIL);
6546 }
6547
6548 if (rdataset->type == type && !found_cname) {
6549 /*
6550 * We've found an ordinary answer.
6551 */
6552 found = ISC_TRUE;
6553 found_type = ISC_TRUE;
6554 done = ISC_TRUE;
6555 aflag = DNS_RDATASETATTR_ANSWER;
6556 } else if (type == dns_rdatatype_any) {
6557 /*
6558 * We've found an answer matching
6559 * an ANY query. There may be
6560 * more.
6561 */
6562 found = ISC_TRUE;
6563 aflag = DNS_RDATASETATTR_ANSWER;
6564 } else if (rdataset->type == dns_rdatatype_rrsig
6565 && rdataset->covers == type
6566 && !found_cname) {
6567 /*
6568 * We've found a signature that
6569 * covers the type we're looking for.
6570 */
6571 found = ISC_TRUE;
6572 found_type = ISC_TRUE;
6573 aflag = DNS_RDATASETATTR_ANSWERSIG;
6574 } else if (rdataset->type ==
6575 dns_rdatatype_cname
6576 && !found_type) {
6577 /*
6578 * We're looking for something else,
6579 * but we found a CNAME.
6580 *
6581 * Getting a CNAME response for some
6582 * query types is an error, see
6583 * RFC 4035, Section 2.5.
6584 */
6585 if (type == dns_rdatatype_rrsig ||
6586 type == dns_rdatatype_key ||
6587 type == dns_rdatatype_nsec) {
6588 char buf[DNS_RDATATYPE_FORMATSIZE];
6589 dns_rdatatype_format(fctx->type,
6590 buf, sizeof(buf));
6591 log_formerr(fctx,
6592 "CNAME response "
6593 "for %s RR", buf);
6594 return (DNS_R_FORMERR);
6595 }
6596 found = ISC_TRUE;
6597 found_cname = ISC_TRUE;
6598 want_chaining = ISC_TRUE;
6599 aflag = DNS_RDATASETATTR_ANSWER;
6600 result = cname_target(rdataset,
6601 &tname);
6602 if (result != ISC_R_SUCCESS)
6603 return (result);
6604 /* Apply filters on the target name. */
6605 if (!is_answertarget_allowed(view,
6606 name,
6607 rdataset->type,
6608 &tname,
6609 &fctx->domain)) {
6610 return (DNS_R_SERVFAIL);
6611 }
6612 } else if (rdataset->type == dns_rdatatype_rrsig
6613 && rdataset->covers ==
6614 dns_rdatatype_cname
6615 && !found_type) {
6616 /*
6617 * We're looking for something else,
6618 * but we found a SIG CNAME.
6619 */
6620 found = ISC_TRUE;
6621 found_cname = ISC_TRUE;
6622 aflag = DNS_RDATASETATTR_ANSWERSIG;
6623 }
6624
6625 if (found) {
6626 /*
6627 * We've found an answer to our
6628 * question.
6629 */
6630 name->attributes |=
6631 DNS_NAMEATTR_CACHE;
6632 rdataset->attributes |=
6633 DNS_RDATASETATTR_CACHE;
6634 rdataset->trust = dns_trust_answer;
6635 if (!chaining) {
6636 /*
6637 * This data is "the" answer
6638 * to our question only if
6639 * we're not chaining (i.e.
6640 * if we haven't followed
6641 * a CNAME or DNAME).
6642 */
6643 INSIST(!external);
6644 if ((rdataset->type !=
6645 dns_rdatatype_cname) ||
6646 !found_dname ||
6647 (aflag ==
6648 DNS_RDATASETATTR_ANSWER))
6649 {
6650 have_answer = ISC_TRUE;
6651 if (rdataset->type ==
6652 dns_rdatatype_cname)
6653 cname = name;
6654 name->attributes |=
6655 DNS_NAMEATTR_ANSWER;
6656 }
6657 rdataset->attributes |= aflag;
6658 if (aa)
6659 rdataset->trust =
6660 dns_trust_authanswer;
6661 } else if (external) {
6662 /*
6663 * This data is outside of
6664 * our query domain, and
6665 * may not be cached.
6666 */
6667 rdataset->attributes |=
6668 DNS_RDATASETATTR_EXTERNAL;
6669 }
6670
6671 /*
6672 * Mark any additional data related
6673 * to this rdataset.
6674 */
6675 (void)dns_rdataset_additionaldata(
6676 rdataset,
6677 check_related,
6678 fctx);
6679
6680 /*
6681 * CNAME chaining.
6682 */
6683 if (want_chaining) {
6684 wanted_chaining = ISC_TRUE;
6685 name->attributes |=
6686 DNS_NAMEATTR_CHAINING;
6687 rdataset->attributes |=
6688 DNS_RDATASETATTR_CHAINING;
6689 qname = &tname;
6690 }
6691 }
6692 /*
6693 * We could add an "else" clause here and
6694 * log that we're ignoring this rdataset.
6695 */
6696 }
6697 /*
6698 * If wanted_chaining is true, we've done
6699 * some chaining as the result of processing
6700 * this node, and thus we need to set
6701 * chaining to true.
6702 *
6703 * We don't set chaining inside of the
6704 * rdataset loop because doing that would
6705 * cause us to ignore the signatures of
6706 * CNAMEs.
6707 */
6708 if (wanted_chaining)
6709 chaining = ISC_TRUE;
6710 } else {
6711 dns_rdataset_t *dnameset = NULL;
6712
6713 /*
6714 * Look for a DNAME (or its SIG). Anything else is
6715 * ignored.
6716 */
6717 wanted_chaining = ISC_FALSE;
6718 for (rdataset = ISC_LIST_HEAD(name->list);
6719 rdataset != NULL;
6720 rdataset = ISC_LIST_NEXT(rdataset, link))
6721 {
6722 /*
6723 * Only pass DNAME or RRSIG(DNAME).
6724 */
6725 if (rdataset->type != dns_rdatatype_dname &&
6726 (rdataset->type != dns_rdatatype_rrsig ||
6727 rdataset->covers != dns_rdatatype_dname))
6728 continue;
6729
6730 /*
6731 * If we're not chaining, then the DNAME and
6732 * its signature should not be external.
6733 */
6734 if (!chaining && external) {
6735 char qbuf[DNS_NAME_FORMATSIZE];
6736 char obuf[DNS_NAME_FORMATSIZE];
6737
6738 dns_name_format(name, qbuf,
6739 sizeof(qbuf));
6740 dns_name_format(&fctx->domain, obuf,
6741 sizeof(obuf));
6742 log_formerr(fctx, "external DNAME or "
6743 "RRSIG covering DNAME "
6744 "in answer: %s is "
6745 "not in %s", qbuf, obuf);
6746 return (DNS_R_FORMERR);
6747 }
6748
6749 if (dnamereln != dns_namereln_subdomain) {
6750 char qbuf[DNS_NAME_FORMATSIZE];
6751 char obuf[DNS_NAME_FORMATSIZE];
6752
6753 dns_name_format(dqname, qbuf,
6754 sizeof(qbuf));
6755 dns_name_format(name, obuf,
6756 sizeof(obuf));
6757 log_formerr(fctx, "unrelated DNAME "
6758 "in answer: %s is "
6759 "not in %s", qbuf, obuf);
6760 return (DNS_R_FORMERR);
6761 }
6762
6763 aflag = 0;
6764 if (rdataset->type == dns_rdatatype_dname) {
6765 want_chaining = ISC_TRUE;
6766 POST(want_chaining);
6767 aflag = DNS_RDATASETATTR_ANSWER;
6768 result = dname_target(rdataset, dqname,
6769 nlabels, &fdname);
6770 if (result == ISC_R_NOSPACE) {
6771 /*
6772 * We can't construct the
6773 * DNAME target. Do not
6774 * try to continue.
6775 */
6776 want_chaining = ISC_FALSE;
6777 POST(want_chaining);
6778 } else if (result != ISC_R_SUCCESS)
6779 return (result);
6780 else
6781 dnameset = rdataset;
6782
6783 dname = dns_fixedname_name(&fdname);
6784 if (!is_answertarget_allowed(view,
6785 dqname, rdataset->type,
6786 dname, &fctx->domain))
6787 {
6788 return (DNS_R_SERVFAIL);
6789 }
6790 dqname = dns_fixedname_name(&fqdname);
6791 dns_name_copy(dname, dqname, NULL);
6792 } else {
6793 /*
6794 * We've found a signature that
6795 * covers the DNAME.
6796 */
6797 aflag = DNS_RDATASETATTR_ANSWERSIG;
6798 }
6799
6800 /*
6801 * We've found an answer to our
6802 * question.
6803 */
6804 name->attributes |= DNS_NAMEATTR_CACHE;
6805 rdataset->attributes |= DNS_RDATASETATTR_CACHE;
6806 rdataset->trust = dns_trust_answer;
6807 if (!chaining) {
6808 /*
6809 * This data is "the" answer to
6810 * our question only if we're
6811 * not chaining.
6812 */
6813 INSIST(!external);
6814 if (aflag == DNS_RDATASETATTR_ANSWER) {
6815 have_answer = ISC_TRUE;
6816 found_dname = ISC_TRUE;
6817 if (cname != NULL)
6818 cname->attributes &=
6819 ~DNS_NAMEATTR_ANSWER;
6820 name->attributes |=
6821 DNS_NAMEATTR_ANSWER;
6822 }
6823 rdataset->attributes |= aflag;
6824 if (aa)
6825 rdataset->trust =
6826 dns_trust_authanswer;
6827 } else if (external) {
6828 rdataset->attributes |=
6829 DNS_RDATASETATTR_EXTERNAL;
6830 }
6831 }
6832
6833 /*
6834 * DNAME chaining.
6835 */
6836 if (dnameset != NULL) {
6837 /*
6838 * Copy the dname into the qname fixed name.
6839 *
6840 * Although we check for failure of the copy
6841 * operation, in practice it should never fail
6842 * since we already know that the result fits
6843 * in a fixedname.
6844 */
6845 dns_fixedname_init(&fqname);
6846 qname = dns_fixedname_name(&fqname);
6847 result = dns_name_copy(dname, qname, NULL);
6848 if (result != ISC_R_SUCCESS)
6849 return (result);
6850 wanted_chaining = ISC_TRUE;
6851 name->attributes |= DNS_NAMEATTR_CHAINING;
6852 dnameset->attributes |=
6853 DNS_RDATASETATTR_CHAINING;
6854 }
6855 if (wanted_chaining)
6856 chaining = ISC_TRUE;
6857 }
6858 result = dns_message_nextname(message, DNS_SECTION_ANSWER);
6859 }
6860 if (result == ISC_R_NOMORE)
6861 result = ISC_R_SUCCESS;
6862 if (result != ISC_R_SUCCESS)
6863 return (result);
6864
6865 /*
6866 * We should have found an answer.
6867 */
6868 if (!have_answer) {
6869 log_formerr(fctx, "reply has no answer");
6870 return (DNS_R_FORMERR);
6871 }
6872
6873 /*
6874 * This response is now potentially cacheable.
6875 */
6876 fctx->attributes |= FCTX_ATTR_WANTCACHE;
6877
6878 /*
6879 * Did chaining end before we got the final answer?
6880 */
6881 if (chaining) {
6882 /*
6883 * Yes. This may be a negative reply, so hand off
6884 * authority section processing to the noanswer code.
6885 * If it isn't a noanswer response, no harm will be
6886 * done.
6887 */
6888 return (noanswer_response(fctx, qname, 0));
6889 }
6890
6891 /*
6892 * We didn't end with an incomplete chain, so the rcode should be
6893 * "no error".
6894 */
6895 if (message->rcode != dns_rcode_noerror) {
6896 log_formerr(fctx, "CNAME/DNAME chain complete, but RCODE "
6897 "indicates error");
6898 return (DNS_R_FORMERR);
6899 }
6900
6901 /*
6902 * Examine the authority section (if there is one).
6903 *
6904 * We expect there to be only one owner name for all the rdatasets
6905 * in this section, and we expect that it is not external.
6906 */
6907 done = ISC_FALSE;
6908 ns_name = NULL;
6909 ns_rdataset = NULL;
6910 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
6911 while (!done && result == ISC_R_SUCCESS) {
6912 name = NULL;
6913 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
6914 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
6915 if (!external) {
6916 /*
6917 * We expect to find NS or SIG NS rdatasets, and
6918 * nothing else.
6919 */
6920 for (rdataset = ISC_LIST_HEAD(name->list);
6921 rdataset != NULL;
6922 rdataset = ISC_LIST_NEXT(rdataset, link)) {
6923 if (rdataset->type == dns_rdatatype_ns ||
6924 (rdataset->type == dns_rdatatype_rrsig &&
6925 rdataset->covers == dns_rdatatype_ns)) {
6926 name->attributes |=
6927 DNS_NAMEATTR_CACHE;
6928 rdataset->attributes |=
6929 DNS_RDATASETATTR_CACHE;
6930 if (aa && !chaining)
6931 rdataset->trust =
6932 dns_trust_authauthority;
6933 else
6934 rdataset->trust =
6935 dns_trust_additional;
6936
6937 if (rdataset->type == dns_rdatatype_ns) {
6938 ns_name = name;
6939 ns_rdataset = rdataset;
6940 }
6941 /*
6942 * Mark any additional data related
6943 * to this rdataset.
6944 */
6945 (void)dns_rdataset_additionaldata(
6946 rdataset,
6947 check_related,
6948 fctx);
6949 done = ISC_TRUE;
6950 }
6951 }
6952 }
6953 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
6954 }
6955 if (result == ISC_R_NOMORE)
6956 result = ISC_R_SUCCESS;
6957
6958 log_ns_ttl(fctx, "answer_response");
6959
6960 if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
6961 !dns_name_equal(ns_name, dns_rootname))
6962 trim_ns_ttl(fctx, ns_name, ns_rdataset);
6963
6964 return (result);
6965 }
6966
6967 static void
fctx_increference(fetchctx_t * fctx)6968 fctx_increference(fetchctx_t *fctx) {
6969 REQUIRE(VALID_FCTX(fctx));
6970
6971 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
6972 fctx->references++;
6973 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
6974 }
6975
6976 static isc_boolean_t
fctx_decreference(fetchctx_t * fctx)6977 fctx_decreference(fetchctx_t *fctx) {
6978 isc_boolean_t bucket_empty = ISC_FALSE;
6979
6980 REQUIRE(VALID_FCTX(fctx));
6981
6982 INSIST(fctx->references > 0);
6983 fctx->references--;
6984 if (fctx->references == 0) {
6985 /*
6986 * No one cares about the result of this fetch anymore.
6987 */
6988 if (fctx->pending == 0 && fctx->nqueries == 0 &&
6989 ISC_LIST_EMPTY(fctx->validators) && SHUTTINGDOWN(fctx)) {
6990 /*
6991 * This fctx is already shutdown; we were just
6992 * waiting for the last reference to go away.
6993 */
6994 bucket_empty = fctx_unlink(fctx);
6995 fctx_destroy(fctx);
6996 } else {
6997 /*
6998 * Initiate shutdown.
6999 */
7000 fctx_shutdown(fctx);
7001 }
7002 }
7003 return (bucket_empty);
7004 }
7005
7006 static void
resume_dslookup(isc_task_t * task,isc_event_t * event)7007 resume_dslookup(isc_task_t *task, isc_event_t *event) {
7008 dns_fetchevent_t *fevent;
7009 dns_resolver_t *res;
7010 fetchctx_t *fctx;
7011 isc_result_t result;
7012 isc_boolean_t bucket_empty;
7013 isc_boolean_t locked = ISC_FALSE;
7014 unsigned int bucketnum;
7015 dns_rdataset_t nameservers;
7016 dns_fixedname_t fixed;
7017 dns_name_t *domain;
7018
7019 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
7020 fevent = (dns_fetchevent_t *)event;
7021 fctx = event->ev_arg;
7022 REQUIRE(VALID_FCTX(fctx));
7023 res = fctx->res;
7024
7025 UNUSED(task);
7026 FCTXTRACE("resume_dslookup");
7027
7028 if (fevent->node != NULL)
7029 dns_db_detachnode(fevent->db, &fevent->node);
7030 if (fevent->db != NULL)
7031 dns_db_detach(&fevent->db);
7032
7033 dns_rdataset_init(&nameservers);
7034
7035 bucketnum = fctx->bucketnum;
7036 if (fevent->result == ISC_R_CANCELED) {
7037 dns_resolver_destroyfetch(&fctx->nsfetch);
7038 fctx_done(fctx, ISC_R_CANCELED, __LINE__);
7039 } else if (fevent->result == ISC_R_SUCCESS) {
7040
7041 FCTXTRACE("resuming DS lookup");
7042
7043 dns_resolver_destroyfetch(&fctx->nsfetch);
7044 if (dns_rdataset_isassociated(&fctx->nameservers))
7045 dns_rdataset_disassociate(&fctx->nameservers);
7046 dns_rdataset_clone(fevent->rdataset, &fctx->nameservers);
7047 fctx->ns_ttl = fctx->nameservers.ttl;
7048 fctx->ns_ttl_ok = ISC_TRUE;
7049 log_ns_ttl(fctx, "resume_dslookup");
7050
7051 #ifdef ENABLE_FETCHLIMIT
7052 fcount_decr(fctx);
7053 #endif /* ENABLE_FETCHLIMIT */
7054
7055 dns_name_free(&fctx->domain, fctx->mctx);
7056 dns_name_init(&fctx->domain, NULL);
7057 result = dns_name_dup(&fctx->nsname, fctx->mctx, &fctx->domain);
7058 if (result != ISC_R_SUCCESS) {
7059 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
7060 goto cleanup;
7061 }
7062
7063 #ifdef ENABLE_FETCHLIMIT
7064 result = fcount_incr(fctx, ISC_TRUE);
7065 if (result != ISC_R_SUCCESS) {
7066 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
7067 goto cleanup;
7068 }
7069 #endif /* ENABLE_FETCHLIMIT */
7070
7071 /*
7072 * Try again.
7073 */
7074 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
7075 } else {
7076 unsigned int n;
7077 dns_rdataset_t *nsrdataset = NULL;
7078
7079 /*
7080 * Retrieve state from fctx->nsfetch before we destroy it.
7081 */
7082 dns_fixedname_init(&fixed);
7083 domain = dns_fixedname_name(&fixed);
7084 dns_name_copy(&fctx->nsfetch->private->domain, domain, NULL);
7085 if (dns_name_equal(&fctx->nsname, domain)) {
7086 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
7087 dns_resolver_destroyfetch(&fctx->nsfetch);
7088 goto cleanup;
7089 }
7090 if (dns_rdataset_isassociated(
7091 &fctx->nsfetch->private->nameservers)) {
7092 dns_rdataset_clone(
7093 &fctx->nsfetch->private->nameservers,
7094 &nameservers);
7095 nsrdataset = &nameservers;
7096 } else
7097 domain = NULL;
7098 dns_resolver_destroyfetch(&fctx->nsfetch);
7099 n = dns_name_countlabels(&fctx->nsname);
7100 dns_name_getlabelsequence(&fctx->nsname, 1, n - 1,
7101 &fctx->nsname);
7102
7103 if (dns_rdataset_isassociated(fevent->rdataset))
7104 dns_rdataset_disassociate(fevent->rdataset);
7105 FCTXTRACE("continuing to look for parent's NS records");
7106 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
7107 dns_rdatatype_ns, domain,
7108 nsrdataset, NULL, 0, task,
7109 resume_dslookup, fctx,
7110 &fctx->nsrrset, NULL,
7111 &fctx->nsfetch);
7112 if (result != ISC_R_SUCCESS)
7113 fctx_done(fctx, result, __LINE__);
7114 else {
7115 LOCK(&res->buckets[bucketnum].lock);
7116 locked = ISC_TRUE;
7117 fctx->references++;
7118 }
7119 }
7120
7121 cleanup:
7122 if (dns_rdataset_isassociated(&nameservers))
7123 dns_rdataset_disassociate(&nameservers);
7124 if (dns_rdataset_isassociated(fevent->rdataset))
7125 dns_rdataset_disassociate(fevent->rdataset);
7126 INSIST(fevent->sigrdataset == NULL);
7127 isc_event_free(&event);
7128 if (!locked)
7129 LOCK(&res->buckets[bucketnum].lock);
7130 bucket_empty = fctx_decreference(fctx);
7131 UNLOCK(&res->buckets[bucketnum].lock);
7132 if (bucket_empty)
7133 empty_bucket(res);
7134 }
7135
7136 static inline void
checknamessection(dns_message_t * message,dns_section_t section)7137 checknamessection(dns_message_t *message, dns_section_t section) {
7138 isc_result_t result;
7139 dns_name_t *name;
7140 dns_rdata_t rdata = DNS_RDATA_INIT;
7141 dns_rdataset_t *rdataset;
7142
7143 for (result = dns_message_firstname(message, section);
7144 result == ISC_R_SUCCESS;
7145 result = dns_message_nextname(message, section))
7146 {
7147 name = NULL;
7148 dns_message_currentname(message, section, &name);
7149 for (rdataset = ISC_LIST_HEAD(name->list);
7150 rdataset != NULL;
7151 rdataset = ISC_LIST_NEXT(rdataset, link)) {
7152 for (result = dns_rdataset_first(rdataset);
7153 result == ISC_R_SUCCESS;
7154 result = dns_rdataset_next(rdataset)) {
7155 dns_rdataset_current(rdataset, &rdata);
7156 if (!dns_rdata_checkowner(name, rdata.rdclass,
7157 rdata.type,
7158 ISC_FALSE) ||
7159 !dns_rdata_checknames(&rdata, name, NULL))
7160 {
7161 rdataset->attributes |=
7162 DNS_RDATASETATTR_CHECKNAMES;
7163 }
7164 dns_rdata_reset(&rdata);
7165 }
7166 }
7167 }
7168 }
7169
7170 static void
checknames(dns_message_t * message)7171 checknames(dns_message_t *message) {
7172
7173 checknamessection(message, DNS_SECTION_ANSWER);
7174 checknamessection(message, DNS_SECTION_AUTHORITY);
7175 checknamessection(message, DNS_SECTION_ADDITIONAL);
7176 }
7177
7178 /*
7179 * Log server NSID at log level 'level'
7180 */
7181 static void
log_nsid(isc_buffer_t * opt,size_t nsid_len,resquery_t * query,int level,isc_mem_t * mctx)7182 log_nsid(isc_buffer_t *opt, size_t nsid_len, resquery_t *query,
7183 int level, isc_mem_t *mctx)
7184 {
7185 static const char hex[17] = "0123456789abcdef";
7186 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
7187 isc_uint16_t buflen, i;
7188 unsigned char *p, *buf, *nsid;
7189
7190 /* Allocate buffer for storing hex version of the NSID */
7191 buflen = (isc_uint16_t)nsid_len * 2 + 1;
7192 buf = isc_mem_get(mctx, buflen);
7193 if (buf == NULL)
7194 return;
7195
7196 /* Convert to hex */
7197 p = buf;
7198 nsid = isc_buffer_current(opt);
7199 for (i = 0; i < nsid_len; i++) {
7200 *p++ = hex[(nsid[0] >> 4) & 0xf];
7201 *p++ = hex[nsid[0] & 0xf];
7202 nsid++;
7203 }
7204 *p = '\0';
7205
7206 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
7207 sizeof(addrbuf));
7208 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
7209 DNS_LOGMODULE_RESOLVER, level,
7210 "received NSID '%s' from %s", buf, addrbuf);
7211
7212 /* Clean up */
7213 isc_mem_put(mctx, buf, buflen);
7214 return;
7215 }
7216
7217 static void
log_packet(dns_message_t * message,int level,isc_mem_t * mctx)7218 log_packet(dns_message_t *message, int level, isc_mem_t *mctx) {
7219 isc_buffer_t buffer;
7220 char *buf = NULL;
7221 int len = 1024;
7222 isc_result_t result;
7223
7224 if (! isc_log_wouldlog(dns_lctx, level))
7225 return;
7226
7227 /*
7228 * Note that these are multiline debug messages. We want a newline
7229 * to appear in the log after each message.
7230 */
7231
7232 do {
7233 buf = isc_mem_get(mctx, len);
7234 if (buf == NULL)
7235 break;
7236 isc_buffer_init(&buffer, buf, len);
7237 result = dns_message_totext(message, &dns_master_style_debug,
7238 0, &buffer);
7239 if (result == ISC_R_NOSPACE) {
7240 isc_mem_put(mctx, buf, len);
7241 len += 1024;
7242 } else if (result == ISC_R_SUCCESS)
7243 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
7244 DNS_LOGMODULE_RESOLVER, level,
7245 "received packet:\n%.*s",
7246 (int)isc_buffer_usedlength(&buffer),
7247 buf);
7248 } while (result == ISC_R_NOSPACE);
7249
7250 if (buf != NULL)
7251 isc_mem_put(mctx, buf, len);
7252 }
7253
7254 static isc_boolean_t
iscname(fetchctx_t * fctx)7255 iscname(fetchctx_t *fctx) {
7256 isc_result_t result;
7257
7258 result = dns_message_findname(fctx->rmessage, DNS_SECTION_ANSWER,
7259 &fctx->name, dns_rdatatype_cname, 0,
7260 NULL, NULL);
7261 return (result == ISC_R_SUCCESS ? ISC_TRUE : ISC_FALSE);
7262 }
7263
7264 static isc_boolean_t
betterreferral(fetchctx_t * fctx)7265 betterreferral(fetchctx_t *fctx) {
7266 isc_result_t result;
7267 dns_name_t *name;
7268 dns_rdataset_t *rdataset;
7269 dns_message_t *message = fctx->rmessage;
7270
7271 for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
7272 result == ISC_R_SUCCESS;
7273 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY)) {
7274 name = NULL;
7275 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
7276 if (!isstrictsubdomain(name, &fctx->domain))
7277 continue;
7278 for (rdataset = ISC_LIST_HEAD(name->list);
7279 rdataset != NULL;
7280 rdataset = ISC_LIST_NEXT(rdataset, link))
7281 if (rdataset->type == dns_rdatatype_ns)
7282 return (ISC_TRUE);
7283 }
7284 return (ISC_FALSE);
7285 }
7286
7287 static void
process_opt(resquery_t * query,dns_rdataset_t * opt)7288 process_opt(resquery_t *query, dns_rdataset_t *opt) {
7289 dns_rdata_t rdata;
7290 isc_buffer_t optbuf;
7291 isc_result_t result;
7292 isc_uint16_t optcode;
7293 isc_uint16_t optlen;
7294
7295 result = dns_rdataset_first(opt);
7296 if (result == ISC_R_SUCCESS) {
7297 dns_rdata_init(&rdata);
7298 dns_rdataset_current(opt, &rdata);
7299 isc_buffer_init(&optbuf, rdata.data, rdata.length);
7300 isc_buffer_add(&optbuf, rdata.length);
7301 while (isc_buffer_remaininglength(&optbuf) >= 4) {
7302 optcode = isc_buffer_getuint16(&optbuf);
7303 optlen = isc_buffer_getuint16(&optbuf);
7304 INSIST(optlen <= isc_buffer_remaininglength(&optbuf));
7305 switch (optcode) {
7306 case DNS_OPT_NSID:
7307 if (query->options & DNS_FETCHOPT_WANTNSID)
7308 log_nsid(&optbuf, optlen, query,
7309 ISC_LOG_INFO,
7310 query->fctx->res->mctx);
7311 isc_buffer_forward(&optbuf, optlen);
7312 break;
7313 default:
7314 isc_buffer_forward(&optbuf, optlen);
7315 break;
7316 }
7317 }
7318 INSIST(isc_buffer_remaininglength(&optbuf) == 0U);
7319 }
7320 }
7321
7322 static void
resquery_response(isc_task_t * task,isc_event_t * event)7323 resquery_response(isc_task_t *task, isc_event_t *event) {
7324 isc_result_t result = ISC_R_SUCCESS;
7325 resquery_t *query = event->ev_arg;
7326 dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
7327 isc_boolean_t keep_trying, get_nameservers, resend;
7328 isc_boolean_t truncated;
7329 dns_message_t *message;
7330 dns_rdataset_t *opt;
7331 fetchctx_t *fctx;
7332 dns_name_t *fname;
7333 dns_fixedname_t foundname;
7334 isc_stdtime_t now;
7335 isc_time_t tnow, *finish;
7336 dns_adbaddrinfo_t *addrinfo;
7337 unsigned int options;
7338 unsigned int findoptions;
7339 isc_result_t broken_server;
7340 badnstype_t broken_type = badns_response;
7341 isc_boolean_t no_response;
7342 unsigned int bucketnum;
7343 dns_resolver_t *res;
7344 isc_boolean_t bucket_empty;
7345
7346 REQUIRE(VALID_QUERY(query));
7347 fctx = query->fctx;
7348 options = query->options;
7349 REQUIRE(VALID_FCTX(fctx));
7350 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
7351
7352 QTRACE("response");
7353
7354 res = fctx->res;
7355 if (isc_sockaddr_pf(&query->addrinfo->sockaddr) == PF_INET)
7356 inc_stats(res, dns_resstatscounter_responsev4);
7357 else
7358 inc_stats(res, dns_resstatscounter_responsev6);
7359
7360 (void)isc_timer_touch(fctx->timer);
7361
7362 keep_trying = ISC_FALSE;
7363 broken_server = ISC_R_SUCCESS;
7364 get_nameservers = ISC_FALSE;
7365 resend = ISC_FALSE;
7366 truncated = ISC_FALSE;
7367 finish = NULL;
7368 no_response = ISC_FALSE;
7369
7370 if (res->exiting) {
7371 result = ISC_R_SHUTTINGDOWN;
7372 FCTXTRACE("resolver shutting down");
7373 goto done;
7374 }
7375
7376 fctx->timeouts = 0;
7377 fctx->timeout = ISC_FALSE;
7378 fctx->addrinfo = query->addrinfo;
7379
7380 /*
7381 * XXXRTH We should really get the current time just once. We
7382 * need a routine to convert from an isc_time_t to an
7383 * isc_stdtime_t.
7384 */
7385 TIME_NOW(&tnow);
7386 finish = &tnow;
7387 isc_stdtime_get(&now);
7388
7389 /*
7390 * Did the dispatcher have a problem?
7391 */
7392 if (devent->result != ISC_R_SUCCESS) {
7393 if (devent->result == ISC_R_EOF &&
7394 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
7395 /*
7396 * The problem might be that they
7397 * don't understand EDNS0. Turn it
7398 * off and try again.
7399 */
7400 options |= DNS_FETCHOPT_NOEDNS0;
7401 resend = ISC_TRUE;
7402 add_bad_edns(fctx, &query->addrinfo->sockaddr);
7403 } else {
7404 /*
7405 * There's no hope for this query.
7406 */
7407 keep_trying = ISC_TRUE;
7408
7409 /*
7410 * If this is a network error on an exclusive query
7411 * socket, mark the server as bad so that we won't try
7412 * it for this fetch again. Also adjust finish and
7413 * no_response so that we penalize this address in SRTT
7414 * adjustment later.
7415 */
7416 if (query->exclusivesocket &&
7417 (devent->result == ISC_R_HOSTUNREACH ||
7418 devent->result == ISC_R_NETUNREACH ||
7419 devent->result == ISC_R_CONNREFUSED ||
7420 devent->result == ISC_R_CANCELED)) {
7421 broken_server = devent->result;
7422 broken_type = badns_unreachable;
7423 finish = NULL;
7424 no_response = ISC_TRUE;
7425 }
7426 }
7427 FCTXTRACE3("dispatcher failure", devent->result);
7428 goto done;
7429 }
7430
7431 message = fctx->rmessage;
7432
7433 if (query->tsig != NULL) {
7434 result = dns_message_setquerytsig(message, query->tsig);
7435 if (result != ISC_R_SUCCESS) {
7436 FCTXTRACE3("unable to set query tsig", result);
7437 goto done;
7438 }
7439 }
7440
7441 if (query->tsigkey) {
7442 result = dns_message_settsigkey(message, query->tsigkey);
7443 if (result != ISC_R_SUCCESS) {
7444 FCTXTRACE3("unable to set tsig key", result);
7445 goto done;
7446 }
7447 }
7448
7449 dns_message_setclass(message, res->rdclass);
7450
7451 if ((options & DNS_FETCHOPT_TCP) == 0)
7452 dns_adb_plainresponse(fctx->adb, query->addrinfo);
7453
7454 result = dns_message_parse(message, &devent->buffer, 0);
7455 if (result != ISC_R_SUCCESS) {
7456 FCTXTRACE3("message failed to parse", result);
7457 switch (result) {
7458 case ISC_R_UNEXPECTEDEND:
7459 if (!message->question_ok ||
7460 (message->flags & DNS_MESSAGEFLAG_TC) == 0 ||
7461 (options & DNS_FETCHOPT_TCP) != 0) {
7462 /*
7463 * Either the message ended prematurely,
7464 * and/or wasn't marked as being truncated,
7465 * and/or this is a response to a query we
7466 * sent over TCP. In all of these cases,
7467 * something is wrong with the remote
7468 * server and we don't want to retry using
7469 * TCP.
7470 */
7471 if ((query->options & DNS_FETCHOPT_NOEDNS0)
7472 == 0) {
7473 /*
7474 * The problem might be that they
7475 * don't understand EDNS0. Turn it
7476 * off and try again.
7477 */
7478 options |= DNS_FETCHOPT_NOEDNS0;
7479 resend = ISC_TRUE;
7480 add_bad_edns(fctx,
7481 &query->addrinfo->sockaddr);
7482 inc_stats(res,
7483 dns_resstatscounter_edns0fail);
7484 } else {
7485 broken_server = result;
7486 keep_trying = ISC_TRUE;
7487 }
7488 goto done;
7489 }
7490 /*
7491 * We defer retrying via TCP for a bit so we can
7492 * check out this message further.
7493 */
7494 truncated = ISC_TRUE;
7495 break;
7496 case DNS_R_FORMERR:
7497 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
7498 /*
7499 * The problem might be that they
7500 * don't understand EDNS0. Turn it
7501 * off and try again.
7502 */
7503 options |= DNS_FETCHOPT_NOEDNS0;
7504 resend = ISC_TRUE;
7505 add_bad_edns(fctx, &query->addrinfo->sockaddr);
7506 inc_stats(res, dns_resstatscounter_edns0fail);
7507 } else {
7508 broken_server = DNS_R_UNEXPECTEDRCODE;
7509 keep_trying = ISC_TRUE;
7510 }
7511 goto done;
7512 default:
7513 /*
7514 * Something bad has happened.
7515 */
7516 goto done;
7517 }
7518 }
7519
7520
7521 /*
7522 * Log the incoming packet.
7523 */
7524 log_packet(message, ISC_LOG_DEBUG(10), res->mctx);
7525
7526 if (message->rdclass != res->rdclass) {
7527 resend = ISC_TRUE;
7528 FCTXTRACE("bad class");
7529 goto done;
7530 }
7531
7532 /*
7533 * Process receive opt record.
7534 */
7535 opt = dns_message_getopt(message);
7536 if (opt != NULL)
7537 process_opt(query, opt);
7538
7539 /*
7540 * If the message is signed, check the signature. If not, this
7541 * returns success anyway.
7542 */
7543 result = dns_message_checksig(message, res->view);
7544 if (result != ISC_R_SUCCESS) {
7545 FCTXTRACE3("signature check failed", result);
7546 goto done;
7547 }
7548
7549 /*
7550 * The dispatcher should ensure we only get responses with QR set.
7551 */
7552 INSIST((message->flags & DNS_MESSAGEFLAG_QR) != 0);
7553 /*
7554 * INSIST() that the message comes from the place we sent it to,
7555 * since the dispatch code should ensure this.
7556 *
7557 * INSIST() that the message id is correct (this should also be
7558 * ensured by the dispatch code).
7559 */
7560
7561 /*
7562 * We have an affirmative response to the query and we have
7563 * previously got a response from this server which indicated
7564 * EDNS may not be supported so we can now cache the lack of
7565 * EDNS support.
7566 */
7567 if (opt == NULL && !EDNSOK(query->addrinfo) &&
7568 (message->rcode == dns_rcode_noerror ||
7569 message->rcode == dns_rcode_nxdomain ||
7570 message->rcode == dns_rcode_refused ||
7571 message->rcode == dns_rcode_yxdomain) &&
7572 bad_edns(fctx, &query->addrinfo->sockaddr)) {
7573 dns_adb_changeflags(fctx->adb, query->addrinfo,
7574 DNS_FETCHOPT_NOEDNS0,
7575 DNS_FETCHOPT_NOEDNS0);
7576 }
7577
7578 /*
7579 * If we get a non error EDNS response record the fact so we
7580 * won't fallback to plain DNS in the future for this server.
7581 */
7582 if (opt != NULL && !EDNSOK(query->addrinfo) &&
7583 (query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
7584 (message->rcode == dns_rcode_noerror ||
7585 message->rcode == dns_rcode_nxdomain ||
7586 message->rcode == dns_rcode_refused ||
7587 message->rcode == dns_rcode_yxdomain)) {
7588 dns_adb_changeflags(fctx->adb, query->addrinfo,
7589 FCTX_ADDRINFO_EDNSOK,
7590 FCTX_ADDRINFO_EDNSOK);
7591 }
7592
7593 /*
7594 * Deal with truncated responses by retrying using TCP.
7595 */
7596 if ((message->flags & DNS_MESSAGEFLAG_TC) != 0)
7597 truncated = ISC_TRUE;
7598
7599 if (truncated) {
7600 inc_stats(res, dns_resstatscounter_truncated);
7601 if ((options & DNS_FETCHOPT_TCP) != 0) {
7602 broken_server = DNS_R_TRUNCATEDTCP;
7603 keep_trying = ISC_TRUE;
7604 } else {
7605 options |= DNS_FETCHOPT_TCP;
7606 resend = ISC_TRUE;
7607 }
7608 FCTXTRACE3("message truncated", result);
7609 goto done;
7610 }
7611
7612 /*
7613 * Is it a query response?
7614 */
7615 if (message->opcode != dns_opcode_query) {
7616 /* XXXRTH Log */
7617 broken_server = DNS_R_UNEXPECTEDOPCODE;
7618 keep_trying = ISC_TRUE;
7619 FCTXTRACE("invalid message opcode");
7620 goto done;
7621 }
7622
7623 /*
7624 * Update statistics about erroneous responses.
7625 */
7626 if (message->rcode != dns_rcode_noerror) {
7627 switch (message->rcode) {
7628 case dns_rcode_nxdomain:
7629 inc_stats(res, dns_resstatscounter_nxdomain);
7630 break;
7631 case dns_rcode_servfail:
7632 inc_stats(res, dns_resstatscounter_servfail);
7633 break;
7634 case dns_rcode_formerr:
7635 inc_stats(res, dns_resstatscounter_formerr);
7636 break;
7637 default:
7638 inc_stats(res, dns_resstatscounter_othererror);
7639 break;
7640 }
7641 }
7642
7643 /*
7644 * Is the remote server broken, or does it dislike us?
7645 */
7646 if (message->rcode != dns_rcode_noerror &&
7647 message->rcode != dns_rcode_nxdomain) {
7648 isc_buffer_t b;
7649 char code[64];
7650 if (((message->rcode == dns_rcode_formerr ||
7651 message->rcode == dns_rcode_notimp) ||
7652 (message->rcode == dns_rcode_servfail &&
7653 dns_message_getopt(message) == NULL)) &&
7654 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
7655 /*
7656 * It's very likely they don't like EDNS0.
7657 * If the response code is SERVFAIL, also check if the
7658 * response contains an OPT RR and don't cache the
7659 * failure since it can be returned for various other
7660 * reasons.
7661 *
7662 * XXXRTH We should check if the question
7663 * we're asking requires EDNS0, and
7664 * if so, we should bail out.
7665 */
7666 options |= DNS_FETCHOPT_NOEDNS0;
7667 resend = ISC_TRUE;
7668 /*
7669 * Remember that they may not like EDNS0.
7670 */
7671 add_bad_edns(fctx, &query->addrinfo->sockaddr);
7672 inc_stats(res, dns_resstatscounter_edns0fail);
7673 } else if (message->rcode == dns_rcode_formerr) {
7674 if (ISFORWARDER(query->addrinfo)) {
7675 /*
7676 * This forwarder doesn't understand us,
7677 * but other forwarders might. Keep trying.
7678 */
7679 broken_server = DNS_R_REMOTEFORMERR;
7680 keep_trying = ISC_TRUE;
7681 } else {
7682 /*
7683 * The server doesn't understand us. Since
7684 * all servers for a zone need similar
7685 * capabilities, we assume that we will get
7686 * FORMERR from all servers, and thus we
7687 * cannot make any more progress with this
7688 * fetch.
7689 */
7690 log_formerr(fctx, "server sent FORMERR");
7691 result = DNS_R_FORMERR;
7692 }
7693 } else if (message->rcode == dns_rcode_yxdomain) {
7694 /*
7695 * DNAME mapping failed because the new name
7696 * was too long. There's no chance of success
7697 * for this fetch.
7698 */
7699 result = DNS_R_YXDOMAIN;
7700 } else if (message->rcode == dns_rcode_badvers) {
7701 /*
7702 * This should be impossible as we only send EDNS
7703 * version 0 requests and to return BADVERS you
7704 * need to support EDNS as it is a extended rcode.
7705 */
7706 broken_server = DNS_R_BADVERS;
7707 keep_trying = ISC_TRUE;
7708 } else {
7709 /*
7710 * XXXRTH log.
7711 */
7712 broken_server = DNS_R_UNEXPECTEDRCODE;
7713 INSIST(broken_server != ISC_R_SUCCESS);
7714 keep_trying = ISC_TRUE;
7715 }
7716
7717 isc_buffer_init(&b, code, sizeof(code) - 1);
7718 dns_rcode_totext(fctx->rmessage->rcode, &b);
7719 code[isc_buffer_usedlength(&b)] = '\0';
7720 FCTXTRACE2("remote server broken: returned ", code);
7721 goto done;
7722 }
7723
7724 /*
7725 * Is the question the same as the one we asked?
7726 */
7727 result = same_question(fctx);
7728 if (result != ISC_R_SUCCESS) {
7729 /* XXXRTH Log */
7730 if (result == DNS_R_FORMERR)
7731 keep_trying = ISC_TRUE;
7732 FCTXTRACE3("response did not match question", result);
7733 goto done;
7734 }
7735
7736 /*
7737 * Is the server lame?
7738 */
7739 if (res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
7740 is_lame(fctx)) {
7741 inc_stats(res, dns_resstatscounter_lame);
7742 log_lame(fctx, query->addrinfo);
7743 result = dns_adb_marklame(fctx->adb, query->addrinfo,
7744 &fctx->name, fctx->type,
7745 now + res->lame_ttl);
7746 if (result != ISC_R_SUCCESS)
7747 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
7748 DNS_LOGMODULE_RESOLVER, ISC_LOG_ERROR,
7749 "could not mark server as lame: %s",
7750 isc_result_totext(result));
7751 broken_server = DNS_R_LAME;
7752 keep_trying = ISC_TRUE;
7753 FCTXTRACE("lame server");
7754 goto done;
7755 }
7756
7757 /*
7758 * Enforce delegations only zones like NET and COM.
7759 */
7760 if (!ISFORWARDER(query->addrinfo) &&
7761 dns_view_isdelegationonly(res->view, &fctx->domain) &&
7762 !dns_name_equal(&fctx->domain, &fctx->name) &&
7763 fix_mustbedelegationornxdomain(message, fctx)) {
7764 char namebuf[DNS_NAME_FORMATSIZE];
7765 char domainbuf[DNS_NAME_FORMATSIZE];
7766 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
7767 char classbuf[64];
7768 char typebuf[64];
7769
7770 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
7771 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
7772 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
7773 dns_rdataclass_format(res->rdclass, classbuf,
7774 sizeof(classbuf));
7775 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
7776 sizeof(addrbuf));
7777
7778 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DELEGATION_ONLY,
7779 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
7780 "enforced delegation-only for '%s' (%s/%s/%s) "
7781 "from %s",
7782 domainbuf, namebuf, typebuf, classbuf, addrbuf);
7783 }
7784
7785 if ((res->options & DNS_RESOLVER_CHECKNAMES) != 0)
7786 checknames(message);
7787
7788 /*
7789 * Clear cache bits.
7790 */
7791 fctx->attributes &= ~(FCTX_ATTR_WANTNCACHE | FCTX_ATTR_WANTCACHE);
7792
7793 /*
7794 * Did we get any answers?
7795 */
7796 if (message->counts[DNS_SECTION_ANSWER] > 0 &&
7797 (message->rcode == dns_rcode_noerror ||
7798 message->rcode == dns_rcode_nxdomain)) {
7799 /*
7800 * [normal case]
7801 * We've got answers. If it has an authoritative answer or an
7802 * answer from a forwarder, we're done.
7803 */
7804 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 ||
7805 ISFORWARDER(query->addrinfo))
7806 {
7807 result = answer_response(fctx);
7808 if (result != ISC_R_SUCCESS)
7809 FCTXTRACE3("answer_response (AA/fwd)", result);
7810 } else if (iscname(fctx) &&
7811 fctx->type != dns_rdatatype_any &&
7812 fctx->type != dns_rdatatype_cname)
7813 {
7814 /*
7815 * A BIND8 server could return a non-authoritative
7816 * answer when a CNAME is followed. We should treat
7817 * it as a valid answer.
7818 */
7819 result = answer_response(fctx);
7820 if (result != ISC_R_SUCCESS)
7821 FCTXTRACE3("answer_response (!ANY/!CNAME)",
7822 result);
7823 } else if (fctx->type != dns_rdatatype_ns &&
7824 !betterreferral(fctx)) {
7825 /*
7826 * Lame response !!!.
7827 */
7828 result = answer_response(fctx);
7829 if (result != ISC_R_SUCCESS)
7830 FCTXTRACE3("answer_response (!NS)", result);
7831 } else {
7832 if (fctx->type == dns_rdatatype_ns) {
7833 /*
7834 * A BIND 8 server could incorrectly return a
7835 * non-authoritative answer to an NS query
7836 * instead of a referral. Since this answer
7837 * lacks the SIGs necessary to do DNSSEC
7838 * validation, we must invoke the following
7839 * special kludge to treat it as a referral.
7840 */
7841 result = noanswer_response(fctx, NULL,
7842 LOOK_FOR_NS_IN_ANSWER);
7843 if (result != ISC_R_SUCCESS)
7844 FCTXTRACE3("noanswer_response (NS)",
7845 result);
7846 } else {
7847 /*
7848 * Some other servers may still somehow include
7849 * an answer when it should return a referral
7850 * with an empty answer. Check to see if we can
7851 * treat this as a referral by ignoring the
7852 * answer. Further more, there may be an
7853 * implementation that moves A/AAAA glue records
7854 * to the answer section for that type of
7855 * delegation when the query is for that glue
7856 * record. LOOK_FOR_GLUE_IN_ANSWER will handle
7857 * such a corner case.
7858 */
7859 result = noanswer_response(fctx, NULL,
7860 LOOK_FOR_GLUE_IN_ANSWER);
7861 if (result != ISC_R_SUCCESS)
7862 FCTXTRACE3("noanswer_response", result);
7863 }
7864 if (result != DNS_R_DELEGATION) {
7865 /*
7866 * At this point, AA is not set, the response
7867 * is not a referral, and the server is not a
7868 * forwarder. It is technically lame and it's
7869 * easier to treat it as such than to figure out
7870 * some more elaborate course of action.
7871 */
7872 broken_server = DNS_R_LAME;
7873 keep_trying = ISC_TRUE;
7874 goto done;
7875 }
7876 goto force_referral;
7877 }
7878 if (result != ISC_R_SUCCESS) {
7879 if (result == DNS_R_FORMERR)
7880 keep_trying = ISC_TRUE;
7881 goto done;
7882 }
7883 } else if (message->counts[DNS_SECTION_AUTHORITY] > 0 ||
7884 message->rcode == dns_rcode_noerror ||
7885 message->rcode == dns_rcode_nxdomain) {
7886 /*
7887 * NXDOMAIN, NXRDATASET, or referral.
7888 */
7889 result = noanswer_response(fctx, NULL, 0);
7890 switch (result) {
7891 case ISC_R_SUCCESS:
7892 case DNS_R_CHASEDSSERVERS:
7893 break;
7894 case DNS_R_DELEGATION:
7895 force_referral:
7896 /*
7897 * We don't have the answer, but we know a better
7898 * place to look.
7899 */
7900 get_nameservers = ISC_TRUE;
7901 keep_trying = ISC_TRUE;
7902 /*
7903 * We have a new set of name servers, and it
7904 * has not experienced any restarts yet.
7905 */
7906 fctx->restarts = 0;
7907
7908 /*
7909 * Update local statistics counters collected for each
7910 * new zone.
7911 */
7912 fctx->referrals++;
7913 fctx->querysent = 0;
7914 fctx->lamecount = 0;
7915 fctx->quotacount = 0;
7916 fctx->neterr = 0;
7917 fctx->badresp = 0;
7918 fctx->adberr = 0;
7919
7920 result = ISC_R_SUCCESS;
7921 break;
7922 default:
7923 /*
7924 * Something has gone wrong.
7925 */
7926 if (result == DNS_R_FORMERR)
7927 keep_trying = ISC_TRUE;
7928 FCTXTRACE3("noanswer_response", result);
7929 goto done;
7930 }
7931 } else {
7932 /*
7933 * The server is insane.
7934 */
7935 /* XXXRTH Log */
7936 broken_server = DNS_R_UNEXPECTEDRCODE;
7937 keep_trying = ISC_TRUE;
7938 FCTXTRACE("broken server: unexpected rcode");
7939 goto done;
7940 }
7941
7942 /*
7943 * Follow additional section data chains.
7944 */
7945 chase_additional(fctx);
7946
7947 /*
7948 * Cache the cacheable parts of the message. This may also cause
7949 * work to be queued to the DNSSEC validator.
7950 */
7951 if (WANTCACHE(fctx)) {
7952 result = cache_message(fctx, query->addrinfo, now);
7953 if (result != ISC_R_SUCCESS) {
7954 FCTXTRACE3("cache_message complete", result);
7955 goto done;
7956 }
7957 }
7958
7959 /*
7960 * Ncache the negatively cacheable parts of the message. This may
7961 * also cause work to be queued to the DNSSEC validator.
7962 */
7963 if (WANTNCACHE(fctx)) {
7964 dns_rdatatype_t covers;
7965
7966 /*
7967 * Cache DS NXDOMAIN seperately to other types.
7968 */
7969 if (message->rcode == dns_rcode_nxdomain &&
7970 fctx->type != dns_rdatatype_ds)
7971 covers = dns_rdatatype_any;
7972 else
7973 covers = fctx->type;
7974
7975 /*
7976 * Cache any negative cache entries in the message.
7977 */
7978 result = ncache_message(fctx, query->addrinfo, covers, now);
7979 if (result != ISC_R_SUCCESS)
7980 FCTXTRACE3("ncache_message complete", result);
7981 }
7982
7983 done:
7984 /*
7985 * Remember the query's addrinfo, in case we need to mark the
7986 * server as broken.
7987 */
7988 addrinfo = query->addrinfo;
7989
7990 FCTXTRACE4("query canceled in response(); ",
7991 no_response ? "no response" : "responding",
7992 result);
7993
7994 /*
7995 * Cancel the query.
7996 *
7997 * XXXRTH Don't cancel the query if waiting for validation?
7998 */
7999 fctx_cancelquery(&query, &devent, finish, no_response, ISC_FALSE);
8000
8001 if (keep_trying) {
8002 if (result == DNS_R_FORMERR)
8003 broken_server = DNS_R_FORMERR;
8004 if (broken_server != ISC_R_SUCCESS) {
8005 /*
8006 * Add this server to the list of bad servers for
8007 * this fctx.
8008 */
8009 add_bad(fctx, addrinfo, broken_server, broken_type);
8010 }
8011
8012 if (get_nameservers) {
8013 dns_name_t *name;
8014 dns_fixedname_init(&foundname);
8015 fname = dns_fixedname_name(&foundname);
8016 if (result != ISC_R_SUCCESS) {
8017 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
8018 return;
8019 }
8020 findoptions = 0;
8021 if (dns_rdatatype_atparent(fctx->type))
8022 findoptions |= DNS_DBFIND_NOEXACT;
8023 if ((options & DNS_FETCHOPT_UNSHARED) == 0)
8024 name = &fctx->name;
8025 else
8026 name = &fctx->domain;
8027 result = dns_view_findzonecut(res->view,
8028 name, fname,
8029 now, findoptions,
8030 ISC_TRUE,
8031 &fctx->nameservers,
8032 NULL);
8033 if (result != ISC_R_SUCCESS) {
8034 FCTXTRACE("couldn't find a zonecut");
8035 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
8036 return;
8037 }
8038 if (!dns_name_issubdomain(fname, &fctx->domain)) {
8039 /*
8040 * The best nameservers are now above our
8041 * QDOMAIN.
8042 */
8043 FCTXTRACE("nameservers now above QDOMAIN");
8044 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
8045 return;
8046 }
8047
8048 #ifdef ENABLE_FETCHLIMIT
8049 fcount_decr(fctx);
8050 #endif /* ENABLE_FETCHLIMIT */
8051
8052 dns_name_free(&fctx->domain, fctx->mctx);
8053 dns_name_init(&fctx->domain, NULL);
8054 result = dns_name_dup(fname, fctx->mctx, &fctx->domain);
8055 if (result != ISC_R_SUCCESS) {
8056 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
8057 return;
8058 }
8059
8060 #ifdef ENABLE_FETCHLIMIT
8061 result = fcount_incr(fctx, ISC_TRUE);
8062 if (result != ISC_R_SUCCESS) {
8063 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
8064 return;
8065 }
8066 #endif /* ENABLE_FETCHLIMIT */
8067
8068 fctx->ns_ttl = fctx->nameservers.ttl;
8069 fctx->ns_ttl_ok = ISC_TRUE;
8070 fctx_cancelqueries(fctx, ISC_TRUE, ISC_FALSE);
8071 fctx_cleanupfinds(fctx);
8072 fctx_cleanupaltfinds(fctx);
8073 fctx_cleanupforwaddrs(fctx);
8074 fctx_cleanupaltaddrs(fctx);
8075 }
8076 /*
8077 * Try again.
8078 */
8079 fctx_try(fctx, !get_nameservers, ISC_FALSE);
8080 } else if (resend) {
8081 /*
8082 * Resend (probably with changed options).
8083 */
8084 FCTXTRACE("resend");
8085 inc_stats(res, dns_resstatscounter_retry);
8086 bucketnum = fctx->bucketnum;
8087 fctx_increference(fctx);
8088 result = fctx_query(fctx, addrinfo, options);
8089 if (result != ISC_R_SUCCESS) {
8090 fctx_done(fctx, result, __LINE__);
8091 LOCK(&res->buckets[bucketnum].lock);
8092 bucket_empty = fctx_decreference(fctx);
8093 UNLOCK(&res->buckets[bucketnum].lock);
8094 if (bucket_empty)
8095 empty_bucket(res);
8096 }
8097 } else if (result == ISC_R_SUCCESS && !HAVE_ANSWER(fctx)) {
8098 /*
8099 * All has gone well so far, but we are waiting for the
8100 * DNSSEC validator to validate the answer.
8101 */
8102 FCTXTRACE("wait for validator");
8103 fctx_cancelqueries(fctx, ISC_TRUE, ISC_FALSE);
8104 /*
8105 * We must not retransmit while the validator is working;
8106 * it has references to the current rmessage.
8107 */
8108 result = fctx_stopidletimer(fctx);
8109 if (result != ISC_R_SUCCESS)
8110 fctx_done(fctx, result, __LINE__);
8111 } else if (result == DNS_R_CHASEDSSERVERS) {
8112 unsigned int n;
8113 add_bad(fctx, addrinfo, result, broken_type);
8114 fctx_cancelqueries(fctx, ISC_TRUE, ISC_FALSE);
8115 fctx_cleanupfinds(fctx);
8116 fctx_cleanupforwaddrs(fctx);
8117
8118 n = dns_name_countlabels(&fctx->name);
8119 dns_name_getlabelsequence(&fctx->name, 1, n - 1, &fctx->nsname);
8120
8121 FCTXTRACE("suspending DS lookup to find parent's NS records");
8122
8123 result = dns_resolver_createfetch(res, &fctx->nsname,
8124 dns_rdatatype_ns,
8125 NULL, NULL, NULL, 0, task,
8126 resume_dslookup, fctx,
8127 &fctx->nsrrset, NULL,
8128 &fctx->nsfetch);
8129 if (result != ISC_R_SUCCESS)
8130 fctx_done(fctx, result, __LINE__);
8131 else {
8132 fctx_increference(fctx);
8133 result = fctx_stopidletimer(fctx);
8134 if (result != ISC_R_SUCCESS)
8135 fctx_done(fctx, result, __LINE__);
8136 }
8137 } else {
8138 /*
8139 * We're done.
8140 */
8141 fctx_done(fctx, result, __LINE__);
8142 }
8143 }
8144
8145
8146 /***
8147 *** Resolver Methods
8148 ***/
8149 static void
destroy_badcache(dns_resolver_t * res)8150 destroy_badcache(dns_resolver_t *res) {
8151 dns_badcache_t *bad, *next;
8152 unsigned int i;
8153
8154 if (res->badcache != NULL) {
8155 for (i = 0; i < res->badhash; i++)
8156 for (bad = res->badcache[i]; bad != NULL;
8157 bad = next) {
8158 next = bad->next;
8159 isc_mem_put(res->mctx, bad, sizeof(*bad) +
8160 bad->name.length);
8161 res->badcount--;
8162 }
8163 isc_mem_put(res->mctx, res->badcache,
8164 sizeof(*res->badcache) * res->badhash);
8165 res->badcache = NULL;
8166 res->badhash = 0;
8167 INSIST(res->badcount == 0);
8168 }
8169 }
8170
8171 static void
destroy(dns_resolver_t * res)8172 destroy(dns_resolver_t *res) {
8173 unsigned int i;
8174 alternate_t *a;
8175
8176 REQUIRE(res->references == 0);
8177 REQUIRE(!res->priming);
8178 REQUIRE(res->primefetch == NULL);
8179
8180 RTRACE("destroy");
8181
8182 INSIST(res->nfctx == 0);
8183
8184 DESTROYLOCK(&res->primelock);
8185 DESTROYLOCK(&res->nlock);
8186 DESTROYLOCK(&res->lock);
8187 for (i = 0; i < res->nbuckets; i++) {
8188 INSIST(ISC_LIST_EMPTY(res->buckets[i].fctxs));
8189 isc_task_shutdown(res->buckets[i].task);
8190 isc_task_detach(&res->buckets[i].task);
8191 DESTROYLOCK(&res->buckets[i].lock);
8192 isc_mem_detach(&res->buckets[i].mctx);
8193 }
8194 isc_mem_put(res->mctx, res->buckets,
8195 res->nbuckets * sizeof(fctxbucket_t));
8196 #ifdef ENABLE_FETCHLIMIT
8197 for (i = 0; i < RES_DOMAIN_BUCKETS; i++) {
8198 INSIST(ISC_LIST_EMPTY(res->dbuckets[i].list));
8199 isc_mem_detach(&res->dbuckets[i].mctx);
8200 DESTROYLOCK(&res->dbuckets[i].lock);
8201 }
8202 isc_mem_put(res->mctx, res->dbuckets,
8203 RES_DOMAIN_BUCKETS * sizeof(zonebucket_t));
8204 #endif /* ENABLE_FETCHLIMIT */
8205 if (res->dispatches4 != NULL)
8206 dns_dispatchset_destroy(&res->dispatches4);
8207 if (res->dispatches6 != NULL)
8208 dns_dispatchset_destroy(&res->dispatches6);
8209 while ((a = ISC_LIST_HEAD(res->alternates)) != NULL) {
8210 ISC_LIST_UNLINK(res->alternates, a, link);
8211 if (!a->isaddress)
8212 dns_name_free(&a->_u._n.name, res->mctx);
8213 isc_mem_put(res->mctx, a, sizeof(*a));
8214 }
8215 dns_resolver_reset_algorithms(res);
8216 destroy_badcache(res);
8217 dns_resolver_resetmustbesecure(res);
8218 #if USE_ALGLOCK
8219 isc_rwlock_destroy(&res->alglock);
8220 #endif
8221 #if USE_MBSLOCK
8222 isc_rwlock_destroy(&res->mbslock);
8223 #endif
8224 isc_timer_detach(&res->spillattimer);
8225 res->magic = 0;
8226 isc_mem_put(res->mctx, res, sizeof(*res));
8227 }
8228
8229 static void
send_shutdown_events(dns_resolver_t * res)8230 send_shutdown_events(dns_resolver_t *res) {
8231 isc_event_t *event, *next_event;
8232 isc_task_t *etask;
8233
8234 /*
8235 * Caller must be holding the resolver lock.
8236 */
8237
8238 for (event = ISC_LIST_HEAD(res->whenshutdown);
8239 event != NULL;
8240 event = next_event) {
8241 next_event = ISC_LIST_NEXT(event, ev_link);
8242 ISC_LIST_UNLINK(res->whenshutdown, event, ev_link);
8243 etask = event->ev_sender;
8244 event->ev_sender = res;
8245 isc_task_sendanddetach(&etask, &event);
8246 }
8247 }
8248
8249 static void
empty_bucket(dns_resolver_t * res)8250 empty_bucket(dns_resolver_t *res) {
8251 RTRACE("empty_bucket");
8252
8253 LOCK(&res->lock);
8254
8255 INSIST(res->activebuckets > 0);
8256 res->activebuckets--;
8257 if (res->activebuckets == 0)
8258 send_shutdown_events(res);
8259
8260 UNLOCK(&res->lock);
8261 }
8262
8263 static void
spillattimer_countdown(isc_task_t * task,isc_event_t * event)8264 spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
8265 dns_resolver_t *res = event->ev_arg;
8266 isc_result_t result;
8267 unsigned int count;
8268 isc_boolean_t logit = ISC_FALSE;
8269
8270 REQUIRE(VALID_RESOLVER(res));
8271
8272 UNUSED(task);
8273
8274 LOCK(&res->lock);
8275 INSIST(!res->exiting);
8276 if (res->spillat > res->spillatmin) {
8277 res->spillat--;
8278 logit = ISC_TRUE;
8279 }
8280 if (res->spillat <= res->spillatmin) {
8281 result = isc_timer_reset(res->spillattimer,
8282 isc_timertype_inactive, NULL,
8283 NULL, ISC_TRUE);
8284 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8285 }
8286 count = res->spillat;
8287 UNLOCK(&res->lock);
8288 if (logit)
8289 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
8290 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
8291 "clients-per-query decreased to %u", count);
8292
8293 isc_event_free(&event);
8294 }
8295
8296 isc_result_t
dns_resolver_create(dns_view_t * view,isc_taskmgr_t * taskmgr,unsigned int ntasks,unsigned int ndisp,isc_socketmgr_t * socketmgr,isc_timermgr_t * timermgr,unsigned int options,dns_dispatchmgr_t * dispatchmgr,dns_dispatch_t * dispatchv4,dns_dispatch_t * dispatchv6,dns_resolver_t ** resp)8297 dns_resolver_create(dns_view_t *view,
8298 isc_taskmgr_t *taskmgr,
8299 unsigned int ntasks, unsigned int ndisp,
8300 isc_socketmgr_t *socketmgr,
8301 isc_timermgr_t *timermgr,
8302 unsigned int options,
8303 dns_dispatchmgr_t *dispatchmgr,
8304 dns_dispatch_t *dispatchv4,
8305 dns_dispatch_t *dispatchv6,
8306 dns_resolver_t **resp)
8307 {
8308 dns_resolver_t *res;
8309 isc_result_t result = ISC_R_SUCCESS;
8310 unsigned int i, buckets_created = 0;
8311 isc_task_t *task = NULL;
8312 char name[16];
8313 unsigned dispattr;
8314 #ifdef ENABLE_FETCHLIMIT
8315 unsigned int dbuckets_created = 0;
8316 #endif /* ENABLE_FETCHLIMIT */
8317
8318 /*
8319 * Create a resolver.
8320 */
8321
8322 REQUIRE(DNS_VIEW_VALID(view));
8323 REQUIRE(ntasks > 0);
8324 REQUIRE(ndisp > 0);
8325 REQUIRE(resp != NULL && *resp == NULL);
8326 REQUIRE(dispatchmgr != NULL);
8327 REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
8328
8329 res = isc_mem_get(view->mctx, sizeof(*res));
8330 if (res == NULL)
8331 return (ISC_R_NOMEMORY);
8332 RTRACE("create");
8333 res->mctx = view->mctx;
8334 res->rdclass = view->rdclass;
8335 res->socketmgr = socketmgr;
8336 res->timermgr = timermgr;
8337 res->taskmgr = taskmgr;
8338 res->dispatchmgr = dispatchmgr;
8339 res->view = view;
8340 res->options = options;
8341 res->lame_ttl = 0;
8342 ISC_LIST_INIT(res->alternates);
8343 res->udpsize = RECV_BUFFER_SIZE;
8344 res->algorithms = NULL;
8345 res->badcache = NULL;
8346 res->badcount = 0;
8347 res->badhash = 0;
8348 res->badsweep = 0;
8349 res->mustbesecure = NULL;
8350 res->spillatmin = res->spillat = 10;
8351 res->spillatmax = 100;
8352 res->spillattimer = NULL;
8353 res->zspill = 0;
8354 res->zero_no_soa_ttl = ISC_FALSE;
8355 res->query_timeout = DEFAULT_QUERY_TIMEOUT;
8356 res->maxdepth = DEFAULT_RECURSION_DEPTH;
8357 res->maxqueries = DEFAULT_MAX_QUERIES;
8358 res->quotaresp[dns_quotatype_zone] = DNS_R_DROP;
8359 res->quotaresp[dns_quotatype_server] = DNS_R_SERVFAIL;
8360 res->nbuckets = ntasks;
8361 res->activebuckets = ntasks;
8362 res->buckets = isc_mem_get(view->mctx,
8363 ntasks * sizeof(fctxbucket_t));
8364 if (res->buckets == NULL) {
8365 result = ISC_R_NOMEMORY;
8366 goto cleanup_res;
8367 }
8368 for (i = 0; i < ntasks; i++) {
8369 result = isc_mutex_init(&res->buckets[i].lock);
8370 if (result != ISC_R_SUCCESS)
8371 goto cleanup_buckets;
8372 res->buckets[i].task = NULL;
8373 result = isc_task_create(taskmgr, 0, &res->buckets[i].task);
8374 if (result != ISC_R_SUCCESS) {
8375 DESTROYLOCK(&res->buckets[i].lock);
8376 goto cleanup_buckets;
8377 }
8378 res->buckets[i].mctx = NULL;
8379 snprintf(name, sizeof(name), "res%u", i);
8380 #ifdef ISC_PLATFORM_USETHREADS
8381 /*
8382 * Use a separate memory context for each bucket to reduce
8383 * contention among multiple threads. Do this only when
8384 * enabling threads because it will be require more memory.
8385 */
8386 result = isc_mem_create(0, 0, &res->buckets[i].mctx);
8387 if (result != ISC_R_SUCCESS) {
8388 isc_task_detach(&res->buckets[i].task);
8389 DESTROYLOCK(&res->buckets[i].lock);
8390 goto cleanup_buckets;
8391 }
8392 isc_mem_setname(res->buckets[i].mctx, name, NULL);
8393 #else
8394 isc_mem_attach(view->mctx, &res->buckets[i].mctx);
8395 #endif
8396 isc_task_setname(res->buckets[i].task, name, res);
8397 ISC_LIST_INIT(res->buckets[i].fctxs);
8398 res->buckets[i].exiting = ISC_FALSE;
8399 buckets_created++;
8400 }
8401
8402 #ifdef ENABLE_FETCHLIMIT
8403 res->dbuckets = isc_mem_get(view->mctx,
8404 RES_DOMAIN_BUCKETS * sizeof(zonebucket_t));
8405 if (res->dbuckets == NULL) {
8406 result = ISC_R_NOMEMORY;
8407 goto cleanup_buckets;
8408 }
8409 for (i = 0; i < RES_DOMAIN_BUCKETS; i++) {
8410 ISC_LIST_INIT(res->dbuckets[i].list);
8411 res->dbuckets[i].mctx = NULL;
8412 isc_mem_attach(view->mctx, &res->dbuckets[i].mctx);
8413 result = isc_mutex_init(&res->dbuckets[i].lock);
8414 if (result != ISC_R_SUCCESS) {
8415 isc_mem_detach(&res->dbuckets[i].mctx);
8416 goto cleanup_dbuckets;
8417 }
8418 dbuckets_created++;
8419 }
8420 #endif /* ENABLE_FETCHLIMIT */
8421
8422 res->dispatches4 = NULL;
8423 if (dispatchv4 != NULL) {
8424 dns_dispatchset_create(view->mctx, socketmgr, taskmgr,
8425 dispatchv4, &res->dispatches4, ndisp);
8426 dispattr = dns_dispatch_getattributes(dispatchv4);
8427 res->exclusivev4 =
8428 ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
8429 }
8430
8431 res->dispatches6 = NULL;
8432 if (dispatchv6 != NULL) {
8433 dns_dispatchset_create(view->mctx, socketmgr, taskmgr,
8434 dispatchv6, &res->dispatches6, ndisp);
8435 dispattr = dns_dispatch_getattributes(dispatchv6);
8436 res->exclusivev6 =
8437 ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
8438 }
8439
8440 res->references = 1;
8441 res->exiting = ISC_FALSE;
8442 res->frozen = ISC_FALSE;
8443 ISC_LIST_INIT(res->whenshutdown);
8444 res->priming = ISC_FALSE;
8445 res->primefetch = NULL;
8446 res->nfctx = 0;
8447
8448 result = isc_mutex_init(&res->lock);
8449 if (result != ISC_R_SUCCESS)
8450 goto cleanup_dispatches;
8451
8452 result = isc_mutex_init(&res->nlock);
8453 if (result != ISC_R_SUCCESS)
8454 goto cleanup_lock;
8455
8456 result = isc_mutex_init(&res->primelock);
8457 if (result != ISC_R_SUCCESS)
8458 goto cleanup_nlock;
8459
8460 task = NULL;
8461 result = isc_task_create(taskmgr, 0, &task);
8462 if (result != ISC_R_SUCCESS)
8463 goto cleanup_primelock;
8464
8465 result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
8466 task, spillattimer_countdown, res,
8467 &res->spillattimer);
8468 isc_task_detach(&task);
8469 if (result != ISC_R_SUCCESS)
8470 goto cleanup_primelock;
8471
8472 #if USE_ALGLOCK
8473 result = isc_rwlock_init(&res->alglock, 0, 0);
8474 if (result != ISC_R_SUCCESS)
8475 goto cleanup_spillattimer;
8476 #endif
8477 #if USE_MBSLOCK
8478 result = isc_rwlock_init(&res->mbslock, 0, 0);
8479 if (result != ISC_R_SUCCESS)
8480 goto cleanup_alglock;
8481 #endif
8482
8483 res->magic = RES_MAGIC;
8484
8485 *resp = res;
8486
8487 return (ISC_R_SUCCESS);
8488
8489 #if USE_MBSLOCK
8490 cleanup_alglock:
8491 #if USE_ALGLOCK
8492 isc_rwlock_destroy(&res->alglock);
8493 #endif
8494 #endif
8495 #if USE_ALGLOCK || USE_MBSLOCK
8496 cleanup_spillattimer:
8497 isc_timer_detach(&res->spillattimer);
8498 #endif
8499
8500 cleanup_primelock:
8501 DESTROYLOCK(&res->primelock);
8502
8503 cleanup_nlock:
8504 DESTROYLOCK(&res->nlock);
8505
8506 cleanup_lock:
8507 DESTROYLOCK(&res->lock);
8508
8509 cleanup_dispatches:
8510 if (res->dispatches6 != NULL)
8511 dns_dispatchset_destroy(&res->dispatches6);
8512 if (res->dispatches4 != NULL)
8513 dns_dispatchset_destroy(&res->dispatches4);
8514
8515 #ifdef ENABLE_FETCHLIMIT
8516 cleanup_dbuckets:
8517 for (i = 0; i < dbuckets_created; i++) {
8518 DESTROYLOCK(&res->dbuckets[i].lock);
8519 isc_mem_detach(&res->dbuckets[i].mctx);
8520 }
8521 isc_mem_put(view->mctx, res->dbuckets,
8522 RES_DOMAIN_BUCKETS * sizeof(zonebucket_t));
8523 #endif /* ENABLE_FETCHLIMIT*/
8524
8525 cleanup_buckets:
8526 for (i = 0; i < buckets_created; i++) {
8527 isc_mem_detach(&res->buckets[i].mctx);
8528 DESTROYLOCK(&res->buckets[i].lock);
8529 isc_task_shutdown(res->buckets[i].task);
8530 isc_task_detach(&res->buckets[i].task);
8531 }
8532 isc_mem_put(view->mctx, res->buckets,
8533 res->nbuckets * sizeof(fctxbucket_t));
8534
8535 cleanup_res:
8536 isc_mem_put(view->mctx, res, sizeof(*res));
8537
8538 return (result);
8539 }
8540
8541 #ifdef BIND9
8542 static void
prime_done(isc_task_t * task,isc_event_t * event)8543 prime_done(isc_task_t *task, isc_event_t *event) {
8544 dns_resolver_t *res;
8545 dns_fetchevent_t *fevent;
8546 dns_fetch_t *fetch;
8547 dns_db_t *db = NULL;
8548
8549 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
8550 fevent = (dns_fetchevent_t *)event;
8551 res = event->ev_arg;
8552 REQUIRE(VALID_RESOLVER(res));
8553
8554 UNUSED(task);
8555
8556 LOCK(&res->lock);
8557
8558 INSIST(res->priming);
8559 res->priming = ISC_FALSE;
8560 LOCK(&res->primelock);
8561 fetch = res->primefetch;
8562 res->primefetch = NULL;
8563 UNLOCK(&res->primelock);
8564
8565 UNLOCK(&res->lock);
8566
8567 if (fevent->result == ISC_R_SUCCESS &&
8568 res->view->cache != NULL && res->view->hints != NULL) {
8569 dns_cache_attachdb(res->view->cache, &db);
8570 dns_root_checkhints(res->view, res->view->hints, db);
8571 dns_db_detach(&db);
8572 }
8573
8574 if (fevent->node != NULL)
8575 dns_db_detachnode(fevent->db, &fevent->node);
8576 if (fevent->db != NULL)
8577 dns_db_detach(&fevent->db);
8578 if (dns_rdataset_isassociated(fevent->rdataset))
8579 dns_rdataset_disassociate(fevent->rdataset);
8580 INSIST(fevent->sigrdataset == NULL);
8581
8582 isc_mem_put(res->mctx, fevent->rdataset, sizeof(*fevent->rdataset));
8583
8584 isc_event_free(&event);
8585 dns_resolver_destroyfetch(&fetch);
8586 }
8587
8588 void
dns_resolver_prime(dns_resolver_t * res)8589 dns_resolver_prime(dns_resolver_t *res) {
8590 isc_boolean_t want_priming = ISC_FALSE;
8591 dns_rdataset_t *rdataset;
8592 isc_result_t result;
8593
8594 REQUIRE(VALID_RESOLVER(res));
8595 REQUIRE(res->frozen);
8596
8597 RTRACE("dns_resolver_prime");
8598
8599 LOCK(&res->lock);
8600
8601 if (!res->exiting && !res->priming) {
8602 INSIST(res->primefetch == NULL);
8603 res->priming = ISC_TRUE;
8604 want_priming = ISC_TRUE;
8605 }
8606
8607 UNLOCK(&res->lock);
8608
8609 if (want_priming) {
8610 /*
8611 * To avoid any possible recursive locking problems, we
8612 * start the priming fetch like any other fetch, and holding
8613 * no resolver locks. No one else will try to start it
8614 * because we're the ones who set res->priming to true.
8615 * Any other callers of dns_resolver_prime() while we're
8616 * running will see that res->priming is already true and
8617 * do nothing.
8618 */
8619 RTRACE("priming");
8620 rdataset = isc_mem_get(res->mctx, sizeof(*rdataset));
8621 if (rdataset == NULL) {
8622 LOCK(&res->lock);
8623 INSIST(res->priming);
8624 INSIST(res->primefetch == NULL);
8625 res->priming = ISC_FALSE;
8626 UNLOCK(&res->lock);
8627 return;
8628 }
8629 dns_rdataset_init(rdataset);
8630 LOCK(&res->primelock);
8631 result = dns_resolver_createfetch(res, dns_rootname,
8632 dns_rdatatype_ns,
8633 NULL, NULL, NULL, 0,
8634 res->buckets[0].task,
8635 prime_done,
8636 res, rdataset, NULL,
8637 &res->primefetch);
8638 UNLOCK(&res->primelock);
8639 if (result != ISC_R_SUCCESS) {
8640 isc_mem_put(res->mctx, rdataset, sizeof(*rdataset));
8641 LOCK(&res->lock);
8642 INSIST(res->priming);
8643 res->priming = ISC_FALSE;
8644 UNLOCK(&res->lock);
8645 }
8646 }
8647 }
8648 #endif /* BIND9 */
8649
8650 void
dns_resolver_freeze(dns_resolver_t * res)8651 dns_resolver_freeze(dns_resolver_t *res) {
8652 /*
8653 * Freeze resolver.
8654 */
8655
8656 REQUIRE(VALID_RESOLVER(res));
8657
8658 res->frozen = ISC_TRUE;
8659 }
8660
8661 void
dns_resolver_attach(dns_resolver_t * source,dns_resolver_t ** targetp)8662 dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp) {
8663 REQUIRE(VALID_RESOLVER(source));
8664 REQUIRE(targetp != NULL && *targetp == NULL);
8665
8666 RRTRACE(source, "attach");
8667 LOCK(&source->lock);
8668 REQUIRE(!source->exiting);
8669
8670 INSIST(source->references > 0);
8671 source->references++;
8672 INSIST(source->references != 0);
8673 UNLOCK(&source->lock);
8674
8675 *targetp = source;
8676 }
8677
8678 void
dns_resolver_whenshutdown(dns_resolver_t * res,isc_task_t * task,isc_event_t ** eventp)8679 dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
8680 isc_event_t **eventp)
8681 {
8682 isc_task_t *clone;
8683 isc_event_t *event;
8684
8685 REQUIRE(VALID_RESOLVER(res));
8686 REQUIRE(eventp != NULL);
8687
8688 event = *eventp;
8689 *eventp = NULL;
8690
8691 LOCK(&res->lock);
8692
8693 if (res->exiting && res->activebuckets == 0) {
8694 /*
8695 * We're already shutdown. Send the event.
8696 */
8697 event->ev_sender = res;
8698 isc_task_send(task, &event);
8699 } else {
8700 clone = NULL;
8701 isc_task_attach(task, &clone);
8702 event->ev_sender = clone;
8703 ISC_LIST_APPEND(res->whenshutdown, event, ev_link);
8704 }
8705
8706 UNLOCK(&res->lock);
8707 }
8708
8709 void
dns_resolver_shutdown(dns_resolver_t * res)8710 dns_resolver_shutdown(dns_resolver_t *res) {
8711 unsigned int i;
8712 fetchctx_t *fctx;
8713 isc_result_t result;
8714
8715 REQUIRE(VALID_RESOLVER(res));
8716
8717 RTRACE("shutdown");
8718
8719 LOCK(&res->lock);
8720
8721 if (!res->exiting) {
8722 RTRACE("exiting");
8723 res->exiting = ISC_TRUE;
8724
8725 for (i = 0; i < res->nbuckets; i++) {
8726 LOCK(&res->buckets[i].lock);
8727 for (fctx = ISC_LIST_HEAD(res->buckets[i].fctxs);
8728 fctx != NULL;
8729 fctx = ISC_LIST_NEXT(fctx, link))
8730 fctx_shutdown(fctx);
8731 if (res->dispatches4 != NULL && !res->exclusivev4) {
8732 dns_dispatchset_cancelall(res->dispatches4,
8733 res->buckets[i].task);
8734 }
8735 if (res->dispatches6 != NULL && !res->exclusivev6) {
8736 dns_dispatchset_cancelall(res->dispatches6,
8737 res->buckets[i].task);
8738 }
8739 res->buckets[i].exiting = ISC_TRUE;
8740 if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) {
8741 INSIST(res->activebuckets > 0);
8742 res->activebuckets--;
8743 }
8744 UNLOCK(&res->buckets[i].lock);
8745 }
8746 if (res->activebuckets == 0)
8747 send_shutdown_events(res);
8748 result = isc_timer_reset(res->spillattimer,
8749 isc_timertype_inactive, NULL,
8750 NULL, ISC_TRUE);
8751 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8752 }
8753
8754 UNLOCK(&res->lock);
8755 }
8756
8757 void
dns_resolver_detach(dns_resolver_t ** resp)8758 dns_resolver_detach(dns_resolver_t **resp) {
8759 dns_resolver_t *res;
8760 isc_boolean_t need_destroy = ISC_FALSE;
8761
8762 REQUIRE(resp != NULL);
8763 res = *resp;
8764 REQUIRE(VALID_RESOLVER(res));
8765
8766 RTRACE("detach");
8767
8768 LOCK(&res->lock);
8769
8770 INSIST(res->references > 0);
8771 res->references--;
8772 if (res->references == 0) {
8773 INSIST(res->exiting && res->activebuckets == 0);
8774 need_destroy = ISC_TRUE;
8775 }
8776
8777 UNLOCK(&res->lock);
8778
8779 if (need_destroy)
8780 destroy(res);
8781
8782 *resp = NULL;
8783 }
8784
8785 static inline isc_boolean_t
fctx_match(fetchctx_t * fctx,dns_name_t * name,dns_rdatatype_t type,unsigned int options)8786 fctx_match(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
8787 unsigned int options)
8788 {
8789 /*
8790 * Don't match fetch contexts that are shutting down.
8791 */
8792 if (fctx->cloned || fctx->state == fetchstate_done ||
8793 ISC_LIST_EMPTY(fctx->events))
8794 return (ISC_FALSE);
8795
8796 if (fctx->type != type || fctx->options != options)
8797 return (ISC_FALSE);
8798 return (dns_name_equal(&fctx->name, name));
8799 }
8800
8801 static inline void
log_fetch(dns_name_t * name,dns_rdatatype_t type)8802 log_fetch(dns_name_t *name, dns_rdatatype_t type) {
8803 char namebuf[DNS_NAME_FORMATSIZE];
8804 char typebuf[DNS_RDATATYPE_FORMATSIZE];
8805 int level = ISC_LOG_DEBUG(1);
8806
8807 /*
8808 * If there's no chance of logging it, don't render (format) the
8809 * name and RDATA type (further below), and return early.
8810 */
8811 if (! isc_log_wouldlog(dns_lctx, level))
8812 return;
8813
8814 dns_name_format(name, namebuf, sizeof(namebuf));
8815 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
8816
8817 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
8818 DNS_LOGMODULE_RESOLVER, level,
8819 "createfetch: %s %s", namebuf, typebuf);
8820 }
8821
8822 isc_result_t
dns_resolver_createfetch(dns_resolver_t * res,dns_name_t * name,dns_rdatatype_t type,dns_name_t * domain,dns_rdataset_t * nameservers,dns_forwarders_t * forwarders,unsigned int options,isc_task_t * task,isc_taskaction_t action,void * arg,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset,dns_fetch_t ** fetchp)8823 dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
8824 dns_rdatatype_t type,
8825 dns_name_t *domain, dns_rdataset_t *nameservers,
8826 dns_forwarders_t *forwarders,
8827 unsigned int options, isc_task_t *task,
8828 isc_taskaction_t action, void *arg,
8829 dns_rdataset_t *rdataset,
8830 dns_rdataset_t *sigrdataset,
8831 dns_fetch_t **fetchp)
8832 {
8833 return (dns_resolver_createfetch3(res, name, type, domain,
8834 nameservers, forwarders, NULL, 0,
8835 options, 0, NULL, task, action, arg,
8836 rdataset, sigrdataset, fetchp));
8837 }
8838
8839 isc_result_t
dns_resolver_createfetch2(dns_resolver_t * res,dns_name_t * name,dns_rdatatype_t type,dns_name_t * domain,dns_rdataset_t * nameservers,dns_forwarders_t * forwarders,isc_sockaddr_t * client,dns_messageid_t id,unsigned int options,isc_task_t * task,isc_taskaction_t action,void * arg,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset,dns_fetch_t ** fetchp)8840 dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
8841 dns_rdatatype_t type,
8842 dns_name_t *domain, dns_rdataset_t *nameservers,
8843 dns_forwarders_t *forwarders,
8844 isc_sockaddr_t *client, dns_messageid_t id,
8845 unsigned int options, isc_task_t *task,
8846 isc_taskaction_t action, void *arg,
8847 dns_rdataset_t *rdataset,
8848 dns_rdataset_t *sigrdataset,
8849 dns_fetch_t **fetchp)
8850 {
8851 return (dns_resolver_createfetch3(res, name, type, domain,
8852 nameservers, forwarders, client, id,
8853 options, 0, NULL, task, action, arg,
8854 rdataset, sigrdataset, fetchp));
8855 }
8856
8857 isc_result_t
dns_resolver_createfetch3(dns_resolver_t * res,dns_name_t * name,dns_rdatatype_t type,dns_name_t * domain,dns_rdataset_t * nameservers,dns_forwarders_t * forwarders,isc_sockaddr_t * client,dns_messageid_t id,unsigned int options,unsigned int depth,isc_counter_t * qc,isc_task_t * task,isc_taskaction_t action,void * arg,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset,dns_fetch_t ** fetchp)8858 dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name,
8859 dns_rdatatype_t type,
8860 dns_name_t *domain, dns_rdataset_t *nameservers,
8861 dns_forwarders_t *forwarders,
8862 isc_sockaddr_t *client, dns_messageid_t id,
8863 unsigned int options, unsigned int depth,
8864 isc_counter_t *qc, isc_task_t *task,
8865 isc_taskaction_t action, void *arg,
8866 dns_rdataset_t *rdataset,
8867 dns_rdataset_t *sigrdataset,
8868 dns_fetch_t **fetchp)
8869 {
8870 dns_fetch_t *fetch;
8871 fetchctx_t *fctx = NULL;
8872 isc_result_t result = ISC_R_SUCCESS;
8873 unsigned int bucketnum;
8874 isc_boolean_t new_fctx = ISC_FALSE;
8875 isc_event_t *event;
8876 unsigned int count = 0;
8877 unsigned int spillat;
8878 unsigned int spillatmin;
8879 isc_boolean_t dodestroy = ISC_FALSE;
8880
8881 UNUSED(forwarders);
8882
8883 REQUIRE(VALID_RESOLVER(res));
8884 REQUIRE(res->frozen);
8885 /* XXXRTH Check for meta type */
8886 if (domain != NULL) {
8887 REQUIRE(DNS_RDATASET_VALID(nameservers));
8888 REQUIRE(nameservers->type == dns_rdatatype_ns);
8889 } else
8890 REQUIRE(nameservers == NULL);
8891 REQUIRE(forwarders == NULL);
8892 REQUIRE(!dns_rdataset_isassociated(rdataset));
8893 REQUIRE(sigrdataset == NULL ||
8894 !dns_rdataset_isassociated(sigrdataset));
8895 REQUIRE(fetchp != NULL && *fetchp == NULL);
8896
8897 log_fetch(name, type);
8898
8899 /*
8900 * XXXRTH use a mempool?
8901 */
8902 fetch = isc_mem_get(res->mctx, sizeof(*fetch));
8903 if (fetch == NULL)
8904 return (ISC_R_NOMEMORY);
8905 fetch->mctx = NULL;
8906 isc_mem_attach(res->mctx, &fetch->mctx);
8907
8908 bucketnum = dns_name_fullhash(name, ISC_FALSE) % res->nbuckets;
8909
8910 LOCK(&res->lock);
8911 spillat = res->spillat;
8912 spillatmin = res->spillatmin;
8913 UNLOCK(&res->lock);
8914 LOCK(&res->buckets[bucketnum].lock);
8915
8916 if (res->buckets[bucketnum].exiting) {
8917 result = ISC_R_SHUTTINGDOWN;
8918 goto unlock;
8919 }
8920
8921 if ((options & DNS_FETCHOPT_UNSHARED) == 0) {
8922 for (fctx = ISC_LIST_HEAD(res->buckets[bucketnum].fctxs);
8923 fctx != NULL;
8924 fctx = ISC_LIST_NEXT(fctx, link)) {
8925 if (fctx_match(fctx, name, type, options))
8926 break;
8927 }
8928 }
8929
8930 /*
8931 * Is this a duplicate?
8932 */
8933 if (fctx != NULL && client != NULL) {
8934 dns_fetchevent_t *fevent;
8935 for (fevent = ISC_LIST_HEAD(fctx->events);
8936 fevent != NULL;
8937 fevent = ISC_LIST_NEXT(fevent, ev_link)) {
8938 if (fevent->client != NULL && fevent->id == id &&
8939 isc_sockaddr_equal(fevent->client, client)) {
8940 result = DNS_R_DUPLICATE;
8941 goto unlock;
8942 }
8943 count++;
8944 }
8945 }
8946 if (count >= spillatmin && spillatmin != 0) {
8947 INSIST(fctx != NULL);
8948 if (count >= spillat)
8949 fctx->spilled = ISC_TRUE;
8950 if (fctx->spilled) {
8951 result = DNS_R_DROP;
8952 goto unlock;
8953 }
8954 }
8955
8956 if (fctx == NULL) {
8957 result = fctx_create(res, name, type, domain, nameservers,
8958 options, bucketnum, depth, qc, &fctx);
8959 if (result != ISC_R_SUCCESS)
8960 goto unlock;
8961 new_fctx = ISC_TRUE;
8962 } else if (fctx->depth > depth)
8963 fctx->depth = depth;
8964
8965 result = fctx_join(fctx, task, client, id, action, arg,
8966 rdataset, sigrdataset, fetch);
8967 if (new_fctx) {
8968 if (result == ISC_R_SUCCESS) {
8969 /*
8970 * Launch this fctx.
8971 */
8972 event = &fctx->control_event;
8973 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
8974 DNS_EVENT_FETCHCONTROL,
8975 fctx_start, fctx, NULL,
8976 NULL, NULL);
8977 isc_task_send(res->buckets[bucketnum].task, &event);
8978 } else {
8979 /*
8980 * We don't care about the result of fctx_unlink()
8981 * since we know we're not exiting.
8982 */
8983 (void)fctx_unlink(fctx);
8984 dodestroy = ISC_TRUE;
8985 }
8986 }
8987
8988 unlock:
8989 UNLOCK(&res->buckets[bucketnum].lock);
8990
8991 if (dodestroy)
8992 fctx_destroy(fctx);
8993
8994 if (result == ISC_R_SUCCESS) {
8995 FTRACE("created");
8996 *fetchp = fetch;
8997 } else
8998 isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch));
8999
9000 return (result);
9001 }
9002
9003 void
dns_resolver_cancelfetch(dns_fetch_t * fetch)9004 dns_resolver_cancelfetch(dns_fetch_t *fetch) {
9005 fetchctx_t *fctx;
9006 dns_resolver_t *res;
9007 dns_fetchevent_t *event, *next_event;
9008 isc_task_t *etask;
9009
9010 REQUIRE(DNS_FETCH_VALID(fetch));
9011 fctx = fetch->private;
9012 REQUIRE(VALID_FCTX(fctx));
9013 res = fctx->res;
9014
9015 FTRACE("cancelfetch");
9016
9017 LOCK(&res->buckets[fctx->bucketnum].lock);
9018
9019 /*
9020 * Find the completion event for this fetch (as opposed
9021 * to those for other fetches that have joined the same
9022 * fctx) and send it with result = ISC_R_CANCELED.
9023 */
9024 event = NULL;
9025 if (fctx->state != fetchstate_done) {
9026 for (event = ISC_LIST_HEAD(fctx->events);
9027 event != NULL;
9028 event = next_event) {
9029 next_event = ISC_LIST_NEXT(event, ev_link);
9030 if (event->fetch == fetch) {
9031 ISC_LIST_UNLINK(fctx->events, event, ev_link);
9032 break;
9033 }
9034 }
9035 }
9036 if (event != NULL) {
9037 etask = event->ev_sender;
9038 event->ev_sender = fctx;
9039 event->result = ISC_R_CANCELED;
9040 isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event));
9041 }
9042 /*
9043 * The fctx continues running even if no fetches remain;
9044 * the answer is still cached.
9045 */
9046
9047 UNLOCK(&res->buckets[fctx->bucketnum].lock);
9048 }
9049
9050 void
dns_resolver_destroyfetch(dns_fetch_t ** fetchp)9051 dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
9052 dns_fetch_t *fetch;
9053 dns_resolver_t *res;
9054 dns_fetchevent_t *event, *next_event;
9055 fetchctx_t *fctx;
9056 unsigned int bucketnum;
9057 isc_boolean_t bucket_empty;
9058
9059 REQUIRE(fetchp != NULL);
9060 fetch = *fetchp;
9061 REQUIRE(DNS_FETCH_VALID(fetch));
9062 fctx = fetch->private;
9063 REQUIRE(VALID_FCTX(fctx));
9064 res = fctx->res;
9065
9066 FTRACE("destroyfetch");
9067
9068 bucketnum = fctx->bucketnum;
9069 LOCK(&res->buckets[bucketnum].lock);
9070
9071 /*
9072 * Sanity check: the caller should have gotten its event before
9073 * trying to destroy the fetch.
9074 */
9075 event = NULL;
9076 if (fctx->state != fetchstate_done) {
9077 for (event = ISC_LIST_HEAD(fctx->events);
9078 event != NULL;
9079 event = next_event) {
9080 next_event = ISC_LIST_NEXT(event, ev_link);
9081 RUNTIME_CHECK(event->fetch != fetch);
9082 }
9083 }
9084
9085 bucket_empty = fctx_decreference(fctx);
9086
9087 UNLOCK(&res->buckets[bucketnum].lock);
9088
9089 isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch));
9090 *fetchp = NULL;
9091
9092 if (bucket_empty)
9093 empty_bucket(res);
9094 }
9095
9096 void
dns_resolver_logfetch(dns_fetch_t * fetch,isc_log_t * lctx,isc_logcategory_t * category,isc_logmodule_t * module,int level,isc_boolean_t duplicateok)9097 dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
9098 isc_logcategory_t *category, isc_logmodule_t *module,
9099 int level, isc_boolean_t duplicateok)
9100 {
9101 fetchctx_t *fctx;
9102 dns_resolver_t *res;
9103 char domainbuf[DNS_NAME_FORMATSIZE];
9104
9105 REQUIRE(DNS_FETCH_VALID(fetch));
9106 fctx = fetch->private;
9107 REQUIRE(VALID_FCTX(fctx));
9108 res = fctx->res;
9109
9110 LOCK(&res->buckets[fctx->bucketnum].lock);
9111
9112 INSIST(fctx->exitline >= 0);
9113 if (!fctx->logged || duplicateok) {
9114 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
9115 isc_log_write(lctx, category, module, level,
9116 "fetch completed at %s:%d for %s in "
9117 "%" ISC_PRINT_QUADFORMAT "u."
9118 "%06" ISC_PRINT_QUADFORMAT "u: %s/%s "
9119 "[domain:%s,referral:%u,restart:%u,qrysent:%u,"
9120 "timeout:%u,lame:%u,"
9121 #ifdef ENABLE_FETCHLIMIT
9122 "quota:%u,"
9123 #endif /* ENABLE_FETCHLIMIT */
9124 "neterr:%u,"
9125 "badresp:%u,adberr:%u,findfail:%u,valfail:%u]",
9126 __FILE__, fctx->exitline, fctx->info,
9127 fctx->duration / US_PER_SEC,
9128 fctx->duration % US_PER_SEC,
9129 isc_result_totext(fctx->result),
9130 isc_result_totext(fctx->vresult), domainbuf,
9131 fctx->referrals, fctx->restarts,
9132 fctx->querysent, fctx->timeouts, fctx->lamecount,
9133 #ifdef ENABLE_FETCHLIMIT
9134 fctx->quotacount,
9135 #endif /* ENABLE_FETCHLIMIT */
9136 fctx->neterr, fctx->badresp, fctx->adberr,
9137 fctx->findfail, fctx->valfail);
9138 fctx->logged = ISC_TRUE;
9139 }
9140
9141 UNLOCK(&res->buckets[fctx->bucketnum].lock);
9142 }
9143
9144 dns_dispatchmgr_t *
dns_resolver_dispatchmgr(dns_resolver_t * resolver)9145 dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
9146 REQUIRE(VALID_RESOLVER(resolver));
9147 return (resolver->dispatchmgr);
9148 }
9149
9150 dns_dispatch_t *
dns_resolver_dispatchv4(dns_resolver_t * resolver)9151 dns_resolver_dispatchv4(dns_resolver_t *resolver) {
9152 REQUIRE(VALID_RESOLVER(resolver));
9153 return (dns_dispatchset_get(resolver->dispatches4));
9154 }
9155
9156 dns_dispatch_t *
dns_resolver_dispatchv6(dns_resolver_t * resolver)9157 dns_resolver_dispatchv6(dns_resolver_t *resolver) {
9158 REQUIRE(VALID_RESOLVER(resolver));
9159 return (dns_dispatchset_get(resolver->dispatches6));
9160 }
9161
9162 isc_socketmgr_t *
dns_resolver_socketmgr(dns_resolver_t * resolver)9163 dns_resolver_socketmgr(dns_resolver_t *resolver) {
9164 REQUIRE(VALID_RESOLVER(resolver));
9165 return (resolver->socketmgr);
9166 }
9167
9168 isc_taskmgr_t *
dns_resolver_taskmgr(dns_resolver_t * resolver)9169 dns_resolver_taskmgr(dns_resolver_t *resolver) {
9170 REQUIRE(VALID_RESOLVER(resolver));
9171 return (resolver->taskmgr);
9172 }
9173
9174 isc_uint32_t
dns_resolver_getlamettl(dns_resolver_t * resolver)9175 dns_resolver_getlamettl(dns_resolver_t *resolver) {
9176 REQUIRE(VALID_RESOLVER(resolver));
9177 return (resolver->lame_ttl);
9178 }
9179
9180 void
dns_resolver_setlamettl(dns_resolver_t * resolver,isc_uint32_t lame_ttl)9181 dns_resolver_setlamettl(dns_resolver_t *resolver, isc_uint32_t lame_ttl) {
9182 REQUIRE(VALID_RESOLVER(resolver));
9183 resolver->lame_ttl = lame_ttl;
9184 }
9185
9186 unsigned int
dns_resolver_nrunning(dns_resolver_t * resolver)9187 dns_resolver_nrunning(dns_resolver_t *resolver) {
9188 unsigned int n;
9189 LOCK(&resolver->nlock);
9190 n = resolver->nfctx;
9191 UNLOCK(&resolver->nlock);
9192 return (n);
9193 }
9194
9195 isc_result_t
dns_resolver_addalternate(dns_resolver_t * resolver,isc_sockaddr_t * alt,dns_name_t * name,in_port_t port)9196 dns_resolver_addalternate(dns_resolver_t *resolver, isc_sockaddr_t *alt,
9197 dns_name_t *name, in_port_t port) {
9198 alternate_t *a;
9199 isc_result_t result;
9200
9201 REQUIRE(VALID_RESOLVER(resolver));
9202 REQUIRE(!resolver->frozen);
9203 REQUIRE((alt == NULL) ^ (name == NULL));
9204
9205 a = isc_mem_get(resolver->mctx, sizeof(*a));
9206 if (a == NULL)
9207 return (ISC_R_NOMEMORY);
9208 if (alt != NULL) {
9209 a->isaddress = ISC_TRUE;
9210 a->_u.addr = *alt;
9211 } else {
9212 a->isaddress = ISC_FALSE;
9213 a->_u._n.port = port;
9214 dns_name_init(&a->_u._n.name, NULL);
9215 result = dns_name_dup(name, resolver->mctx, &a->_u._n.name);
9216 if (result != ISC_R_SUCCESS) {
9217 isc_mem_put(resolver->mctx, a, sizeof(*a));
9218 return (result);
9219 }
9220 }
9221 ISC_LINK_INIT(a, link);
9222 ISC_LIST_APPEND(resolver->alternates, a, link);
9223
9224 return (ISC_R_SUCCESS);
9225 }
9226
9227 void
dns_resolver_setudpsize(dns_resolver_t * resolver,isc_uint16_t udpsize)9228 dns_resolver_setudpsize(dns_resolver_t *resolver, isc_uint16_t udpsize) {
9229 REQUIRE(VALID_RESOLVER(resolver));
9230 resolver->udpsize = udpsize;
9231 }
9232
9233 isc_uint16_t
dns_resolver_getudpsize(dns_resolver_t * resolver)9234 dns_resolver_getudpsize(dns_resolver_t *resolver) {
9235 REQUIRE(VALID_RESOLVER(resolver));
9236 return (resolver->udpsize);
9237 }
9238
9239 void
dns_resolver_flushbadcache(dns_resolver_t * resolver,dns_name_t * name)9240 dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name) {
9241 unsigned int i;
9242 dns_badcache_t *bad, *prev, *next;
9243
9244 /*
9245 * Drop all entries that match the name, and also all expired
9246 * entries from the badcache.
9247 */
9248
9249 REQUIRE(VALID_RESOLVER(resolver));
9250
9251 LOCK(&resolver->lock);
9252 if (resolver->badcache == NULL)
9253 goto unlock;
9254
9255 if (name != NULL) {
9256 isc_time_t now;
9257 isc_result_t result;
9258 result = isc_time_now(&now);
9259 if (result != ISC_R_SUCCESS)
9260 isc_time_settoepoch(&now);
9261 i = dns_name_hash(name, ISC_FALSE) % resolver->badhash;
9262 prev = NULL;
9263 for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
9264 int n;
9265 next = bad->next;
9266 n = isc_time_compare(&bad->expire, &now);
9267 if (n < 0 || dns_name_equal(name, &bad->name)) {
9268 if (prev == NULL)
9269 resolver->badcache[i] = bad->next;
9270 else
9271 prev->next = bad->next;
9272 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
9273 bad->name.length);
9274 resolver->badcount--;
9275 } else
9276 prev = bad;
9277 }
9278 } else
9279 destroy_badcache(resolver);
9280
9281 unlock:
9282 UNLOCK(&resolver->lock);
9283
9284 }
9285
9286 static void
resizehash(dns_resolver_t * resolver,isc_time_t * now,isc_boolean_t grow)9287 resizehash(dns_resolver_t *resolver, isc_time_t *now, isc_boolean_t grow) {
9288 unsigned int newsize;
9289 dns_badcache_t **new, *bad, *next;
9290 unsigned int i;
9291
9292 /*
9293 * The number of buckets in the hashtable is modified in this
9294 * function. Afterwards, all the entries are remapped into the
9295 * corresponding new slot. Rehashing (hash computation) is
9296 * unnecessary as the hash values had been saved.
9297 */
9298
9299 if (grow)
9300 newsize = resolver->badhash * 2 + 1;
9301 else
9302 newsize = (resolver->badhash - 1) / 2;
9303
9304 new = isc_mem_get(resolver->mctx,
9305 sizeof(*resolver->badcache) * newsize);
9306 if (new == NULL)
9307 return;
9308 memset(new, 0, sizeof(*resolver->badcache) * newsize);
9309
9310 /*
9311 * Because the hashtable implements a simple modulus mapping
9312 * from hash to bucket (no extendible hashing is used), every
9313 * name in the hashtable has to be remapped to its new slot.
9314 * Entries that have expired (time) are dropped.
9315 */
9316 for (i = 0; i < resolver->badhash; i++) {
9317 for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
9318 next = bad->next;
9319 if (isc_time_compare(&bad->expire, now) < 0) {
9320 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
9321 bad->name.length);
9322 resolver->badcount--;
9323 } else {
9324 bad->next = new[bad->hashval % newsize];
9325 new[bad->hashval % newsize] = bad;
9326 }
9327 }
9328 }
9329 isc_mem_put(resolver->mctx, resolver->badcache,
9330 sizeof(*resolver->badcache) * resolver->badhash);
9331 resolver->badhash = newsize;
9332 resolver->badcache = new;
9333 }
9334
9335 void
dns_resolver_addbadcache(dns_resolver_t * resolver,dns_name_t * name,dns_rdatatype_t type,isc_time_t * expire)9336 dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
9337 dns_rdatatype_t type, isc_time_t *expire)
9338 {
9339 isc_time_t now;
9340 isc_result_t result = ISC_R_SUCCESS;
9341 unsigned int i, hashval;
9342 dns_badcache_t *bad, *prev, *next;
9343
9344 /*
9345 * The badcache is implemented as a hashtable keyed on the name,
9346 * and each bucket slot points to a linked list (separate
9347 * chaining).
9348 *
9349 * To avoid long list chains, if the number of entries in the
9350 * hashtable goes over number-of-buckets * 8, the
9351 * number-of-buckets is doubled. Similarly, if the number of
9352 * entries goes below number-of-buckets * 2, the number-of-buckets
9353 * is halved. See resizehash().
9354 */
9355
9356 REQUIRE(VALID_RESOLVER(resolver));
9357
9358 LOCK(&resolver->lock);
9359 if (resolver->badcache == NULL) {
9360 resolver->badcache = isc_mem_get(resolver->mctx,
9361 sizeof(*resolver->badcache) *
9362 DNS_BADCACHE_SIZE);
9363 if (resolver->badcache == NULL)
9364 goto cleanup;
9365 resolver->badhash = DNS_BADCACHE_SIZE;
9366 memset(resolver->badcache, 0, sizeof(*resolver->badcache) *
9367 resolver->badhash);
9368 }
9369
9370 result = isc_time_now(&now);
9371 if (result != ISC_R_SUCCESS)
9372 isc_time_settoepoch(&now);
9373 hashval = dns_name_hash(name, ISC_FALSE);
9374 i = hashval % resolver->badhash;
9375 prev = NULL;
9376 for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
9377 next = bad->next;
9378 if (bad->type == type && dns_name_equal(name, &bad->name))
9379 break;
9380 /* Drop expired entries when walking the chain. */
9381 if (isc_time_compare(&bad->expire, &now) < 0) {
9382 if (prev == NULL)
9383 resolver->badcache[i] = bad->next;
9384 else
9385 prev->next = bad->next;
9386 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
9387 bad->name.length);
9388 resolver->badcount--;
9389 } else
9390 prev = bad;
9391 }
9392 if (bad == NULL) {
9393 /*
9394 * Insert the name into the badcache hashtable at the
9395 * head of the linked list at the appropriate slot. The
9396 * name data follows right after the allocation for the
9397 * linked list node.
9398 */
9399 isc_buffer_t buffer;
9400 bad = isc_mem_get(resolver->mctx, sizeof(*bad) + name->length);
9401 if (bad == NULL)
9402 goto cleanup;
9403 bad->type = type;
9404 bad->hashval = hashval;
9405 bad->expire = *expire;
9406 isc_buffer_init(&buffer, bad + 1, name->length);
9407 dns_name_init(&bad->name, NULL);
9408 dns_name_copy(name, &bad->name, &buffer);
9409 bad->next = resolver->badcache[i];
9410 resolver->badcache[i] = bad;
9411 resolver->badcount++;
9412 if (resolver->badcount > resolver->badhash * 8)
9413 resizehash(resolver, &now, ISC_TRUE);
9414 if (resolver->badcount < resolver->badhash * 2 &&
9415 resolver->badhash > DNS_BADCACHE_SIZE)
9416 resizehash(resolver, &now, ISC_FALSE);
9417 } else
9418 bad->expire = *expire;
9419 cleanup:
9420 UNLOCK(&resolver->lock);
9421 }
9422
9423 isc_boolean_t
dns_resolver_getbadcache(dns_resolver_t * resolver,dns_name_t * name,dns_rdatatype_t type,isc_time_t * now)9424 dns_resolver_getbadcache(dns_resolver_t *resolver, dns_name_t *name,
9425 dns_rdatatype_t type, isc_time_t *now)
9426 {
9427 dns_badcache_t *bad, *prev, *next;
9428 isc_boolean_t answer = ISC_FALSE;
9429 unsigned int i;
9430
9431 REQUIRE(VALID_RESOLVER(resolver));
9432
9433 LOCK(&resolver->lock);
9434 if (resolver->badcache == NULL)
9435 goto unlock;
9436
9437 i = dns_name_hash(name, ISC_FALSE) % resolver->badhash;
9438 prev = NULL;
9439 for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
9440 next = bad->next;
9441 /*
9442 * Search the hash list. Clean out expired records as we go.
9443 */
9444 if (isc_time_compare(&bad->expire, now) < 0) {
9445 if (prev != NULL)
9446 prev->next = bad->next;
9447 else
9448 resolver->badcache[i] = bad->next;
9449 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
9450 bad->name.length);
9451 resolver->badcount--;
9452 continue;
9453 }
9454 if (bad->type == type && dns_name_equal(name, &bad->name)) {
9455 answer = ISC_TRUE;
9456 break;
9457 }
9458 prev = bad;
9459 }
9460
9461 /*
9462 * Slow sweep to clean out stale records.
9463 */
9464 i = resolver->badsweep++ % resolver->badhash;
9465 bad = resolver->badcache[i];
9466 if (bad != NULL && isc_time_compare(&bad->expire, now) < 0) {
9467 resolver->badcache[i] = bad->next;
9468 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
9469 bad->name.length);
9470 resolver->badcount--;
9471 }
9472
9473 unlock:
9474 UNLOCK(&resolver->lock);
9475 return (answer);
9476 }
9477
9478 void
dns_resolver_printbadcache(dns_resolver_t * resolver,FILE * fp)9479 dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp) {
9480 char namebuf[DNS_NAME_FORMATSIZE];
9481 char typebuf[DNS_RDATATYPE_FORMATSIZE];
9482 dns_badcache_t *bad, *next, *prev;
9483 isc_time_t now;
9484 unsigned int i;
9485 isc_uint64_t t;
9486
9487 LOCK(&resolver->lock);
9488 fprintf(fp, ";\n; Bad cache\n;\n");
9489
9490 if (resolver->badcache == NULL)
9491 goto unlock;
9492
9493 TIME_NOW(&now);
9494 for (i = 0; i < resolver->badhash; i++) {
9495 prev = NULL;
9496 for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
9497 next = bad->next;
9498 if (isc_time_compare(&bad->expire, &now) < 0) {
9499 if (prev != NULL)
9500 prev->next = bad->next;
9501 else
9502 resolver->badcache[i] = bad->next;
9503 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
9504 bad->name.length);
9505 resolver->badcount--;
9506 continue;
9507 }
9508 prev = bad;
9509 dns_name_format(&bad->name, namebuf, sizeof(namebuf));
9510 dns_rdatatype_format(bad->type, typebuf,
9511 sizeof(typebuf));
9512 t = isc_time_microdiff(&bad->expire, &now);
9513 t /= 1000;
9514 fprintf(fp, "; %s/%s [ttl "
9515 "%" ISC_PLATFORM_QUADFORMAT "u]\n",
9516 namebuf, typebuf, t);
9517 }
9518 }
9519
9520 unlock:
9521 UNLOCK(&resolver->lock);
9522 }
9523
9524 static void
free_algorithm(void * node,void * arg)9525 free_algorithm(void *node, void *arg) {
9526 unsigned char *algorithms = node;
9527 isc_mem_t *mctx = arg;
9528
9529 isc_mem_put(mctx, algorithms, *algorithms);
9530 }
9531
9532 void
dns_resolver_reset_algorithms(dns_resolver_t * resolver)9533 dns_resolver_reset_algorithms(dns_resolver_t *resolver) {
9534
9535 REQUIRE(VALID_RESOLVER(resolver));
9536
9537 #if USE_ALGLOCK
9538 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
9539 #endif
9540 if (resolver->algorithms != NULL)
9541 dns_rbt_destroy(&resolver->algorithms);
9542 #if USE_ALGLOCK
9543 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
9544 #endif
9545 }
9546
9547 isc_result_t
dns_resolver_disable_algorithm(dns_resolver_t * resolver,dns_name_t * name,unsigned int alg)9548 dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
9549 unsigned int alg)
9550 {
9551 unsigned int len, mask;
9552 unsigned char *new;
9553 unsigned char *algorithms;
9554 isc_result_t result;
9555 dns_rbtnode_t *node = NULL;
9556
9557 /*
9558 * Whether an algorithm is disabled (or not) is stored in a
9559 * per-name bitfield that is stored as the node data of an
9560 * RBT.
9561 */
9562
9563 REQUIRE(VALID_RESOLVER(resolver));
9564 if (alg > 255)
9565 return (ISC_R_RANGE);
9566
9567 #if USE_ALGLOCK
9568 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
9569 #endif
9570 if (resolver->algorithms == NULL) {
9571 result = dns_rbt_create(resolver->mctx, free_algorithm,
9572 resolver->mctx, &resolver->algorithms);
9573 if (result != ISC_R_SUCCESS)
9574 goto cleanup;
9575 }
9576
9577 len = alg/8 + 2;
9578 mask = 1 << (alg%8);
9579
9580 result = dns_rbt_addnode(resolver->algorithms, name, &node);
9581
9582 if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
9583 algorithms = node->data;
9584 /*
9585 * If algorithms is set, algorithms[0] contains its
9586 * length.
9587 */
9588 if (algorithms == NULL || len > *algorithms) {
9589 /*
9590 * If no bitfield exists in the node data, or if
9591 * it is not long enough, allocate a new
9592 * bitfield and copy the old (smaller) bitfield
9593 * into it if one exists.
9594 */
9595 new = isc_mem_get(resolver->mctx, len);
9596 if (new == NULL) {
9597 result = ISC_R_NOMEMORY;
9598 goto cleanup;
9599 }
9600 memset(new, 0, len);
9601 if (algorithms != NULL)
9602 memmove(new, algorithms, *algorithms);
9603 new[len-1] |= mask;
9604 /* new[0] should contain the length of new. */
9605 *new = len;
9606 node->data = new;
9607 /* Free the older bitfield. */
9608 if (algorithms != NULL)
9609 isc_mem_put(resolver->mctx, algorithms,
9610 *algorithms);
9611 } else
9612 algorithms[len-1] |= mask;
9613 }
9614 result = ISC_R_SUCCESS;
9615 cleanup:
9616 #if USE_ALGLOCK
9617 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
9618 #endif
9619 return (result);
9620 }
9621
9622 isc_boolean_t
dns_resolver_algorithm_supported(dns_resolver_t * resolver,dns_name_t * name,unsigned int alg)9623 dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
9624 unsigned int alg)
9625 {
9626 unsigned int len, mask;
9627 unsigned char *algorithms;
9628 void *data = NULL;
9629 isc_result_t result;
9630 isc_boolean_t found = ISC_FALSE;
9631
9632 REQUIRE(VALID_RESOLVER(resolver));
9633
9634 /*
9635 * DH is unsupported for DNSKEYs, see RFC 4034 sec. A.1.
9636 */
9637 if ((alg == DST_ALG_DH) || (alg == DST_ALG_INDIRECT))
9638 return (ISC_FALSE);
9639
9640 #if USE_ALGLOCK
9641 RWLOCK(&resolver->alglock, isc_rwlocktype_read);
9642 #endif
9643 if (resolver->algorithms == NULL)
9644 goto unlock;
9645 result = dns_rbt_findname(resolver->algorithms, name, 0, NULL, &data);
9646 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
9647 len = alg/8 + 2;
9648 mask = 1 << (alg%8);
9649 algorithms = data;
9650 if (len <= *algorithms && (algorithms[len-1] & mask) != 0)
9651 found = ISC_TRUE;
9652 }
9653 unlock:
9654 #if USE_ALGLOCK
9655 RWUNLOCK(&resolver->alglock, isc_rwlocktype_read);
9656 #endif
9657 if (found)
9658 return (ISC_FALSE);
9659
9660 return (dst_algorithm_supported(alg));
9661 }
9662
9663 isc_boolean_t
dns_resolver_digest_supported(dns_resolver_t * resolver,unsigned int digest)9664 dns_resolver_digest_supported(dns_resolver_t *resolver, unsigned int digest) {
9665
9666 UNUSED(resolver);
9667 return (dns_ds_digest_supported(digest));
9668 }
9669
9670 void
dns_resolver_resetmustbesecure(dns_resolver_t * resolver)9671 dns_resolver_resetmustbesecure(dns_resolver_t *resolver) {
9672
9673 REQUIRE(VALID_RESOLVER(resolver));
9674
9675 #if USE_MBSLOCK
9676 RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
9677 #endif
9678 if (resolver->mustbesecure != NULL)
9679 dns_rbt_destroy(&resolver->mustbesecure);
9680 #if USE_MBSLOCK
9681 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
9682 #endif
9683 }
9684
9685 static isc_boolean_t yes = ISC_TRUE, no = ISC_FALSE;
9686
9687 isc_result_t
dns_resolver_setmustbesecure(dns_resolver_t * resolver,dns_name_t * name,isc_boolean_t value)9688 dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
9689 isc_boolean_t value)
9690 {
9691 isc_result_t result;
9692
9693 REQUIRE(VALID_RESOLVER(resolver));
9694
9695 #if USE_MBSLOCK
9696 RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
9697 #endif
9698 if (resolver->mustbesecure == NULL) {
9699 result = dns_rbt_create(resolver->mctx, NULL, NULL,
9700 &resolver->mustbesecure);
9701 if (result != ISC_R_SUCCESS)
9702 goto cleanup;
9703 }
9704 result = dns_rbt_addname(resolver->mustbesecure, name,
9705 value ? &yes : &no);
9706 cleanup:
9707 #if USE_MBSLOCK
9708 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
9709 #endif
9710 return (result);
9711 }
9712
9713 isc_boolean_t
dns_resolver_getmustbesecure(dns_resolver_t * resolver,dns_name_t * name)9714 dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name) {
9715 void *data = NULL;
9716 isc_boolean_t value = ISC_FALSE;
9717 isc_result_t result;
9718
9719 REQUIRE(VALID_RESOLVER(resolver));
9720
9721 #if USE_MBSLOCK
9722 RWLOCK(&resolver->mbslock, isc_rwlocktype_read);
9723 #endif
9724 if (resolver->mustbesecure == NULL)
9725 goto unlock;
9726 result = dns_rbt_findname(resolver->mustbesecure, name, 0, NULL, &data);
9727 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
9728 value = *(isc_boolean_t*)data;
9729 unlock:
9730 #if USE_MBSLOCK
9731 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_read);
9732 #endif
9733 return (value);
9734 }
9735
9736 void
dns_resolver_getclientsperquery(dns_resolver_t * resolver,isc_uint32_t * cur,isc_uint32_t * min,isc_uint32_t * max)9737 dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
9738 isc_uint32_t *min, isc_uint32_t *max)
9739 {
9740 REQUIRE(VALID_RESOLVER(resolver));
9741
9742 LOCK(&resolver->lock);
9743 if (cur != NULL)
9744 *cur = resolver->spillat;
9745 if (min != NULL)
9746 *min = resolver->spillatmin;
9747 if (max != NULL)
9748 *max = resolver->spillatmax;
9749 UNLOCK(&resolver->lock);
9750 }
9751
9752 void
dns_resolver_setclientsperquery(dns_resolver_t * resolver,isc_uint32_t min,isc_uint32_t max)9753 dns_resolver_setclientsperquery(dns_resolver_t *resolver, isc_uint32_t min,
9754 isc_uint32_t max)
9755 {
9756 REQUIRE(VALID_RESOLVER(resolver));
9757
9758 LOCK(&resolver->lock);
9759 resolver->spillatmin = resolver->spillat = min;
9760 resolver->spillatmax = max;
9761 UNLOCK(&resolver->lock);
9762 }
9763
9764 void
dns_resolver_setfetchesperzone(dns_resolver_t * resolver,isc_uint32_t clients)9765 dns_resolver_setfetchesperzone(dns_resolver_t *resolver, isc_uint32_t clients)
9766 {
9767 #ifdef ENABLE_FETCHLIMIT
9768 REQUIRE(VALID_RESOLVER(resolver));
9769
9770 LOCK(&resolver->lock);
9771 resolver->zspill = clients;
9772 UNLOCK(&resolver->lock);
9773 #else
9774 UNUSED(resolver);
9775 UNUSED(clients);
9776
9777 return;
9778 #endif /* !ENABLE_FETCHLIMIT */
9779 }
9780
9781
9782 isc_boolean_t
dns_resolver_getzeronosoattl(dns_resolver_t * resolver)9783 dns_resolver_getzeronosoattl(dns_resolver_t *resolver) {
9784 REQUIRE(VALID_RESOLVER(resolver));
9785
9786 return (resolver->zero_no_soa_ttl);
9787 }
9788
9789 void
dns_resolver_setzeronosoattl(dns_resolver_t * resolver,isc_boolean_t state)9790 dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state) {
9791 REQUIRE(VALID_RESOLVER(resolver));
9792
9793 resolver->zero_no_soa_ttl = state;
9794 }
9795
9796 unsigned int
dns_resolver_getoptions(dns_resolver_t * resolver)9797 dns_resolver_getoptions(dns_resolver_t *resolver) {
9798 REQUIRE(VALID_RESOLVER(resolver));
9799
9800 return (resolver->options);
9801 }
9802
9803 unsigned int
dns_resolver_gettimeout(dns_resolver_t * resolver)9804 dns_resolver_gettimeout(dns_resolver_t *resolver) {
9805 REQUIRE(VALID_RESOLVER(resolver));
9806
9807 return (resolver->query_timeout);
9808 }
9809
9810 void
dns_resolver_settimeout(dns_resolver_t * resolver,unsigned int seconds)9811 dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int seconds) {
9812 REQUIRE(VALID_RESOLVER(resolver));
9813
9814 if (seconds == 0)
9815 seconds = DEFAULT_QUERY_TIMEOUT;
9816 if (seconds > MAXIMUM_QUERY_TIMEOUT)
9817 seconds = MAXIMUM_QUERY_TIMEOUT;
9818 if (seconds < MINIMUM_QUERY_TIMEOUT)
9819 seconds = MINIMUM_QUERY_TIMEOUT;
9820
9821 resolver->query_timeout = seconds;
9822 }
9823
9824 void
dns_resolver_setmaxdepth(dns_resolver_t * resolver,unsigned int maxdepth)9825 dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) {
9826 REQUIRE(VALID_RESOLVER(resolver));
9827 resolver->maxdepth = maxdepth;
9828 }
9829
9830 unsigned int
dns_resolver_getmaxdepth(dns_resolver_t * resolver)9831 dns_resolver_getmaxdepth(dns_resolver_t *resolver) {
9832 REQUIRE(VALID_RESOLVER(resolver));
9833 return (resolver->maxdepth);
9834 }
9835
9836 void
dns_resolver_setmaxqueries(dns_resolver_t * resolver,unsigned int queries)9837 dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries) {
9838 REQUIRE(VALID_RESOLVER(resolver));
9839 resolver->maxqueries = queries;
9840 }
9841
9842 unsigned int
dns_resolver_getmaxqueries(dns_resolver_t * resolver)9843 dns_resolver_getmaxqueries(dns_resolver_t *resolver) {
9844 REQUIRE(VALID_RESOLVER(resolver));
9845 return (resolver->maxqueries);
9846 }
9847
9848 void
dns_resolver_dumpfetches(dns_resolver_t * resolver,FILE * fp)9849 dns_resolver_dumpfetches(dns_resolver_t *resolver, FILE *fp) {
9850 #ifdef ENABLE_FETCHLIMIT
9851 int i;
9852
9853 REQUIRE(VALID_RESOLVER(resolver));
9854 REQUIRE(fp != NULL);
9855
9856 for (i = 0; i < RES_DOMAIN_BUCKETS; i++) {
9857 fctxcount_t *fc;
9858 LOCK(&resolver->dbuckets[i].lock);
9859 for (fc = ISC_LIST_HEAD(resolver->dbuckets[i].list);
9860 fc != NULL;
9861 fc = ISC_LIST_NEXT(fc, link))
9862 {
9863 dns_name_print(fc->domain, fp);
9864 fprintf(fp, ": %d active (%d spilled, %d allowed)\n",
9865 fc->count, fc->dropped, fc->allowed);
9866 }
9867 UNLOCK(&resolver->dbuckets[i].lock);
9868 }
9869 #else
9870 UNUSED(resolver);
9871 UNUSED(fp);
9872
9873 return;
9874 #endif /* !ENABLE_FETCHLIMIT */
9875 }
9876
9877 void
dns_resolver_setquotaresponse(dns_resolver_t * resolver,dns_quotatype_t which,isc_result_t resp)9878 dns_resolver_setquotaresponse(dns_resolver_t *resolver,
9879 dns_quotatype_t which, isc_result_t resp)
9880 {
9881 #ifdef ENABLE_FETCHLIMIT
9882 REQUIRE(VALID_RESOLVER(resolver));
9883 REQUIRE(which == dns_quotatype_zone || which == dns_quotatype_server);
9884 REQUIRE(resp == DNS_R_DROP || resp == DNS_R_SERVFAIL);
9885
9886 resolver->quotaresp[which] = resp;
9887 #else
9888 UNUSED(resolver);
9889 UNUSED(which);
9890 UNUSED(resp);
9891
9892 return;
9893 #endif /* !ENABLE_FETCHLIMIT */
9894 }
9895
9896 isc_result_t
dns_resolver_getquotaresponse(dns_resolver_t * resolver,dns_quotatype_t which)9897 dns_resolver_getquotaresponse(dns_resolver_t *resolver, dns_quotatype_t which)
9898 {
9899 #ifdef ENABLE_FETCHLIMIT
9900 REQUIRE(VALID_RESOLVER(resolver));
9901 REQUIRE(which == dns_quotatype_zone || which == dns_quotatype_server);
9902
9903 return (resolver->quotaresp[which]);
9904 #else
9905 UNUSED(resolver);
9906 UNUSED(which);
9907
9908 return (ISC_R_NOTIMPLEMENTED);
9909 #endif /* !ENABLE_FETCHLIMIT */
9910 }
9911