adb.c 95.9 KB
Newer Older
Michael Graff's avatar
Michael Graff committed
1
/*
Bob Halley's avatar
Bob Halley committed
2
 * Copyright (C) 1999, 2000  Internet Software Consortium.
Michael Graff's avatar
Michael Graff committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 * 
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

18
19
20
21
/*
 * Implementation notes
 * --------------------
 *
22
 * In finds, if task == NULL, no events will be generated, and no events
23
 * have been sent.  If task != NULL but taskaction == NULL, an event has been
Bob Halley's avatar
Bob Halley committed
24
 * posted but not yet freed.  If neither are NULL, no event was posted.
25
26
27
 *
 */

28
29
30
31
32
/*
 * After we have cleaned all buckets, dump the database contents.
 */
#define DUMP_ADB_AFTER_CLEANING

Michael Graff's avatar
Michael Graff committed
33
34
#include <config.h>

Mark Andrews's avatar
Mark Andrews committed
35
#include <limits.h>
Michael Graff's avatar
Michael Graff committed
36
37
38
#include <stdio.h>
#include <string.h>

Michael Graff's avatar
Michael Graff committed
39
#include <isc/assertions.h>
Michael Graff's avatar
Michael Graff committed
40
#include <isc/condition.h>
Michael Graff's avatar
Michael Graff committed
41
#include <isc/event.h>
42
#include <isc/log.h>
43
#include <isc/magic.h>
44
#include <isc/mutex.h>
45
#include <isc/mutexblock.h>
Michael Graff's avatar
Michael Graff committed
46
#include <isc/random.h>
Michael Graff's avatar
Michael Graff committed
47
#include <isc/timer.h>
Michael Graff's avatar
Michael Graff committed
48
#include <isc/util.h>
Michael Graff's avatar
Michael Graff committed
49

Bob Halley's avatar
Bob Halley committed
50
#include <dns/a6.h>
Michael Graff's avatar
Michael Graff committed
51
#include <dns/adb.h>
Michael Graff's avatar
Michael Graff committed
52
#include <dns/db.h>
53
#include <dns/events.h>
Michael Graff's avatar
fix    
Michael Graff committed
54
#include <dns/fixedname.h>
55
#include <dns/log.h>
56
#include <dns/name.h>
Michael Graff's avatar
Michael Graff committed
57
58
#include <dns/rdata.h>
#include <dns/rdataset.h>
Michael Graff's avatar
fix    
Michael Graff committed
59
60
#include <dns/resolver.h>
#include <dns/types.h>
Michael Graff's avatar
Michael Graff committed
61
#include <dns/view.h>
62

63
64
65
66
67
68
69
70
71
72
#define DNS_ADB_MAGIC		  0x44616462	/* Dadb. */
#define DNS_ADB_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
#define DNS_ADBNAME_MAGIC	  0x6164624e	/* adbN. */
#define DNS_ADBNAME_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
#define DNS_ADBNAMEHOOK_MAGIC	  0x61644e48	/* adNH. */
#define DNS_ADBNAMEHOOK_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
#define DNS_ADBZONEINFO_MAGIC	  0x6164625a	/* adbZ. */
#define DNS_ADBZONEINFO_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBZONEINFO_MAGIC)
#define DNS_ADBENTRY_MAGIC	  0x61646245	/* adbE. */
#define DNS_ADBENTRY_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
Michael Graff's avatar
Michael Graff committed
73
#define DNS_ADBFETCH_MAGIC	  0x61644634	/* adF4. */
Michael Graff's avatar
Michael Graff committed
74
#define DNS_ADBFETCH_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
Bob Halley's avatar
Bob Halley committed
75
76
#define DNS_ADBFETCH6_MAGIC	  0x61644636	/* adF6. */
#define DNS_ADBFETCH6_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
Michael Graff's avatar
Michael Graff committed
77

78
/*
Bob Halley's avatar
Bob Halley committed
79
80
81
82
83
 * The number of buckets needs to be a prime (for good hashing).
 *
 * XXXRTH  How many buckets do we need?
 *
 * This value must be coordinated with CLEAN_SECONDS (below).
84
 */
85
86
87
88
#define NBUCKETS	       1009	/* how many buckets for names/addrs */

/*
 * For type 3 negative cache entries, we will remember that the address is
89
90
91
 * broken for this long.  XXXMLG This is also used for actual addresses, too.
 * The intent is to keep us from constantly asking about A/A6/AAAA records
 * if the zone has extremely low TTLs.
92
 */
93
#define ADB_CACHE_MINIMUM	10	/* seconds */
94

Bob Halley's avatar
Bob Halley committed
95
/*
96
 * Clean CLEAN_BUCKETS buckets every CLEAN_SECONDS.
Bob Halley's avatar
Bob Halley committed
97
 */
98
99
100
101
102
103
104
#define CLEAN_PERIOD		3600 /* one pass through every N seconds */
#define CLEAN_BUCKETS		((NBUCKETS / CLEAN_PERIOD) + 0.5)
#if CLEAN_BUCKET < 1
#undef CLEAN_BUCKETS
#define CLEAN_BUCKETS 1
#endif
#define CLEAN_SECONDS		(CLEAN_PERIOD * CLEAN_BUCKETS / NBUCKETS)
105
106
107
108
#if CLEAN_SECONDS < 1
#undef CLEAN_SECONDS
#define CLEAN_SECONDS		1
#endif
Michael Graff's avatar
Michael Graff committed
109

110
111
#define FREE_ITEMS		64	/* free count for memory pools */
#define FILL_COUNT		16	/* fill count for memory pools */
112

Michael Graff's avatar
Michael Graff committed
113
114
#define DNS_ADB_INVALIDBUCKET (-1)	/* invalid bucket address */

