resolver.c 298 KB
Newer Older
Michael Graff's avatar
Michael Graff committed
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4 5 6
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 8 9
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
Michael Graff's avatar
Michael Graff committed
10
 */
Bob Halley's avatar
Bob Halley committed
11

12
/*! \file */
David Lawrence's avatar
David Lawrence committed
13

Evan Hunt's avatar
Evan Hunt committed
14
#include <ctype.h>
15
#include <inttypes.h>
16
#include <stdbool.h>
17

Mark Andrews's avatar
Mark Andrews committed
18
#include <isc/atomic.h>
19
#include <isc/counter.h>
20
#include <isc/log.h>
21
#include <isc/platform.h>
22
#include <isc/print.h>
23
#include <isc/random.h>
24
#include <isc/siphash.h>
25
#include <isc/socket.h>
26
#include <isc/stats.h>
27
#include <isc/string.h>
28
#include <isc/task.h>
29
#include <isc/timer.h>
Michael Graff's avatar
Michael Graff committed
30
#include <isc/util.h>
Bob Halley's avatar
Bob Halley committed
31

32
#include <dns/acl.h>
Bob Halley's avatar
Bob Halley committed
33
#include <dns/adb.h>
Evan Hunt's avatar
Evan Hunt committed
34
#include <dns/badcache.h>
35
#include <dns/cache.h>
Bob Halley's avatar
Bob Halley committed
36
#include <dns/db.h>
37
#include <dns/dispatch.h>
Evan Hunt's avatar
Evan Hunt committed
38
#include <dns/dnstap.h>
39
#include <dns/ds.h>
40
#include <dns/edns.h>
Bob Halley's avatar
Bob Halley committed
41
#include <dns/events.h>
42
#include <dns/forward.h>
Bob Halley's avatar
Bob Halley committed
43
#include <dns/keytable.h>
44
#include <dns/log.h>
Bob Halley's avatar
Bob Halley committed
45
#include <dns/message.h>
46
#include <dns/ncache.h>
47 48
#include <dns/nsec.h>
#include <dns/nsec3.h>
49
#include <dns/opcode.h>
50
#include <dns/peer.h>
51
#include <dns/rbt.h>
52
#include <dns/rcode.h>
53
#include <dns/rdata.h>
54
#include <dns/rdataclass.h>
Bob Halley's avatar
Bob Halley committed
55
#include <dns/rdatalist.h>
Bob Halley's avatar
Bob Halley committed
56
#include <dns/rdataset.h>
57
#include <dns/rdatastruct.h>
58
#include <dns/rdatatype.h>
59 60
#include <dns/resolver.h>
#include <dns/result.h>
61
#include <dns/rootns.h>
62
#include <dns/stats.h>
63
#include <dns/tsig.h>
64
#include <dns/validator.h>
65
#ifdef WANT_QUERYTRACE
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
#define RTRACE(m)                                                             \
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,                     \
		      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), "res %p: %s", \
		      res, (m))
#define RRTRACE(r, m)                                                         \
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,                     \
		      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), "res %p: %s", \
		      (r), (m))
#define FCTXTRACE(m)                                            \
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,       \
		      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), \
		      "fctx %p(%s): %s", fctx, fctx->info, (m))
#define FCTXTRACE2(m1, m2)                                      \
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,       \
		      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), \
		      "fctx %p(%s): %s %s", fctx, fctx->info, (m1), (m2))
#define FCTXTRACE3(m, res)                                              \
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,               \
		      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),         \
		      "fctx %p(%s): [result: %s] %s", fctx, fctx->info, \
		      isc_result_totext(res), (m))
#define FCTXTRACE4(m1, m2, res)                                            \
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,                  \
		      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),            \
		      "fctx %p(%s): [result: %s] %s %s", fctx, fctx->info, \
		      isc_result_totext(res), (m1), (m2))
#define FCTXTRACE5(m1, m2, v)                                               \
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,                   \
		      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),             \
		      "fctx %p(%s): %s %s%u", fctx, fctx->info, (m1), (m2), \
		      (v))
#define FTRACE(m)                                                          \
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,                  \
		      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),            \
		      "fetch %p (fctx %p(%s)): %s", fetch, fetch->private, \
		      fetch->private->info, (m))
#define QTRACE(m)                                                          \
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,                  \
		      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),            \
		      "resquery %p (fctx %p(%s)): %s", query, query->fctx, \
		      query->fctx->info, (m))
107
#else /* ifdef WANT_QUERYTRACE */
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
#define RTRACE(m)          \
	do {               \
		UNUSED(m); \
	} while (0)
#define RRTRACE(r, m)      \
	do {               \
		UNUSED(r); \
		UNUSED(m); \
	} while (0)
#define FCTXTRACE(m)       \
	do {               \
		UNUSED(m); \
	} while (0)
#define FCTXTRACE2(m1, m2)  \
	do {                \
		UNUSED(m1); \
		UNUSED(m2); \
	} while (0)
#define FCTXTRACE3(m1, res)  \
	do {                 \
		UNUSED(m1);  \
		UNUSED(res); \
	} while (0)
131
#define FCTXTRACE4(m1, m2, res) \
132 133 134 135 136
	do {                    \
		UNUSED(m1);     \
		UNUSED(m2);     \
		UNUSED(res);    \
	} while (0)
137
#define FCTXTRACE5(m1, m2, v) \
138 139 140 141 142 143 144 145 146 147 148 149 150
	do {                  \
		UNUSED(m1);   \
		UNUSED(m2);   \
		UNUSED(v);    \
	} while (0)
#define FTRACE(m)          \
	do {               \
		UNUSED(m); \
	} while (0)
#define QTRACE(m)          \
	do {               \
		UNUSED(m); \
	} while (0)
151
#endif /* WANT_QUERYTRACE */
Bob Halley's avatar
Bob Halley committed
152