115
typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
Michael Graff's avatar
Michael Graff committed
116
typedef struct dns_adbnamehook dns_adbnamehook_t;
Michael Graff's avatar
Michael Graff committed
117
typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
Michael Graff's avatar
Michael Graff committed
118
typedef struct dns_adbzoneinfo dns_adbzoneinfo_t;
119
typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
Michael Graff's avatar
Michael Graff committed
120
typedef struct dns_adbfetch dns_adbfetch_t;
Bob Halley's avatar
Bob Halley committed
121
typedef struct dns_adbfetch6 dns_adbfetch6_t;
Michael Graff's avatar
Michael Graff committed
122
123

struct dns_adb {
Michael Graff's avatar
Michael Graff committed
124
125
126
	unsigned int			magic;

	isc_mutex_t			lock;
127
	isc_mutex_t			ilock;
Michael Graff's avatar
Michael Graff committed
128
	isc_mem_t		       *mctx;
Michael Graff's avatar
Michael Graff committed
129
	dns_view_t		       *view;
Michael Graff's avatar
fix    
Michael Graff committed
130
	isc_timermgr_t		       *timermgr;
Michael Graff's avatar
Michael Graff committed
131
	isc_timer_t		       *timer;
Michael Graff's avatar
fix    
Michael Graff committed
132
	isc_taskmgr_t		       *taskmgr;
Michael Graff's avatar
Michael Graff committed
133
	isc_task_t		       *task;
Michael Graff's avatar
Michael Graff committed
134

Michael Graff's avatar
Michael Graff committed
135
	isc_interval_t			tick_interval;
136
	int				next_cleanbucket;
Michael Graff's avatar
Michael Graff committed
137

138
139
	unsigned int			irefcnt;
	unsigned int			erefcnt;
Michael Graff's avatar
Michael Graff committed
140

141
	isc_mutex_t			mplock;
Michael Graff's avatar
Michael Graff committed
142
143
144
145
	isc_mempool_t		       *nmp;	/* dns_adbname_t */
	isc_mempool_t		       *nhmp;	/* dns_adbnamehook_t */
	isc_mempool_t		       *zimp;	/* dns_adbzoneinfo_t */
	isc_mempool_t		       *emp;	/* dns_adbentry_t */
146
	isc_mempool_t		       *ahmp;	/* dns_adbfind_t */
Michael Graff's avatar
Michael Graff committed
147
	isc_mempool_t		       *aimp;	/* dns_adbaddrinfo_t */
Michael Graff's avatar
Michael Graff committed
148
	isc_mempool_t		       *afmp;	/* dns_adbfetch_t */
Bob Halley's avatar
Bob Halley committed
149
	isc_mempool_t		       *af6mp;	/* dns_adbfetch6_t */
Michael Graff's avatar
Michael Graff committed
150

Michael Graff's avatar
Michael Graff committed
151
152
	isc_random_t			rand;

153
154
	/*
	 * Bucketized locks and lists for names.
Bob Halley's avatar
Bob Halley committed
155
156
	 *
	 * XXXRTH  Have a per-bucket structure that contains all of these?
157
	 */
158
159
160
161
	dns_adbnamelist_t		names[NBUCKETS];
	isc_mutex_t			namelocks[NBUCKETS];
	isc_boolean_t			name_sd[NBUCKETS];
	unsigned int			name_refcnt[NBUCKETS];
162
163
164

	/*
	 * Bucketized locks for entries.
Bob Halley's avatar
Bob Halley committed
165
166
	 *
	 * XXXRTH  Have a per-bucket structure that contains all of these?
167
	 */
168
169
	dns_adbentrylist_t		entries[NBUCKETS];
	isc_mutex_t			entrylocks[NBUCKETS];
170
171
	isc_boolean_t			entry_sd[NBUCKETS];
	unsigned int			entry_refcnt[NBUCKETS];
172
173
174
175
176

	isc_event_t			cevent;
	isc_boolean_t			cevent_sent;
	isc_boolean_t			shutting_down;
	isc_eventlist_t			whenshutdown;
Michael Graff's avatar
Michael Graff committed
177
178
};

Bob Halley's avatar
Bob Halley committed
179
180
181
182
/*
 * XXXMLG  Document these structures.
 */

Michael Graff's avatar
Michael Graff committed
183
184
struct dns_adbname {
	unsigned int			magic;
185
	dns_name_t			name;
186
	dns_adb_t		       *adb;
Michael Graff's avatar
Michael Graff committed
187
	unsigned int			partial_result;
188
	unsigned int			flags;
Michael Graff's avatar
Michael Graff committed
189
	int				lock_bucket;
190
191
	dns_name_t			target;
	isc_stdtime_t			expire_target;
Michael Graff's avatar
Michael Graff committed
192
193
	isc_stdtime_t			expire_v4;
	isc_stdtime_t			expire_v6;
Bob Halley's avatar
Bob Halley committed
194
	unsigned int			chains;
Michael Graff's avatar
Michael Graff committed
195
196
	dns_adbnamehooklist_t		v4;
	dns_adbnamehooklist_t		v6;
197
198
	dns_adbfetch_t		       *fetch_a;
	dns_adbfetch_t		       *fetch_aaaa;
Bob Halley's avatar
Bob Halley committed
199
	ISC_LIST(dns_adbfetch6_t)	fetches_a6;
Bob Halley's avatar
Bob Halley committed
200
	dns_adbfindlist_t		finds;
201
	ISC_LINK(dns_adbname_t)		plink;
Michael Graff's avatar
Michael Graff committed
202
203
};