Evan Hunt's avatar
Evan Hunt committed
153
#define US_PER_SEC  1000000U
154
#define US_PER_MSEC 1000U
155 156 157
/*
 * The maximum time we will wait for a single query.
 */
Evan Hunt's avatar
Evan Hunt committed
158
#define MAX_SINGLE_QUERY_TIMEOUT    9000U
159
#define MAX_SINGLE_QUERY_TIMEOUT_US (MAX_SINGLE_QUERY_TIMEOUT * US_PER_MSEC)
160 161 162 163

/*
 * We need to allow a individual query time to complete / timeout.
 */
164
#define MINIMUM_QUERY_TIMEOUT (MAX_SINGLE_QUERY_TIMEOUT + 1000U)
165 166

/* The default time in seconds for the whole query to live. */
167
#ifndef DEFAULT_QUERY_TIMEOUT
168
#define DEFAULT_QUERY_TIMEOUT MINIMUM_QUERY_TIMEOUT
169
#endif /* ifndef DEFAULT_QUERY_TIMEOUT */
170

Evan Hunt's avatar
Evan Hunt committed
171
/* The maximum time in seconds for the whole query to live. */
172
#ifndef MAXIMUM_QUERY_TIMEOUT
173
#define MAXIMUM_QUERY_TIMEOUT 30000
174
#endif /* ifndef MAXIMUM_QUERY_TIMEOUT */
175

176 177 178
/* The default maximum number of recursions to follow before giving up. */
#ifndef DEFAULT_RECURSION_DEPTH
#define DEFAULT_RECURSION_DEPTH 7
179
#endif /* ifndef DEFAULT_RECURSION_DEPTH */
180 181 182

/* The default maximum number of iterative queries to allow before giving up. */
#ifndef DEFAULT_MAX_QUERIES
183
#define DEFAULT_MAX_QUERIES 75
184
#endif /* ifndef DEFAULT_MAX_QUERIES */
185

186 187 188 189 190 191 192 193
/*
 * After NS_FAIL_LIMIT attempts to fetch a name server address,
 * if the number of addresses in the NS RRset exceeds NS_RR_LIMIT,
 * stop trying to fetch, in order to avoid wasting resources.
 */
#define NS_FAIL_LIMIT 4
#define NS_RR_LIMIT   5

Evan Hunt's avatar
Evan Hunt committed
194 195
/* Number of hash buckets for zone counters */
#ifndef RES_DOMAIN_BUCKETS
196
#define RES_DOMAIN_BUCKETS 523
197
#endif /* ifndef RES_DOMAIN_BUCKETS */
198
#define RES_NOBUCKET 0xffffffff
Evan Hunt's avatar
Evan Hunt committed
199

200
/*%
Bob Halley's avatar
Bob Halley committed
201 202
 * Maximum EDNS0 input packet size.
 */
203
#define RECV_BUFFER_SIZE 4096 /* XXXRTH  Constant. */
204

205
/*%
206
 * This defines the maximum number of timeouts we will permit before we
207 208
 * disable EDNS0 on the query.
 */
209
#define MAX_EDNS0_TIMEOUTS 3
210

Evan Hunt's avatar
Evan Hunt committed
211 212
#define DNS_RESOLVER_BADCACHESIZE 1021
#define DNS_RESOLVER_BADCACHETTL(fctx) \
213
	(((fctx)->res->lame_ttl > 30) ? (fctx)->res->lame_ttl : 30)
Evan Hunt's avatar
Evan Hunt committed
214

Bob Halley's avatar
Bob Halley committed
215 216
typedef struct fetchctx fetchctx_t;

Bob Halley's avatar
Bob Halley committed
217
typedef struct query {
Mark Andrews's avatar
Mark Andrews committed
218
	/* Locked by task event serialization. */
Evan Hunt's avatar
Evan Hunt committed
219 220 221
	unsigned int magic;
	fetchctx_t *fctx;
	isc_mem_t *mctx;
222
	dns_dispatchmgr_t *dispatchmgr;
Evan Hunt's avatar
Evan Hunt committed
223 224
	dns_dispatch_t *dispatch;
	bool exclusivesocket;
225
	dns_adbaddrinfo_t *addrinfo;
Evan Hunt's avatar
Evan Hunt committed
226 227 228 229
	isc_socket_t *tcpsocket;
	isc_time_t start;
	dns_messageid_t id;
	dns_dispentry_t *dispentry;
230
	ISC_LINK(struct query) link;
Evan Hunt's avatar
Evan Hunt committed
231 232 233 234 235 236 237
	isc_buffer_t buffer;
	isc_buffer_t *tsig;
	dns_tsigkey_t *tsigkey;
	isc_socketevent_t sendevent;
	isc_dscp_t dscp;
	int ednsversion;
	unsigned int options;
238
	isc_sockeventattr_t attributes;
Evan Hunt's avatar
Evan Hunt committed
239 240 241 242
	unsigned int sends;
	unsigned int connects;
	unsigned int udpsize;
	unsigned char data[512];
Bob Halley's avatar
Bob Halley committed
243 244
} resquery_t;

245
struct tried {
246
	isc_sockaddr_t addr;
Evan Hunt's avatar
Evan Hunt committed
247
	unsigned int count;
248
	ISC_LINK(struct tried) link;
249 250
};

Evan Hunt's avatar
Evan Hunt committed
251
#define QUERY_MAGIC	   ISC_MAGIC('Q', '!', '!', '!')
252
#define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
Bob Halley's avatar
Bob Halley committed
253

254
#define RESQUERY_ATTR_CANCELED 0x02
255

256
#define RESQUERY_CONNECTING(q) ((q)->connects > 0)
Evan Hunt's avatar
Evan Hunt committed
257 258
#define RESQUERY_CANCELED(q)   (((q)->attributes & RESQUERY_ATTR_CANCELED) != 0)
#define RESQUERY_SENDING(q)    ((q)->sends > 0)
259

Bob Halley's avatar
Bob Halley committed
260
typedef enum {
261
	fetchstate_init = 0, /*%< Start event has not run yet. */
Mark Andrews's avatar
Mark Andrews committed
262
	fetchstate_active,
263
	fetchstate_done /*%< FETCHDONE events posted. */
Bob Halley's avatar
Bob Halley committed
264 265
} fetchstate;

266 267 268
typedef enum {
	badns_unreachable = 0,
	badns_response,
269 270
	badns_validation,
	badns_forwarder,
271 272
} badnstype_t;

Bob Halley's avatar
Bob Halley committed
273
struct fetchctx {
Mark Andrews's avatar
Mark Andrews committed
274
	/*% Not locked. */
Evan Hunt's avatar
Evan Hunt committed
275
	unsigned int magic;
276
	dns_resolver_t *res;
Evan Hunt's avatar
Evan Hunt committed
277
	dns_name_t name;
278
	dns_rdatatype_t type;
Evan Hunt's avatar
Evan Hunt committed
279 280 281 282 283 284
	unsigned int options;
	unsigned int bucketnum;
	unsigned int dbucketnum;
	char *info;
	isc_mem_t *mctx;
	isc_stdtime_t now;
285

286
	/* Atomic */
287
	isc_refcount_t references;
288

Mark Andrews's avatar
Mark Andrews committed
289
	/*% Locked by appropriate bucket lock. */
Evan Hunt's avatar
Evan Hunt committed
290 291 292 293
	fetchstate state;
	bool want_shutdown;
	bool cloned;
	bool spilled;
294 295 296
	isc_event_t control_event;
	ISC_LINK(struct fetchctx) link;
	ISC_LIST(dns_fetchevent_t) events;
Witold Krecicki's avatar
Witold Krecicki committed
297

Mark Andrews's avatar
Mark Andrews committed
298
	/*% Locked by task event serialization. */
Evan Hunt's avatar
Evan Hunt committed
299 300
	dns_name_t domain;
	dns_rdataset_t nameservers;
301
	atomic_uint_fast32_t attributes;
Evan Hunt's avatar
Evan Hunt committed
302 303 304 305 306
	isc_timer_t *timer;
	isc_time_t expires;
	isc_interval_t interval;
	dns_message_t *qmessage;
	dns_message_t *rmessage;
307
	ISC_LIST(resquery_t) queries;
Evan Hunt's avatar
Evan Hunt committed
308 309 310 311
	dns_adbfindlist_t finds;
	dns_adbfind_t *find;
	dns_adbfindlist_t altfinds;
	dns_adbfind_t *altfind;
312 313
	dns_adbaddrinfolist_t forwaddrs;
	dns_adbaddrinfolist_t altaddrs;
Evan Hunt's avatar
Evan Hunt committed
314 315 316
	dns_forwarderlist_t forwarders;
	dns_fwdpolicy_t fwdpolicy;
	isc_sockaddrlist_t bad;
317 318 319
	ISC_LIST(struct tried) edns;
	ISC_LIST(struct tried) edns512;
	isc_sockaddrlist_t bad_edns;
Evan Hunt's avatar
Evan Hunt committed
320
	dns_validator_t *validator;
321
	ISC_LIST(dns_validator_t) validators;
Evan Hunt's avatar
Evan Hunt committed
322 323 324 325 326 327 328 329 330 331 332
	dns_db_t *cache;
	dns_adb_t *adb;
	bool ns_ttl_ok;
	uint32_t ns_ttl;
	isc_counter_t *qc;
	bool minimized;
	unsigned int qmin_labels;
	isc_result_t qmin_warning;
	bool ip6arpaskip;
	bool forwarding;
	dns_name_t qminname;
333
	dns_rdatatype_t qmintype;
Evan Hunt's avatar
Evan Hunt committed
334 335 336
	dns_fetch_t *qminfetch;
	dns_rdataset_t qminrrset;
	dns_name_t qmindcname;
Mark Andrews's avatar
Mark Andrews committed
337 338 339 340

	/*%
	 * The number of events we're waiting for.
	 */
341
	unsigned int pending; /* Bucket lock. */
Mark Andrews's avatar
Mark Andrews committed
342 343 344 345 346 347 348 349 350

	/*%
	 * The number of times we've "restarted" the current
	 * nameserver set.  This acts as a failsafe to prevent
	 * us from pounding constantly on a particular set of
	 * servers that, for whatever reason, are not giving
	 * us useful responses, but are responding in such a
	 * way that they are not marked "bad".
	 */
351
	unsigned int restarts;
Mark Andrews's avatar
Mark Andrews committed
352 353 354 355 356 357

	/*%
	 * The number of timeouts that have occurred since we
	 * last successfully received a response packet.  This
	 * is used for EDNS0 black hole detection.
	 */
358
	unsigned int timeouts;
359

Mark Andrews's avatar
Mark Andrews committed
360 361 362
	/*%
	 * Look aside state for DS lookups.
	 */
Evan Hunt's avatar
Evan Hunt committed
363 364
	dns_name_t nsname;
	dns_fetch_t *nsfetch;
365
	dns_rdataset_t nsrrset;
Mark Andrews's avatar
Mark Andrews committed
366 367 368 369

	/*%
	 * Number of queries that reference this context.
	 */
370
	unsigned int nqueries; /* Bucket lock. */
371 372 373 374 375

	/*%
	 * The reason to print when logging a successful
	 * response to a query.
	 */
376
	const char *reason;
Evan Hunt's avatar
Evan Hunt committed
377 378 379 380

	/*%
	 * Random numbers to use for mixing up server addresses.
	 */
381 382
	uint32_t rand_buf;
	uint32_t rand_bits;
383 384 385 386