Michael Graff's avatar
Michael Graff committed
204
205
206
207
208
209
210
211
struct dns_adbfetch {
	unsigned int			magic;
	dns_adbnamehook_t	       *namehook;
	dns_adbentry_t		       *entry;
	dns_fetch_t		       *fetch;
	dns_rdataset_t			rdataset;
};

Bob Halley's avatar
Bob Halley committed
212
213
struct dns_adbfetch6 {
	unsigned int			magic;
214
	unsigned int			flags;
Bob Halley's avatar
Bob Halley committed
215
216
217
218
219
220
221
222
	dns_adbnamehook_t	       *namehook;
	dns_adbentry_t		       *entry;
	dns_fetch_t		       *fetch;
	dns_rdataset_t			rdataset;
	dns_a6context_t			a6ctx;
	ISC_LINK(dns_adbfetch6_t)	plink;
};

Michael Graff's avatar
Michael Graff committed
223
224
225
226
227
228
229
230
231
/*
 * dns_adbnamehook_t
 *
 * This is a small widget that dangles off a dns_adbname_t.  It contains a
 * pointer to the address information about this host, and a link to the next
 * namehook that will contain the next address this host has.
 */
struct dns_adbnamehook {
	unsigned int			magic;
232
	dns_adbentry_t		       *entry;
233
	ISC_LINK(dns_adbnamehook_t)	plink;
Michael Graff's avatar
Michael Graff committed
234
235
};

Michael Graff's avatar
Michael Graff committed
236
237
238
239
240
241
242
243
244
245
/*
 * dns_adbzoneinfo_t
 *
 * This is a small widget that holds zone-specific information about an
 * address.  Currently limited to lameness, but could just as easily be
 * extended to other types of information about zones.
 */
struct dns_adbzoneinfo {
	unsigned int			magic;

Michael Graff's avatar
Michael Graff committed
246
	dns_name_t			zone;
247
	isc_stdtime_t			lame_timer;
Michael Graff's avatar
Michael Graff committed
248

249
	ISC_LINK(dns_adbzoneinfo_t)	plink;
Michael Graff's avatar
Michael Graff committed
250
251
252
253
254
255
};

/*
 * An address entry.  It holds quite a bit of information about addresses,
 * including edns state, rtt, and of course the address of the host.
 */
Michael Graff's avatar
Michael Graff committed
256
struct dns_adbentry {
Michael Graff's avatar
Michael Graff committed
257
258
	unsigned int			magic;

259
	int				lock_bucket;
Michael Graff's avatar
Michael Graff committed
260
	unsigned int			refcnt;
Michael Graff's avatar
Michael Graff committed
261
262

	unsigned int			flags;
Michael Graff's avatar
Michael Graff committed
263
264
	int				edns_level;	/* must be int! */
	int				goodness;	/* bad < 0 <= good */
Michael Graff's avatar
Michael Graff committed
265
266
	unsigned int			srtt;
	isc_sockaddr_t			sockaddr;
267
	isc_stdtime_t			expires;
268
	isc_stdtime_t			avoid_bitstring;
Michael Graff's avatar
Michael Graff committed
269
270

	ISC_LIST(dns_adbzoneinfo_t)	zoneinfo;
271
	ISC_LINK(dns_adbentry_t)	plink;
Michael Graff's avatar
Michael Graff committed
272
273
};

Michael Graff's avatar
Michael Graff committed
274
/*
275
276
 * Internal functions (and prototypes).
 */
277
static inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *);
Michael Graff's avatar
Michael Graff committed
278
279
280
281
static inline void free_adbname(dns_adb_t *, dns_adbname_t **);
static inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *,
						 dns_adbentry_t *);
static inline void free_adbnamehook(dns_adb_t *, dns_adbnamehook_t **);
282
static inline dns_adbzoneinfo_t *new_adbzoneinfo(dns_adb_t *, dns_name_t *);
Michael Graff's avatar
Michael Graff committed
283
284
285
static inline void free_adbzoneinfo(dns_adb_t *, dns_adbzoneinfo_t **);
static inline dns_adbentry_t *new_adbentry(dns_adb_t *);
static inline void free_adbentry(dns_adb_t *, dns_adbentry_t **);
286
287
static inline dns_adbfind_t *new_adbfind(dns_adb_t *);
static inline void free_adbfind(dns_adb_t *, dns_adbfind_t **);
Michael Graff's avatar
Michael Graff committed
288
289
static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *,
						 dns_adbentry_t *);
Michael Graff's avatar
Michael Graff committed
290
291
static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *);
static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
Michael Graff's avatar
Michael Graff committed
292
293
static inline dns_adbfetch6_t *new_adbfetch6(dns_adb_t *, dns_adbname_t *,
					     dns_a6context_t *);
Bob Halley's avatar
Bob Halley committed
294
static inline void free_adbfetch6(dns_adb_t *, dns_adbfetch6_t **);
Michael Graff's avatar
Michael Graff committed
295
static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
296
						unsigned int, int *);
Michael Graff's avatar
Michael Graff committed
297
298
static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
						  isc_sockaddr_t *, int *);
299
static void dump_adb(dns_adb_t *, FILE *);
Michael Graff's avatar
Michael Graff committed
300
301
static void print_dns_name(FILE *, dns_name_t *);
static void print_namehook_list(FILE *, dns_adbname_t *);
302
static void print_find_list(FILE *, dns_adbname_t *);
303
static void print_fetch_list(FILE *, dns_adbname_t *);
304
static inline void dec_adb_irefcnt(dns_adb_t *);
305
static inline void inc_adb_erefcnt(dns_adb_t *, isc_boolean_t);
Michael Graff's avatar
Michael Graff committed
306
static inline void dec_adb_erefcnt(dns_adb_t *, isc_boolean_t);
Michael Graff's avatar
Michael Graff committed
307
308
309
310
static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
				    isc_boolean_t);