	/*%
	 * Fetch-local statistics for detailed logging.
	 */
Evan Hunt's avatar
Evan Hunt committed
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
	isc_result_t result;  /*%< fetch result  */
	isc_result_t vresult; /*%< validation result  */
	int exitline;
	isc_time_t start;
	uint64_t duration;
	bool logged;
	unsigned int querysent;
	unsigned int referrals;
	unsigned int lamecount;
	unsigned int quotacount;
	unsigned int neterr;
	unsigned int badresp;
	unsigned int adberr;
	unsigned int findfail;
	unsigned int valfail;
	bool timeout;
	dns_adbaddrinfo_t *addrinfo;
404
	const isc_sockaddr_t *client;
Evan Hunt's avatar
Evan Hunt committed
405 406
	dns_messageid_t id;
	unsigned int depth;
Bob Halley's avatar
Bob Halley committed
407
};
Bob Halley's avatar
Bob Halley committed
408

Evan Hunt's avatar
Evan Hunt committed
409
#define FCTX_MAGIC	 ISC_MAGIC('F', '!', '!', '!')
410
#define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
411

Evan Hunt's avatar
Evan Hunt committed
412 413 414
#define FCTX_ATTR_HAVEANSWER   0x0001
#define FCTX_ATTR_GLUING       0x0002
#define FCTX_ATTR_ADDRWAIT     0x0004
415
#define FCTX_ATTR_SHUTTINGDOWN 0x0008 /* Bucket lock */
Evan Hunt's avatar
Evan Hunt committed
416 417 418 419 420
#define FCTX_ATTR_WANTCACHE    0x0010
#define FCTX_ATTR_WANTNCACHE   0x0020
#define FCTX_ATTR_NEEDEDNS0    0x0040
#define FCTX_ATTR_TRIEDFIND    0x0080
#define FCTX_ATTR_TRIEDALT     0x0100
421

Mark Andrews's avatar
Mark Andrews committed
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
#define HAVE_ANSWER(f) \
	((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_HAVEANSWER) != 0)
#define GLUING(f) \
	((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_GLUING) != 0)
#define ADDRWAIT(f) \
	((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_ADDRWAIT) != 0)
#define SHUTTINGDOWN(f) \
	((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_SHUTTINGDOWN) != 0)
#define WANTCACHE(f) \
	((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_WANTCACHE) != 0)
#define WANTNCACHE(f) \
	((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_WANTNCACHE) != 0)
#define NEEDEDNS0(f) \
	((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_NEEDEDNS0) != 0)
#define TRIEDFIND(f) \
	((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_TRIEDFIND) != 0)
#define TRIEDALT(f) \
	((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_TRIEDALT) != 0)

#define FCTX_ATTR_SET(f, a) atomic_fetch_or_release(&(f)->attributes, (a))
#define FCTX_ATTR_CLR(f, a) atomic_fetch_and_release(&(f)->attributes, ~(a))
Bob Halley's avatar
Bob Halley committed
443

444
typedef struct {
445
	dns_adbaddrinfo_t *addrinfo;
Evan Hunt's avatar
Evan Hunt committed
446
	fetchctx_t *fctx;
447 448
} dns_valarg_t;

Bob Halley's avatar
Bob Halley committed
449
struct dns_fetch {
450
	unsigned int magic;
Evan Hunt's avatar
Evan Hunt committed
451
	isc_mem_t *mctx;
452
	fetchctx_t *private;
Bob Halley's avatar
Bob Halley committed
453 454
};

Evan Hunt's avatar
Evan Hunt committed
455
#define DNS_FETCH_MAGIC	       ISC_MAGIC('F', 't', 'c', 'h')
456
#define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
Bob Halley's avatar
Bob Halley committed
457 458

typedef struct fctxbucket {
459 460 461 462
	isc_task_t *task;
	isc_mutex_t lock;
	ISC_LIST(fetchctx_t) fctxs;
	atomic_bool exiting;
Evan Hunt's avatar
Evan Hunt committed
463
	isc_mem_t *mctx;
Bob Halley's avatar
Bob Halley committed
464 465
} fctxbucket_t;

Evan Hunt's avatar
Evan Hunt committed
466 467
typedef struct fctxcount fctxcount_t;
struct fctxcount {
468
	dns_fixedname_t fdname;
Evan Hunt's avatar
Evan Hunt committed
469 470 471 472 473
	dns_name_t *domain;
	uint32_t count;
	uint32_t allowed;
	uint32_t dropped;
	isc_stdtime_t logged;
474
	ISC_LINK(fctxcount_t) link;
Evan Hunt's avatar
Evan Hunt committed
475 476 477
};

typedef struct zonebucket {
478
	isc_mutex_t lock;
Evan Hunt's avatar
Evan Hunt committed
479
	isc_mem_t *mctx;
480
	ISC_LIST(fctxcount_t) list;
Evan Hunt's avatar
Evan Hunt committed
481 482
} zonebucket_t;

483
typedef struct alternate {
484 485 486
	bool isaddress;
	union {
		isc_sockaddr_t addr;
Mark Andrews's avatar
Mark Andrews committed
487
		struct {
488
			dns_name_t name;
Evan Hunt's avatar
Evan Hunt committed
489
			in_port_t port;
Mark Andrews's avatar
Mark Andrews committed
490 491
		} _n;
	} _u;
492
	ISC_LINK(struct alternate) link;
493 494
} alternate_t;

Bob Halley's avatar
Bob Halley committed
495
struct dns_resolver {
Mark Andrews's avatar
Mark Andrews committed
496
	/* Unlocked. */
Evan Hunt's avatar
Evan Hunt committed
497 498 499 500 501 502 503 504 505 506 507
	unsigned int magic;
	isc_mem_t *mctx;
	isc_mutex_t lock;
	isc_mutex_t primelock;
	dns_rdataclass_t rdclass;
	isc_socketmgr_t *socketmgr;
	isc_timermgr_t *timermgr;
	isc_taskmgr_t *taskmgr;
	dns_view_t *view;
	bool frozen;
	unsigned int options;
508 509
	dns_dispatchmgr_t *dispatchmgr;
	dns_dispatchset_t *dispatches4;
Evan Hunt's avatar
Evan Hunt committed
510
	bool exclusivev4;
511
	dns_dispatchset_t *dispatches6;
Evan Hunt's avatar
Evan Hunt committed
512 513 514 515 516 517 518
	isc_dscp_t querydscp4;
	isc_dscp_t querydscp6;
	bool exclusivev6;
	unsigned int nbuckets;
	fctxbucket_t *buckets;
	zonebucket_t *dbuckets;
	uint32_t lame_ttl;
519 520
	ISC_LIST(alternate_t) alternates;
	uint16_t udpsize;
521
#if USE_ALGLOCK
522
	isc_rwlock_t alglock;
523
#endif /* if USE_ALGLOCK */
524 525
	dns_rbt_t *algorithms;
	dns_rbt_t *digests;
526
#if USE_MBSLOCK
527
	isc_rwlock_t mbslock;
528
#endif /* if USE_MBSLOCK */
Evan Hunt's avatar
Evan Hunt committed
529
	dns_rbt_t *mustbesecure;
530 531 532
	unsigned int spillatmax;
	unsigned int spillatmin;
	isc_timer_t *spillattimer;
Evan Hunt's avatar
Evan Hunt committed
533
	bool zero_no_soa_ttl;
534 535 536 537
	unsigned int query_timeout;
	unsigned int maxdepth;
	unsigned int maxqueries;
	isc_result_t quotaresp[2];
538

539
	/* Additions for serve-stale feature. */
540 541
	unsigned int retryinterval; /* in milliseconds */
	unsigned int nonbackofftries;
542

543
	/* Atomic */
Evan Hunt's avatar
Evan Hunt committed
544
	isc_refcount_t references;
545
	atomic_uint_fast32_t zspill; /* fetches-per-zone */
Evan Hunt's avatar
Evan Hunt committed
546
	atomic_bool exiting;
547
	atomic_bool priming;
548

Mark Andrews's avatar
Mark Andrews committed
549
	/* Locked by lock. */
550
	isc_eventlist_t whenshutdown;
Evan Hunt's avatar
Evan Hunt committed
551 552
	unsigned int activebuckets;
	unsigned int spillat; /* clients-per-query */
553

554
	dns_badcache_t *badcache; /* Bad cache. */
555

Mark Andrews's avatar
Mark Andrews committed
556
	/* Locked by primelock. */
557
	dns_fetch_t *primefetch;
558 559

	/* Atomic. */
560
	atomic_uint_fast32_t nfctx;
Bob Halley's avatar
Bob Halley committed
561 562
};

Evan Hunt's avatar
Evan Hunt committed
563
#define RES_MAGIC	    ISC_MAGIC('R', 'e', 's', '!')
564
#define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
Bob Halley's avatar
Bob Halley committed
565

566
/*%
567 568
 * Private addrinfo flags.  These must not conflict with DNS_FETCHOPT_NOEDNS0
 * (0x008) which we also use as an addrinfo flag.
569
 */
Evan Hunt's avatar
Evan Hunt committed
570
#define FCTX_ADDRINFO_MARK	0x00001
571
#define FCTX_ADDRINFO_FORWARDER 0x01000
Evan Hunt's avatar
Evan Hunt committed
572 573
#define FCTX_ADDRINFO_EDNSOK	0x04000
#define FCTX_ADDRINFO_NOCOOKIE	0x08000
574 575
#define FCTX_ADDRINFO_BADCOOKIE 0x10000

Evan Hunt's avatar
Evan Hunt committed
576
#define UNMARKED(a)    (((a)->flags & FCTX_ADDRINFO_MARK) == 0)
577
#define ISFORWARDER(a) (((a)->flags & FCTX_ADDRINFO_FORWARDER) != 0)
Evan Hunt's avatar
Evan Hunt committed
578 579 580
#define NOCOOKIE(a)    (((a)->flags & FCTX_ADDRINFO_NOCOOKIE) != 0)
#define EDNSOK(a)      (((a)->flags & FCTX_ADDRINFO_EDNSOK) != 0)
#define BADCOOKIE(a)   (((a)->flags & FCTX_ADDRINFO_BADCOOKIE) != 0)
Bob Halley's avatar
Bob Halley committed
581

582
#define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
583
#define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
584

585 586 587 588 589
#define NXDOMAIN_RESULT(r) \
	((r) == DNS_R_NXDOMAIN || (r) == DNS_R_NCACHENXDOMAIN)
#define NXRRSET_RESULT(r)                                      \
	((r) == DNS_R_NCACHENXRRSET || (r) == DNS_R_NXRRSET || \
	 (r) == DNS_R_HINTNXRRSET)
590

591
#ifdef ENABLE_AFL
592
bool dns_fuzzing_resolver = false;
593
void
594
dns_resolver_setfuzzing(void) {
595
	dns_fuzzing_resolver = true;
596
}
597
#endif /* ifdef ENABLE_AFL */
598

Evan Hunt's avatar
Evan Hunt committed
599 600 601 602
static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA";
static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
static const dns_name_t ip6_arpa = DNS_NAME_INITABSOLUTE(ip6_arpa_data,
							 ip6_arpa_offsets);
Witold Krecicki's avatar
Witold Krecicki committed
603

Evan Hunt's avatar
Evan Hunt committed
604 605
static unsigned char underscore_data[] = "\001_";
static unsigned char underscore_offsets[] = { 0 };
606 607 608
static const dns_name_t underscore_name =
	DNS_NAME_INITNONABSOLUTE(underscore_data, underscore_offsets);