static inline void dec_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
				    isc_boolean_t);
311
static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
Michael Graff's avatar
Michael Graff committed
312
static void clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
313
static void clean_target(dns_adb_t *, dns_name_t *);
314
315
static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
				unsigned int);
Michael Graff's avatar
Michael Graff committed
316
static void check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
317
static void cancel_fetches_at_name(dns_adbname_t *);
318
static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
319
				dns_rdatatype_t);
320
321
static isc_result_t fetch_name_v4(dns_adbname_t *, isc_boolean_t);
static isc_result_t fetch_name_aaaa(dns_adbname_t *);
322
static isc_result_t fetch_name_a6(dns_adbname_t *, isc_boolean_t);
Michael Graff's avatar
Michael Graff committed
323
static inline void check_exit(dns_adb_t *);
Michael Graff's avatar
Michael Graff committed
324
static void timer_cleanup(isc_task_t *, isc_event_t *);
325
static void destroy(dns_adb_t *);
Michael Graff's avatar
Michael Graff committed
326
static void shutdown_names(dns_adb_t *);
327
static void shutdown_entries(dns_adb_t *);
Michael Graff's avatar
Michael Graff committed
328
329
static inline void link_name(dns_adb_t *, int, dns_adbname_t *);
static inline void unlink_name(dns_adb_t *, dns_adbname_t *);
330
331
static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *);
static inline void unlink_entry(dns_adb_t *, dns_adbentry_t *);
Michael Graff's avatar
Michael Graff committed
332
333
static void kill_name(dns_adbname_t **, isc_eventtype_t);
static void fetch_callback_a6(isc_task_t *, isc_event_t *);
334
static isc_result_t dbfind_a6(dns_adbname_t *, isc_stdtime_t);
Michael Graff's avatar
Michael Graff committed
335

336
337
338
339
340
/*
 * MUST NOT overlap DNS_ADBFIND_* flags!
 */
#define FIND_EVENT_SENT		0x40000000
#define FIND_EVENT_FREED	0x80000000
341
342
#define FIND_EVENTSENT(h)	(((h)->flags & FIND_EVENT_SENT) != 0)
#define FIND_EVENTFREED(h)	(((h)->flags & FIND_EVENT_FREED) != 0)
343

344
345
#define NAME_NEEDS_POKE		0x80000000
#define NAME_IS_DEAD		0x40000000
346
347
#define NAME_HINT_OK		DNS_ADBFIND_HINTOK
#define NAME_GLUE_OK		DNS_ADBFIND_GLUEOK
348
349
#define NAME_DEAD(n)		(((n)->flags & NAME_IS_DEAD) != 0)
#define NAME_NEEDSPOKE(n)	(((n)->flags & NAME_NEEDS_POKE) != 0)
350
351
#define NAME_HINTOK(n)		(((n)->flags & NAME_HINT_OK) != 0)
#define NAME_GLUEOK(n)		(((n)->flags & NAME_GLUE_OK) != 0)
352

353
354
355
356
357
358
359
/*
 * To the name, address classes are all that really exist.  If it has a
 * V6 address it doesn't care if it came from an A6 chain or an AAAA query.
 */
#define NAME_HAS_V4(n)		(!ISC_LIST_EMPTY((n)->v4))
#define NAME_HAS_V6(n)		(!ISC_LIST_EMPTY((n)->v6))
#define NAME_HAS_ADDRS(n)	(NAME_HAS_V4(n) || NAME_HAS_V6(n))
Michael Graff's avatar
Michael Graff committed
360

361
362
363
364
365
/*
 * Fetches are broken out into A, AAAA, and A6 types.  In some cases,
 * however, it makes more sense to test for a particular class of fetches,
 * like V4 or V6 above.
 */
366
367
368
369
370
371
#define NAME_FETCH_A(n)		((n)->fetch_a != NULL)
#define NAME_FETCH_AAAA(n)	((n)->fetch_aaaa != NULL)
#define NAME_FETCH_A6(n)	(!ISC_LIST_EMPTY((n)->fetches_a6))
#define NAME_FETCH_V4(n)	(NAME_FETCH_A(n))
#define NAME_FETCH_V6(n)	(NAME_FETCH_AAAA(n) || NAME_FETCH_A6(n))
#define NAME_FETCH(n)		(NAME_FETCH_V4(n) || NAME_FETCH_V6(n))
372

373
374
375
376
377
/*
 * Was this fetch started using the hints database?
 * Was this the initial fetch for the A6 record?  If so, we might want to
 * start AAAA queries if it fails.
 */
378
#define FETCH_FIRST_A6		0x80000000
379
380
381
382
383
384
385
#define FETCH_FIRSTA6(f)	(((f)->flags & FETCH_FIRST_A6) != 0)

/*
 * Find options and tests to see if there are addresses on the list.
 */
#define FIND_WANTEVENT(fn)	(((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
#define FIND_WANTEMPTYEVENT(fn)	(((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
Bob Halley's avatar
Bob Halley committed
386
387
#define FIND_AVOIDFETCHES(fn)	(((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
				 != 0)
Bob Halley's avatar
Bob Halley committed
388
389
#define FIND_STARTATROOT(fn)	(((fn)->options & DNS_ADBFIND_STARTATROOT) \
				 != 0)
390
391
#define FIND_HINTOK(fn)		(((fn)->options & DNS_ADBFIND_HINTOK) != 0)
#define FIND_GLUEOK(fn)		(((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
392
#define FIND_HAS_ADDRS(fn)	(!ISC_LIST_EMPTY((fn)->list))
Michael Graff's avatar
Michael Graff committed
393
#define FIND_RETURNLAME(fn)	(((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
Bob Halley's avatar
Bob Halley committed
394