Ondřej Surý's avatar
Ondřej Surý committed
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626
static void
destroy(dns_resolver_t *res);
static void
empty_bucket(dns_resolver_t *res);
static isc_result_t
resquery_send(resquery_t *query);
static void
resquery_response(isc_task_t *task, isc_event_t *event);
static void
resquery_connected(isc_task_t *task, isc_event_t *event);
static void
fctx_try(fetchctx_t *fctx, bool retrying, bool badcache);
static isc_result_t
fctx_minimize_qname(fetchctx_t *fctx);
static void
fctx_destroy(fetchctx_t *fctx);
static bool
fctx_unlink(fetchctx_t *fctx);
627 628 629 630 631
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 minttl,
		  dns_ttl_t maxttl, bool optout, bool secure,
		  dns_rdataset_t *ardataset, isc_result_t *eresultp);
Ondřej Surý's avatar
Ondřej Surý committed
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
static void
validated(isc_task_t *task, isc_event_t *event);
static bool
maybe_destroy(fetchctx_t *fctx, bool locked);
static void
add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason,
	badnstype_t badtype);
static inline isc_result_t
findnoqname(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
	    dns_name_t **noqname);
static void
fctx_increference(fetchctx_t *fctx);
static bool
fctx_decreference(fetchctx_t *fctx);
static void
resume_qmin(isc_task_t *task, isc_event_t *event);
648

649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
/*%
 * The structure and functions defined below implement the resolver
 * query (resquery) response handling logic.
 *
 * When a resolver query is sent and a response is received, the
 * resquery_response() event handler is run, which calls the rctx_*()
 * functions.  The respctx_t structure maintains state from function
 * to function.
 *
 * The call flow is described below:
 *
 * 1. resquery_response():
 *    - Initialize a respctx_t structure (rctx_respinit()).
 *    - Check for dispatcher failure (rctx_dispfail()).
 *    - Parse the response (rctx_parse()).
 *    - Log the response (rctx_logpacket()).
 *    - Check the parsed response for an OPT record and handle
 *      EDNS (rctx_opt(), rctx_edns()).
 *    - Check for a bad or lame server (rctx_badserver(), rctx_lameserver()).
 *    - Handle delegation-only zones (rctx_delonly_zone()).
 *    - If RCODE and ANCOUNT suggest this is a positive answer, and
 *      if so, call rctx_answer(): go to step 2.
 *    - If RCODE and NSCOUNT suggest this is a negative answer or a
 *      referral, call rctx_answer_none(): go to step 4.
 *    - Check the additional section for data that should be cached
 *      (rctx_additional()).
 *    - Clean up and finish by calling rctx_done(): go to step 5.
 *
 * 2. rctx_answer():
 *    - If the answer appears to be positive, call rctx_answer_positive():
 *      go to step 3.
 *    - If the response is a malformed delegation (with glue or NS records
 *      in the answer section), call rctx_answer_none(): go to step 4.
 *
 * 3. rctx_answer_positive():
 *    - Initialize the portions of respctx_t needed for processing an answer
 *      (rctx_answer_init()).
 *    - Scan the answer section to find records that are responsive to the
 *      query (rctx_answer_scan()).
 *    - For whichever type of response was found, call a separate routine
 *      to handle it: matching QNAME/QTYPE (rctx_answer_match()),
 *      CNAME (rctx_answer_cname()), covering DNAME (rctx_answer_dname()),
 *      or any records returned in response to a query of type ANY
 *      (rctx_answer_any()).
 *    - Scan the authority section for NS or other records that may be
 *      included with a positive answer (rctx_authority_scan()).
 *
 * 4. rctx_answer_none():
 *    - Determine whether this is an NXDOMAIN, NXRRSET, or referral.
 *    - If referral, set up the resolver to follow the delegation
 *      (rctx_referral()).
 *    - If NXDOMAIN/NXRRSET, scan the authority section for NS and SOA
 *      records included with a negative response (rctx_authority_negative()),
 *      then for DNSSEC proof of nonexistence (rctx_authority_dnssec()).
 *
 * 5. rctx_done():
 *    - Set up chasing of DS records if needed (rctx_chaseds()).
 *    - If the response wasn't intended for us, wait for another response
 *      from the dispatcher (rctx_next()).
 *    - If there is a problem with the responding server, set up another
 *      query to a different server (rctx_nextserver()).
 *    - If there is a problem that might be temporary or dependent on
 *      EDNS options, set up another query to the same server with changed
 *      options (rctx_resend()).
 *    - Shut down the fetch context.
 */

typedef struct respctx {
Evan Hunt's avatar
Evan Hunt committed
717
	isc_task_t *task;
718
	dns_dispatchevent_t *devent;
Evan Hunt's avatar
Evan Hunt committed
719 720 721 722 723 724 725 726 727 728 729 730 731
	resquery_t *query;
	fetchctx_t *fctx;
	isc_result_t result;
	unsigned int retryopts; /* updated options to pass to
				 * fctx_query() when resending */

	dns_rdatatype_t type; /* type being sought (set to
			       * ANY if qtype was SIG or RRSIG) */
	bool aa;	      /* authoritative answer? */
	dns_trust_t trust;    /* answer trust level */
	bool chaining;	      /* CNAME/DNAME processing? */
	bool next_server;     /* give up, try the next server
			       * */
732

733 734
	badnstype_t broken_type; /* type of name server problem
				  * */
735 736
	isc_result_t broken_server;

737 738
	bool get_nameservers; /* get a new NS rrset at
			       * zone cut? */
739 740 741 742 743
	bool resend;	      /* resend this query? */
	bool nextitem;	      /* invalid response; keep
			       * listening for the correct one */
	bool truncated;	      /* response was truncated */
	bool no_response;     /* no response was received */
744 745 746 747
	bool glue_in_answer;  /* glue may be in the answer
			       * section */
	bool ns_in_answer;    /* NS may be in the answer
			       * section */
748
	bool negative;	      /* is this a negative response? */
749

750
	isc_stdtime_t now; /* time info */
Evan Hunt's avatar
Evan Hunt committed
751 752
	isc_time_t tnow;
	isc_time_t *finish;
753 754

	unsigned int dname_labels;
755 756
	unsigned int domain_labels; /* range of permissible number
				     * of
757
				     * labels in a DNAME */
758

Evan Hunt's avatar
Evan Hunt committed
759
	dns_name_t *aname;	   /* answer name */
760
	dns_rdataset_t *ardataset; /* answer rdataset */
761

Evan Hunt's avatar
Evan Hunt committed
762
	dns_name_t *cname;	   /* CNAME name */
763
	dns_rdataset_t *crdataset; /* CNAME rdataset */
764

Evan Hunt's avatar
Evan Hunt committed
765
	dns_name_t *dname;	   /* DNAME name */
766
	dns_rdataset_t *drdataset; /* DNAME rdataset */
767

Evan Hunt's avatar
Evan Hunt committed
768
	dns_name_t *ns_name;	     /* NS name */
769
	dns_rdataset_t *ns_rdataset; /* NS rdataset */
770

771 772
	dns_name_t *soa_name; /* SOA name in a negative answer */
	dns_name_t *ds_name;  /* DS name in a negative answer */
773

774 775 776 777
	dns_name_t *found_name;	    /* invalid name in negative
				     * response */
	dns_rdatatype_t found_type; /* invalid type in negative
				     * response */
778

779
	dns_rdataset_t *opt; /* OPT rdataset */
780 781
} respctx_t;

Ondřej Surý's avatar
Ondřej Surý committed
782 783 784
static void
rctx_respinit(isc_task_t *task, dns_dispatchevent_t *devent, resquery_t *query,
	      fetchctx_t *fctx, respctx_t *rctx);
785

Ondřej Surý's avatar
Ondřej Surý committed
786 787
static void
rctx_answer_init(respctx_t *rctx);
788

Ondřej Surý's avatar
Ondřej Surý committed
789 790
static void
rctx_answer_scan(respctx_t *rctx);
791

Ondřej Surý's avatar
Ondřej Surý committed
792 793
static void
rctx_authority_positive(respctx_t *rctx);
794

Ondřej Surý's avatar
Ondřej Surý committed
795 796
static isc_result_t
rctx_answer_any(respctx_t *rctx);
797

Ondřej Surý's avatar
Ondřej Surý committed
798 799
static isc_result_t
rctx_answer_match(respctx_t *rctx);
800

Ondřej Surý's avatar
Ondřej Surý committed
801 802
static isc_result_t
rctx_answer_cname(respctx_t *rctx);
803

Ondřej Surý's avatar
Ondřej Surý committed
804 805
static isc_result_t
rctx_answer_dname(respctx_t *rctx);
806

Ondřej Surý's avatar
Ondřej Surý committed
807 808
static isc_result_t
rctx_answer_positive(respctx_t *rctx);
809

Ondřej Surý's avatar
Ondřej Surý committed
810 811
static isc_result_t
rctx_authority_negative(respctx_t *rctx);
812

Ondřej Surý's avatar
Ondřej Surý committed
813 814
static isc_result_t
rctx_authority_dnssec(respctx_t *rctx);
815

Ondřej Surý's avatar
Ondřej Surý committed
816 817
static void
rctx_additional(respctx_t *rctx);
818

Ondřej Surý's avatar
Ondřej Surý committed
819 820
static isc_result_t
rctx_referral(respctx_t *rctx);
821

Ondřej Surý's avatar
Ondřej Surý committed
822 823
static isc_result_t
rctx_answer_none(respctx_t *rctx);
824

Ondřej Surý's avatar
Ondřej Surý committed
825 826 827
static void
rctx_nextserver(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo,
		isc_result_t result);
828

Ondřej Surý's avatar
Ondřej Surý committed
829 830
static void
rctx_resend(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo);
831

Ondřej Surý's avatar
Ondřej Surý committed
832 833
static void
rctx_next(respctx_t *rctx);
834

Ondřej Surý's avatar
Ondřej Surý committed
835 836
static void
rctx_chaseds(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo, isc_result_t result);
837

Ondřej Surý's avatar
Ondřej Surý committed
838 839
static void
rctx_done(respctx_t *rctx, isc_result_t result);
840

Ondřej Surý's avatar
Ondřej Surý committed
841 842
static void
rctx_logpacket(respctx_t *rctx);
843

Ondřej Surý's avatar
Ondřej Surý committed
844 845
static void
rctx_opt(respctx_t *rctx);
846

Ondřej Surý's avatar
Ondřej Surý committed
847 848
static void
rctx_edns(respctx_t *rctx);
849

Ondřej Surý's avatar
Ondřej Surý committed
850 851
static isc_result_t
rctx_parse(respctx_t *rctx);
852

Ondřej Surý's avatar
Ondřej Surý committed
853 854
static isc_result_t
rctx_badserver(respctx_t *rctx, isc_result_t result);
855

Ondřej Surý's avatar
Ondřej Surý committed
856 857
static isc_result_t
rctx_answer(respctx_t *rctx);
858

Ondřej Surý's avatar
Ondřej Surý committed
859 860
static isc_result_t
rctx_lameserver(respctx_t *rctx);
861

Ondřej Surý's avatar
Ondřej Surý committed
862 863
static isc_result_t
rctx_dispfail(respctx_t *rctx);
864

Ondřej Surý's avatar
Ondřej Surý committed
865 866
static void
rctx_delonly_zone(respctx_t *rctx);
867

Ondřej Surý's avatar
Ondřej Surý committed
868 869
static void
rctx_ncache(respctx_t *rctx);
870

871 872 873 874
/*%
 * Increment resolver-related statistics counters.
 */
static inline void
Evan Hunt's avatar
Evan Hunt committed
875
inc_stats(dns_resolver_t *res, isc_statscounter_t counter) {
876
	if (res->view->resstats != NULL) {
877
		isc_stats_increment(res->view->resstats, counter);
878
	}
879 880
}