395
396
397
398
399
400
401
/*
 * These are currently used on simple unsigned ints, so they are
 * not really associated with any particular type.
 */
#define WANT_INET(x)		(((x) & DNS_ADBFIND_INET) != 0)
#define WANT_INET6(x)		(((x) & DNS_ADBFIND_INET6) != 0)

402
403
#define EXPIRE_OK(exp, now)	((exp == INT_MAX) || (exp < now))

404
405
406
407
408
409
410
411
412
/*
 * Find out if the flags on a name (nf) indicate if it is a hint or
 * glue, and compare this to the appropriate bits set in o, to see if
 * this is ok.
 */
#define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0))
#define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0))
#define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o))

413
414
415
416
#define ENTER_LEVEL		50
#define EXIT_LEVEL		ENTER_LEVEL
#define CLEAN_LEVEL		100
#define DEF_LEVEL		5
417
#define NCACHE_LEVEL		20
418

419
420
#define NCACHE_RESULT(r)	((r) == DNS_R_NCACHENXDOMAIN || \
				 (r) == DNS_R_NCACHENXRRSET)
Bob Halley's avatar
Bob Halley committed
421
422
#define AUTH_NX(r)		((r) == DNS_R_NXDOMAIN || \
				 (r) == DNS_R_NXRRSET)
423
424


425
426
427
428
429
430
431
432
433
434
435
436
static void
DP(int level, char *format, ...)
{
	va_list args;

	va_start(args, format);
	isc_log_vwrite(dns_lctx,
		       DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
		       ISC_LOG_DEBUG(level), format, args);
	va_end(args);
}

437
438
/*
 * Requires the adbname bucket be locked and that no entry buckets be locked.
439
440
 *
 * This code handles A and AAAA rdatasets only.
441
442
 */
static isc_result_t
443
444
import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
		isc_stdtime_t now)
445
446
{
	isc_result_t result;
Michael Graff's avatar
Michael Graff committed
447
	dns_adb_t *adb;
448
449
450
	dns_adbnamehook_t *nh;
	dns_rdata_t rdata;
	struct in_addr ina;
451
	struct in6_addr in6a;
452
453
454
455
	isc_sockaddr_t sockaddr;
	dns_adbentry_t *foundentry;  /* NO CLEAN UP! */
	int addr_bucket;
	isc_boolean_t new_addresses_added;
456
	dns_rdatatype_t rdtype;
457
	unsigned int findoptions;
458

Michael Graff's avatar
Michael Graff committed
459
460
461
462
	INSIST(DNS_ADBNAME_VALID(adbname));
	adb = adbname->adb;
	INSIST(DNS_ADB_VALID(adb));

463
464
	rdtype = rdataset->type;
	INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));
465
466
	if (rdtype == dns_rdatatype_a)
		findoptions = DNS_ADBFIND_INET;
467
	else
468
		findoptions = DNS_ADBFIND_INET6;
Michael Graff's avatar
Michael Graff committed
469

470
471
	addr_bucket = DNS_ADB_INVALIDBUCKET;
	new_addresses_added = ISC_FALSE;
472

473
	nh = NULL;
474
475
476
	result = dns_rdataset_first(rdataset);
	while (result == ISC_R_SUCCESS) {
		dns_rdataset_current(rdataset, &rdata);
477
478
479
480
		if (rdtype == dns_rdatatype_a) {
			INSIST(rdata.length == 4);
			memcpy(&ina.s_addr, rdata.data, 4);
			isc_sockaddr_fromin(&sockaddr, &ina, 53);
481
		} else {
482
			INSIST(rdata.length == 16);
Mark Andrews's avatar
Mark Andrews committed
483
			memcpy(in6a.s6_addr, rdata.data, 16);
484
			isc_sockaddr_fromin6(&sockaddr, &in6a, 53);
485
486
		}

487
488
489
490
491
492
493
494
495
496
497
498
499
500
		if (IN6_IS_ADDR_V4MAPPED(&sockaddr.type.sin6.sin6_addr)
		    || IN6_IS_ADDR_V4COMPAT(&sockaddr.type.sin6.sin6_addr)) {
			DP(1, "Ignoring IPv6 mapped IPv4 address");
			goto next;
		}

		INSIST(nh == NULL);
		nh = new_adbnamehook(adb, NULL);
		if (nh == NULL) {
			adbname->partial_result |= findoptions;
			result = ISC_R_NOMEMORY;
			goto fail;
		}

Michael Graff's avatar
Michael Graff committed
501
502
503
504
505
506
		foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket);
		if (foundentry == NULL) {
			dns_adbentry_t *entry;

			entry = new_adbentry(adb);
			if (entry == NULL) {
507
				adbname->partial_result |= findoptions;
Michael Graff's avatar
Michael Graff committed
508
509
510
511
512
513
514
515
516
				result = ISC_R_NOMEMORY;
				goto fail;
			}

			entry->sockaddr = sockaddr;
			entry->refcnt = 1;

			nh->entry = entry;

517
			link_entry(adb, addr_bucket, entry);
Michael Graff's avatar
Michael Graff committed
518
519
520
521
522
523
		} else {
			foundentry->refcnt++;
			nh->entry = foundentry;
		}

		new_addresses_added = ISC_TRUE;
524
525
526
527
		if (rdtype == dns_rdatatype_a)
			ISC_LIST_APPEND(adbname->v4, nh, plink);
		else
			ISC_LIST_APPEND(adbname->v6, nh, plink);
Michael Graff's avatar
Michael Graff committed
528
529
		nh = NULL;

530
531
	next:

Michael Graff's avatar
Michael Graff committed
532
533
534
535
536
537
538
539
540
541
		result = dns_rdataset_next(rdataset);
	}

 fail:
	if (nh != NULL)
		free_adbnamehook(adb, &nh);

	if (addr_bucket != DNS_ADB_INVALIDBUCKET)
		UNLOCK(&adb->entrylocks[addr_bucket]);

542
	rdataset->ttl = ISC_MAX(rdataset->ttl, ADB_CACHE_MINIMUM);
543

544
545
546
547
548
549
550
551
552
553
554
	if (rdtype == dns_rdatatype_a) {
		DP(NCACHE_LEVEL, "expire_v4 set to MIN(%u,%u) import_rdataset",
		   adbname->expire_v4, now + rdataset->ttl);
		adbname->expire_v4 = ISC_MIN(adbname->expire_v4,
					     now + rdataset->ttl);
	} else {
		DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) import_rdataset",
		   adbname->expire_v6, now + rdataset->ttl);
		adbname->expire_v6 = ISC_MIN(adbname->expire_v6,
					     now + rdataset->ttl);
	}
Michael Graff's avatar
Michael Graff committed
555

556
	if (new_addresses_added) {
557
558
559
560
		/*
		 * Lie a little here.  This is more or less so code that cares
		 * can find out if any new information was added or not.
		 */
Michael Graff's avatar
Michael Graff committed
561
		return (ISC_R_SUCCESS);
562
	}
563
564
565
566

	return (result);
}

567
static void
568
import_a6(dns_a6context_t *a6ctx)
569
570
571
572
573
574
575
576
{
	dns_adbname_t *name;
	dns_adb_t *adb;
	dns_adbnamehook_t *nh;
	dns_adbentry_t *foundentry;  /* NO CLEAN UP! */
	int addr_bucket;
	isc_sockaddr_t sockaddr;

577
	name = a6ctx->arg;
578
579
580
581
	INSIST(DNS_ADBNAME_VALID(name));
	adb = name->adb;
	INSIST(DNS_ADB_VALID(adb));

Bob Halley's avatar
Bob Halley committed
582
	addr_bucket = DNS_ADB_INVALIDBUCKET;
583

584
	DP(ENTER_LEVEL, "ENTER: import_a6() name %p", name);
585
	
586
587
588
589
590
591
	nh = new_adbnamehook(adb, NULL);
	if (nh == NULL) {
		name->partial_result |= DNS_ADBFIND_INET6; /* clear for AAAA */
		goto fail;
	}

592
	isc_sockaddr_fromin6(&sockaddr, &a6ctx->in6addr, 53);
593

594
595
596
597
598
599
	if (IN6_IS_ADDR_V4MAPPED(&sockaddr.type.sin6.sin6_addr)
	    || IN6_IS_ADDR_V4COMPAT(&sockaddr.type.sin6.sin6_addr)) {
		DP(1, "Ignoring IPv6 mapped IPv4 address");
		goto fail;
	}

600
601
602
603
604
605
606
607
608
609
610
611
	foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket);
	if (foundentry == NULL) {
		dns_adbentry_t *entry;
		entry = new_adbentry(adb);
		if (entry == NULL) {
			name->partial_result |= DNS_ADBFIND_INET6;
			goto fail;
		}

		entry->sockaddr = sockaddr;
		entry->refcnt = 1;
		nh->entry = entry;
612
		link_entry(adb, addr_bucket, entry);
613
614
615
616
617
618
619
620
	} else {
		foundentry->refcnt++;
		nh->entry = foundentry;
	}

	ISC_LIST_APPEND(name->v6, nh, plink);
	nh = NULL;

621
622
 fail:
	DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) in import_v6",
Bob Halley's avatar
Bob Halley committed
623
624
625
626
627
	   name->expire_v6, a6ctx->expiration);
	name->expire_v6 = ISC_MIN(name->expire_v6, a6ctx->expiration);

	name->flags |= NAME_NEEDS_POKE;

628
629
630
631
632
633
634
	if (nh != NULL)
		free_adbnamehook(adb, &nh);

	if (addr_bucket != DNS_ADB_INVALIDBUCKET)
		UNLOCK(&adb->entrylocks[addr_bucket]);
}

Michael Graff's avatar
Michael Graff committed
635
636
637
638
/*
 * Requires the name's bucket be locked.
 */
static void
Michael Graff's avatar
Michael Graff committed
639
kill_name(dns_adbname_t **n, isc_eventtype_t ev)
Michael Graff's avatar
Michael Graff committed
640
641
{
	dns_adbname_t *name;
Michael Graff's avatar
Michael Graff committed
642
	dns_adb_t *adb;
Michael Graff's avatar
Michael Graff committed
643
644
645
646
647

	INSIST(n != NULL);
	name = *n;
	*n = NULL;
	INSIST(DNS_ADBNAME_VALID(name));
Michael Graff's avatar
Michael Graff committed
648
649
	adb = name->adb;
	INSIST(DNS_ADB_VALID(adb));
Michael Graff's avatar
Michael Graff committed
650

651
	DP(DEF_LEVEL, "killing name %p", name);
652

653
654
655
656
	/*
	 * If we're dead already, just check to see if we should go
	 * away now or not.
	 */
657
	if (NAME_DEAD(name) && !NAME_FETCH(name)) {
658
659
660
661
662
663
664
665
666
		unlink_name(adb, name);
		free_adbname(adb, &name);
		return;
	}

	/*
	 * Clean up the name's various lists.  These two are destructive
	 * in that they will always empty the list.
	 */
667
	clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK);
Michael Graff's avatar
Michael Graff committed
668
669
	clean_namehooks(adb, &name->v4);
	clean_namehooks(adb, &name->v6);
670
	clean_target(adb, &name->target);
Michael Graff's avatar
Michael Graff committed
671