881
static inline void
Evan Hunt's avatar
Evan Hunt committed
882
dec_stats(dns_resolver_t *res, isc_statscounter_t counter) {
883
	if (res->view->resstats != NULL) {
884
		isc_stats_decrement(res->view->resstats, counter);
885
	}
886 887
}

888 889
static isc_result_t
valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
Mark Andrews's avatar
Mark Andrews committed
890 891
	  dns_rdatatype_t type, dns_rdataset_t *rdataset,
	  dns_rdataset_t *sigrdataset, unsigned int valoptions,
Evan Hunt's avatar
Evan Hunt committed
892
	  isc_task_t *task) {
Mark Andrews's avatar
Mark Andrews committed
893
	dns_validator_t *validator = NULL;
Evan Hunt's avatar
Evan Hunt committed
894 895
	dns_valarg_t *valarg;
	isc_result_t result;
Mark Andrews's avatar
Mark Andrews committed
896

897
	valarg = isc_mem_get(fctx->mctx, sizeof(*valarg));
Mark Andrews's avatar
Mark Andrews committed
898 899 900 901

	valarg->fctx = fctx;
	valarg->addrinfo = addrinfo;

902
	if (!ISC_LIST_EMPTY(fctx->validators)) {
903
		valoptions |= DNS_VALIDATOR_DEFER;
904
	} else {
905
		valoptions &= ~DNS_VALIDATOR_DEFER;
906
	}
Mark Andrews's avatar
Mark Andrews committed
907 908

	result = dns_validator_create(fctx->res->view, name, type, rdataset,
909 910
				      sigrdataset, fctx->rmessage, valoptions,
				      task, validated, valarg, &validator);
Mark Andrews's avatar
Mark Andrews committed
911
	if (result == ISC_R_SUCCESS) {
912
		inc_stats(fctx->res, dns_resstatscounter_val);
Mark Andrews's avatar
Mark Andrews committed
913 914
		if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
			INSIST(fctx->validator == NULL);
915
			fctx->validator = validator;
Mark Andrews's avatar
Mark Andrews committed
916 917
		}
		ISC_LIST_APPEND(fctx->validators, validator, link);
918
	} else {
919
		isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
920
	}
Mark Andrews's avatar
Mark Andrews committed
921
	return (result);
922
}
Bob Halley's avatar
Bob Halley committed
923

924
static bool
Evan Hunt's avatar
Evan Hunt committed
925 926
rrsig_fromchildzone(fetchctx_t *fctx, dns_rdataset_t *rdataset) {
	dns_namereln_t namereln;
927
	dns_rdata_rrsig_t rrsig;
Evan Hunt's avatar
Evan Hunt committed
928 929 930 931
	dns_rdata_t rdata = DNS_RDATA_INIT;
	int order;
	isc_result_t result;
	unsigned int labels;
932

933
	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
Evan Hunt's avatar
Evan Hunt committed
934 935
	     result = dns_rdataset_next(rdataset))
	{
936 937 938 939
		dns_rdataset_current(rdataset, &rdata);
		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
		RUNTIME_CHECK(result == ISC_R_SUCCESS);
		namereln = dns_name_fullcompare(&rrsig.signer, &fctx->domain,
Automatic Updater's avatar
Automatic Updater committed
940
						&order, &labels);
941
		if (namereln == dns_namereln_subdomain) {
942
			return (true);
943
		}
944 945
		dns_rdata_reset(&rdata);
	}
946
	return (false);
947 948
}

949
static bool
Evan Hunt's avatar
Evan Hunt committed
950 951 952
fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
	dns_name_t *name;
	dns_name_t *domain = &fctx->domain;
Mark Andrews's avatar
Mark Andrews committed
953 954
	dns_rdataset_t *rdataset;
	dns_rdatatype_t type;
Evan Hunt's avatar
Evan Hunt committed
955 956
	isc_result_t result;
	bool keep_auth = false;
Mark Andrews's avatar
Mark Andrews committed
957

958
	if (message->rcode == dns_rcode_nxdomain) {
959
		return (false);
960
	}
Mark Andrews's avatar
Mark Andrews committed
961 962

	/*
963 964 965 966
	 * A DS RRset can appear anywhere in a zone, even for a delegation-only
	 * zone.  So a response to an explicit query for this type should be
	 * excluded from delegation-only fixup.
	 *
967
	 * SOA, NS, and DNSKEY can only exist at a zone apex, so a positive
968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990
	 * response to a query for these types can never violate the
	 * delegation-only assumption: if the query name is below a
	 * zone cut, the response should normally be a referral, which should
	 * be accepted; if the query name is below a zone cut but the server
	 * happens to have authority for the zone of the query name, the
	 * response is a (non-referral) answer.  But this does not violate
	 * delegation-only because the query name must be in a different zone
	 * due to the "apex-only" nature of these types.  Note that if the
	 * remote server happens to have authority for a child zone of a
	 * delegation-only zone, we may still incorrectly "fix" the response
	 * with NXDOMAIN for queries for other types.  Unfortunately it's
	 * generally impossible to differentiate this case from violation of
	 * the delegation-only assumption.  Once the resolver learns the
	 * correct zone cut, possibly via a separate query for an "apex-only"
	 * type, queries for other types will be resolved correctly.
	 *
	 * A query for type ANY will be accepted if it hits an exceptional
	 * type above in the answer section as it should be from a child
	 * zone.
	 *
	 * Also accept answers with RRSIG records from the child zone.
	 * Direct queries for RRSIG records should not be answered from
	 * the parent zone.
Mark Andrews's avatar
Mark Andrews committed
991
	 */
992

Mark Andrews's avatar
Mark Andrews committed
993
	if (message->counts[DNS_SECTION_ANSWER] != 0 &&
994
	    (fctx->type == dns_rdatatype_ns || fctx->type == dns_rdatatype_ds ||