672
673
674
675
	/*
	 * If fetches are running, cancel them.  If none are running, we can
	 * just kill the name here.
	 */
676
	if (!NAME_FETCH(name)) {
Michael Graff's avatar
Michael Graff committed
677
678
679
		unlink_name(adb, name);
		free_adbname(adb, &name);
	} else {
680
		name->flags |= NAME_IS_DEAD;
681
		cancel_fetches_at_name(name);
Michael Graff's avatar
Michael Graff committed
682
683
684
	}
}

Michael Graff's avatar
Michael Graff committed
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
/*
 * Requires the name's bucket be locked and no entry buckets be locked.
 */
static void
check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now)
{
	dns_adb_t *adb;

	INSIST(DNS_ADBNAME_VALID(name));
	adb = name->adb;
	INSIST(DNS_ADB_VALID(adb));

	/*
	 * Check to see if we need to remove the v4 addresses
	 */
700
	if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) {
701
		if (NAME_HAS_V4(name)) {
702
703
			DP(DEF_LEVEL, "expiring v4 for name %p", name);
			clean_namehooks(adb, &name->v4);
704
			name->partial_result &= ~DNS_ADBFIND_INET;
705
		}
706
		name->expire_v4 = INT_MAX;
707
708
	}

Michael Graff's avatar
Michael Graff committed
709
710
711
	/*
	 * Check to see if we need to remove the v6 addresses
	 */
712
	if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) {
713
		if (NAME_HAS_V6(name)) {
714
715
			DP(DEF_LEVEL, "expiring v6 for name %p", name);
			clean_namehooks(adb, &name->v6);
716
			name->partial_result &= ~DNS_ADBFIND_INET6;
717
		}
718
		name->expire_v6 = INT_MAX;
719
	}
720
721
722
723
724
725
726
727

	/*
	 * Check to see if we need to remove the alias target.
	 */
	if (EXPIRE_OK(name->expire_target, now)) {
		clean_target(adb, &name->target);
		name->expire_target = INT_MAX;
	}
Michael Graff's avatar
Michael Graff committed
728
729
}

Michael Graff's avatar
Michael Graff committed
730
731
732
733
734
735
736
737
/*
 * Requires the name's bucket be locked.
 */
static inline void
link_name(dns_adb_t *adb, int bucket, dns_adbname_t *name)
{
	INSIST(name->lock_bucket == DNS_ADB_INVALIDBUCKET);

738
	ISC_LIST_PREPEND(adb->names[bucket], name, plink);
Michael Graff's avatar
Michael Graff committed
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
	name->lock_bucket = bucket;
	adb->name_refcnt[bucket]++;
}

/*
 * Requires the name's bucket be locked.
 */
static inline void
unlink_name(dns_adb_t *adb, dns_adbname_t *name)
{
	int bucket;

	bucket = name->lock_bucket;
	INSIST(bucket != DNS_ADB_INVALIDBUCKET);

754
	ISC_LIST_UNLINK(adb->names[bucket], name, plink);
Michael Graff's avatar
Michael Graff committed
755
756
757
	name->lock_bucket = DNS_ADB_INVALIDBUCKET;
	INSIST(adb->name_refcnt[bucket] > 0);
	adb->name_refcnt[bucket]--;
758
759
	if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0)
		dec_adb_irefcnt(adb);
Michael Graff's avatar
Michael Graff committed
760
}
761

762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
/*
 * Requires the entry's bucket be locked.
 */
static inline void
link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry)
{
	ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
	entry->lock_bucket = bucket;
	adb->entry_refcnt[bucket]++;
}

/*
 * Requires the entry's bucket be locked.
 */
static inline void
unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry)
{
	int bucket;

	bucket = entry->lock_bucket;
	INSIST(bucket != DNS_ADB_INVALIDBUCKET);

	ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
	entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
	INSIST(adb->entry_refcnt[bucket] > 0);
	adb->entry_refcnt[bucket]--;
788
789
	if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0)
		dec_adb_irefcnt(adb);
790
791
}

792
793
794
795
796
797
798
799
800
801
802
static inline void
violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want)
{
	if (isc_mutex_trylock(want) != ISC_R_SUCCESS) {
		UNLOCK(have);
		LOCK(want);
		LOCK(have);
	}
}

/*
803
804
 * The ADB _MUST_ be locked before calling.  Also, exit conditions must be
 * checked after calling this function.
805
806
 */
static void
Michael Graff's avatar
Michael Graff committed
807
shutdown_names(dns_adb_t *adb)
808
809
810
{
	int bucket;
	dns_adbname_t *name;
Michael Graff's avatar
Michael Graff committed
811
	dns_adbname_t *next_name;
812

813
	for (bucket = 0 ; bucket < NBUCKETS ; bucket++) {
814
815
816
817
		LOCK(&adb->namelocks[bucket]);
		adb->name_sd[bucket] = ISC_TRUE;

		name = ISC_LIST_HEAD(adb->names[bucket]);
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
		if (name == NULL) {
			/*
			 * This bucket has no names.  We must decrement the
			 * irefcnt ourselves, since it will not be
			 * automatically triggered by a name being unlinked.
			 */
			dec_adb_irefcnt(adb);
		} else {
			/*
			 * Run through the list.  For each name, clean up finds
			 * found there, and cancel any fetches running.  When
			 * all the fetches are canceled, the name will destroy
			 * itself.
			 */
			while (name != NULL) {
				next_name = ISC_LIST_NEXT(name, plink);
				kill_name(&name, DNS_EVENT_ADBSHUTDOWN);
				name = next_name;
			}
837
838
839
840
841
842
		}

		UNLOCK(&adb->namelocks[bucket]);
	}
}

843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
/*
 * The ADB _MUST_ be locked before calling.  Also, exit conditions must be
 * checked after calling this function.
 */
static void
shutdown_entries(dns_adb_t *adb)
{
	int bucket;
	dns_adbentry_t *entry;
	dns_adbentry_t *next_entry;

	for (bucket = 0 ; bucket < NBUCKETS ; bucket++) {
		LOCK(&adb->entrylocks[bucket]);
		adb->entry_sd[bucket] = ISC_TRUE;

		entry = ISC_LIST_HEAD(adb->entries[bucket]);
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
		if (entry == NULL) {
			/*
			 * This bucket has no entries.  We must decrement the
			 * irefcnt ourselves, since it will not be
			 * automatically triggered by an entry being unlinked.
			 */
			dec_adb_irefcnt(adb);
		} else {
			/*
			 * Run through the list.  Cleanup any entries not
			 * associated with names, and which are not in use.
			 */
			while (entry != NULL) {
				next_entry = ISC_LIST_NEXT(entry, plink);
				if (entry->refcnt == 0 &&
				    entry->expires != 0) {
					unlink_entry(adb, entry);
					free_adbentry(adb, &entry);
				}
				entry = next_entry;
879
880
881
			}
		}

882
		UNLOCK(&adb->entrylocks[bucket]);
883
884
885
	}
}

Michael Graff's avatar
Michael Graff committed
886
887
888
889
/*
 * Name bucket must be locked
 */
static void
890
cancel_fetches_at_name(dns_adbname_t *name)
Michael Graff's avatar
Michael Graff committed
891
{
892
893
	dns_adbfetch6_t *fetch6;

894
	if (NAME_FETCH_A(name))
895
896
	    dns_resolver_cancelfetch(name->fetch_a->fetch);
				     
Michael Graff's avatar
Michael Graff committed
897

898
	if (NAME_FETCH_AAAA(name))
899
900
	    dns_resolver_cancelfetch(name->fetch_aaaa->fetch);
				     
901
902
903

	fetch6 = ISC_LIST_HEAD(name->fetches_a6);
	while (fetch6 != NULL) {
904
		dns_resolver_cancelfetch(fetch6->fetch);
905
906
		fetch6 = ISC_LIST_NEXT(fetch6, plink);
	}
Michael Graff's avatar
Michael Graff committed
907
908
}

Michael Graff's avatar
Michael Graff committed
909
910
911
/*
 * Assumes the name bucket is locked.
 */
912
static void
Michael Graff's avatar
Michael Graff committed
913
clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks)
914
915
916
917
918
919
{
	dns_adbentry_t *entry;
	dns_adbnamehook_t *namehook;
	int addr_bucket;

	addr_bucket = DNS_ADB_INVALIDBUCKET;
Michael Graff's avatar
Michael Graff committed
920
	namehook = ISC_LIST_HEAD(*namehooks);
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
	while (namehook != NULL) {
		INSIST(DNS_ADBNAMEHOOK_VALID(namehook));

		/*
		 * Clean up the entry if needed.
		 */
		entry = namehook->entry;
		if (entry != NULL) {
			INSIST(DNS_ADBENTRY_VALID(entry));

			if (addr_bucket != entry->lock_bucket) {
				if (addr_bucket != DNS_ADB_INVALIDBUCKET)
					UNLOCK(&adb->entrylocks[addr_bucket]);
				addr_bucket = entry->lock_bucket;
				LOCK(&adb->entrylocks[addr_bucket]);
			}

			dec_entry_refcnt(adb, entry, ISC_FALSE);
		}

		/*
		 * Free the namehook
		 */
		namehook->entry = NULL;
945
		ISC_LIST_UNLINK(*namehooks, namehook, plink);
946
947
		free_adbnamehook(adb, &namehook);

Michael Graff's avatar
Michael Graff committed
948
		namehook = ISC_LIST_HEAD(*namehooks);
949
950
951
952
953
954
	}

	if (addr_bucket != DNS_ADB_INVALIDBUCKET)
		UNLOCK(&adb->entrylocks[addr_bucket]);
}

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
static void
clean_target(dns_adb_t *adb, dns_name_t *target) {
	if (dns_name_countlabels(target) > 0) {
		dns_name_free(target, adb->mctx);
		dns_name_init(target, NULL);
	}
}

static isc_result_t
set_target(dns_adb_t *adb, dns_name_t *name, dns_name_t *fname,
	   dns_rdataset_t *rdataset, dns_name_t *target)
{
	isc_result_t result;
	dns_namereln_t namereln;
	unsigned int nlabels, nbits;
	int order;
	dns_rdata_t rdata;
	isc_region_t r;
	dns_name_t tname;
	dns_fixedname_t fixed1, fixed2;
	dns_name_t *prefix, *new_target;

977
978
	REQUIRE(dns_name_countlabels(target) == 0);

979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
	if (rdataset->type == dns_rdatatype_cname) {
		/*
		 * Copy the CNAME's target into the target name.
		 */
		result = dns_rdataset_first(rdataset);
		if (result != ISC_R_SUCCESS)
			return (result);
		dns_rdataset_current(rdataset, &rdata);
		r.base = rdata.data;
		r.length = rdata.length;
		dns_name_init(&tname, NULL);
		dns_name_fromregion(&tname, &r);
		result = dns_name_dup(&tname, adb->mctx, target);
		if (result != ISC_R_SUCCESS)
			return (result);
	} else {
		INSIST(rdataset->type == dns_rdatatype_dname);
		namereln = dns_name_fullcompare(name, fname, &order,
						&nlabels, &nbits);
		INSIST(namereln == dns_namereln_subdomain);
		/*
		 * Get the target name of the DNAME.
For faster browsing, not all history is shown. View entire blame