adb.c 89.3 KB
Newer Older
Michael Graff's avatar
Michael Graff committed
1
/*
Mark Andrews's avatar
Mark Andrews committed
2
 * Copyright (C) 2004, 2005  Internet Systems Consortium, Inc. ("ISC")
Mark Andrews's avatar
Mark Andrews committed
3
 * Copyright (C) 1999-2003  Internet Software Consortium.
4
 *
Michael Graff's avatar
Michael Graff committed
5
6
7
 * 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.
8
 *
Mark Andrews's avatar
Mark Andrews committed
9
10
11
12
13
14
15
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS.  IN NO EVENT SHALL ISC 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.
Michael Graff's avatar
Michael Graff committed
16
17
 */

18
/* $Id: adb.c,v 1.227 2006/08/30 23:09:18 marka Exp $ */
David Lawrence's avatar
David Lawrence committed
19

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

29
/*%
30
31
 * After we have cleaned all buckets, dump the database contents.
 */
32
#if 0
33
#define DUMP_ADB_AFTER_CLEANING
34
#endif
35

Michael Graff's avatar
Michael Graff committed
36
37
#include <config.h>

Mark Andrews's avatar
Mark Andrews committed
38
#include <limits.h>
39

40
#include <isc/mutexblock.h>
41
#include <isc/netaddr.h>
Michael Graff's avatar
Michael Graff committed
42
#include <isc/random.h>
43
#include <isc/string.h>		/* Required for HP/UX (and others?) */
44
#include <isc/task.h>
Michael Graff's avatar
Michael Graff committed
45
#include <isc/timer.h>
Michael Graff's avatar
Michael Graff committed
46
#include <isc/util.h>
Michael Graff's avatar
Michael Graff committed
47

Michael Graff's avatar
Michael Graff committed
48
#include <dns/adb.h>
Michael Graff's avatar
Michael Graff committed
49
#include <dns/db.h>
50
#include <dns/events.h>
51
#include <dns/log.h>
Michael Graff's avatar
Michael Graff committed
52
53
#include <dns/rdata.h>
#include <dns/rdataset.h>
54
#include <dns/rdatastruct.h>
55
#include <dns/rdatatype.h>
Michael Graff's avatar
fix    
Michael Graff committed
56
#include <dns/resolver.h>
57
#include <dns/result.h>
58

59
#define DNS_ADB_MAGIC		  ISC_MAGIC('D', 'a', 'd', 'b')
60
#define DNS_ADB_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
61
#define DNS_ADBNAME_MAGIC	  ISC_MAGIC('a', 'd', 'b', 'N')
62
#define DNS_ADBNAME_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
63
#define DNS_ADBNAMEHOOK_MAGIC	  ISC_MAGIC('a', 'd', 'N', 'H')
64
#define DNS_ADBNAMEHOOK_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
65
66
#define DNS_ADBLAMEINFO_MAGIC	  ISC_MAGIC('a', 'd', 'b', 'Z')
#define DNS_ADBLAMEINFO_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBLAMEINFO_MAGIC)
67
#define DNS_ADBENTRY_MAGIC	  ISC_MAGIC('a', 'd', 'b', 'E')
68
#define DNS_ADBENTRY_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
69
#define DNS_ADBFETCH_MAGIC	  ISC_MAGIC('a', 'd', 'F', '4')
Michael Graff's avatar
Michael Graff committed
70
#define DNS_ADBFETCH_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
71
#define DNS_ADBFETCH6_MAGIC	  ISC_MAGIC('a', 'd', 'F', '6')
Bob Halley's avatar
Bob Halley committed
72
#define DNS_ADBFETCH6_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
Michael Graff's avatar
Michael Graff committed
73

74
/*! 
Bob Halley's avatar
Bob Halley committed
75
76
77
 * The number of buckets needs to be a prime (for good hashing).
 *
 * XXXRTH  How many buckets do we need?
78
 */
79
#define NBUCKETS	       1009	/*%< how many buckets for names/addrs */
80

81
/*!
82
 * For type 3 negative cache entries, we will remember that the address is
83
 * broken for this long.  XXXMLG This is also used for actual addresses, too.
84
 * The intent is to keep us from constantly asking about A/AAAA records
85
 * if the zone has extremely low TTLs.
86
 */
87
88
89
#define ADB_CACHE_MINIMUM	10	/*%< seconds */
#define ADB_CACHE_MAXIMUM	86400	/*%< seconds (86400 = 24 hours) */
#define ADB_ENTRY_WINDOW	1800	/*%< seconds */
90

91
/*%
92
93
 * Wake up every CLEAN_SECONDS and clean CLEAN_BUCKETS buckets, so that all
 * buckets are cleaned in CLEAN_PERIOD seconds.
Bob Halley's avatar
Bob Halley committed
94
 */
95
#define CLEAN_PERIOD		3600
96
/*% See #CLEAN_PERIOD */
97
#define CLEAN_SECONDS		30
98
/*% See #CLEAN_PERIOD */
99
#define CLEAN_BUCKETS		((NBUCKETS * CLEAN_SECONDS) / CLEAN_PERIOD)
Michael Graff's avatar
Michael Graff committed
100

101
102
#define FREE_ITEMS		64	/*%< free count for memory pools */
#define FILL_COUNT		16	/*%< fill count for memory pools */
103

104
#define DNS_ADB_INVALIDBUCKET (-1)	/*%< invalid bucket address */
Michael Graff's avatar
Michael Graff committed
105

106
#define DNS_ADB_MINADBSIZE	(1024*1024)	/*%< 1 Megabyte */
107

108
typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
Michael Graff's avatar
Michael Graff committed
109
typedef struct dns_adbnamehook dns_adbnamehook_t;
Michael Graff's avatar
Michael Graff committed
110
typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
111
typedef struct dns_adblameinfo dns_adblameinfo_t;
112
typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
Michael Graff's avatar
Michael Graff committed
113
typedef struct dns_adbfetch dns_adbfetch_t;
Bob Halley's avatar
Bob Halley committed
114
typedef struct dns_adbfetch6 dns_adbfetch6_t;
Michael Graff's avatar
Michael Graff committed
115

116
/*% dns adb structure */
Michael Graff's avatar
Michael Graff committed
117
struct dns_adb {
Michael Graff's avatar
Michael Graff committed
118
119
120
	unsigned int			magic;

	isc_mutex_t			lock;
121
	isc_mutex_t			reflock; /*%< Covers irefcnt, erefcnt */
Michael Graff's avatar
Michael Graff committed
122
	isc_mem_t		       *mctx;
Michael Graff's avatar
Michael Graff committed
123
	dns_view_t		       *view;
Michael Graff's avatar
fix    
Michael Graff committed
124
	isc_timermgr_t		       *timermgr;
Michael Graff's avatar
Michael Graff committed
125
	isc_timer_t		       *timer;
Michael Graff's avatar
fix    
Michael Graff committed
126
	isc_taskmgr_t		       *taskmgr;
Michael Graff's avatar
Michael Graff committed
127
	isc_task_t		       *task;
128
	isc_boolean_t			overmem;
Michael Graff's avatar
Michael Graff committed
129

Michael Graff's avatar
Michael Graff committed
130
	isc_interval_t			tick_interval;
131
	int				next_cleanbucket;
Michael Graff's avatar
Michael Graff committed
132

133
134
	unsigned int			irefcnt;
	unsigned int			erefcnt;
Michael Graff's avatar
Michael Graff committed
135

136
	isc_mutex_t			mplock;
137
138
	isc_mempool_t		       *nmp;	/*%< dns_adbname_t */
	isc_mempool_t		       *nhmp;	/*%< dns_adbnamehook_t */
139
	isc_mempool_t		       *limp;	/*%< dns_adblameinfo_t */
140
141
142
143
144
145
	isc_mempool_t		       *emp;	/*%< dns_adbentry_t */
	isc_mempool_t		       *ahmp;	/*%< dns_adbfind_t */
	isc_mempool_t		       *aimp;	/*%< dns_adbaddrinfo_t */
	isc_mempool_t		       *afmp;	/*%< dns_adbfetch_t */

	/*!
146
	 * Bucketized locks and lists for names.
Bob Halley's avatar
Bob Halley committed
147
148
	 *
	 * XXXRTH  Have a per-bucket structure that contains all of these?
149
	 */
150
	dns_adbnamelist_t		names[NBUCKETS];
151
	/*% See dns_adbnamelist_t */
152
	isc_mutex_t			namelocks[NBUCKETS];
153
	/*% See dns_adbnamelist_t */
154
	isc_boolean_t			name_sd[NBUCKETS];
155
	/*% See dns_adbnamelist_t */
156
	unsigned int			name_refcnt[NBUCKETS];
157

158
	/*!
159
	 * Bucketized locks for entries.
Bob Halley's avatar
Bob Halley committed
160
161
	 *
	 * XXXRTH  Have a per-bucket structure that contains all of these?
162
	 */
163
164
	dns_adbentrylist_t		entries[NBUCKETS];
	isc_mutex_t			entrylocks[NBUCKETS];
165
	isc_boolean_t			entry_sd[NBUCKETS]; /*%< shutting down */
166
	unsigned int			entry_refcnt[NBUCKETS];
167
168
169
170
171

	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
172
173
};

Bob Halley's avatar
Bob Halley committed
174
175
176
177
/*
 * XXXMLG  Document these structures.
 */

178
/*% dns_adbname structure */
Michael Graff's avatar
Michael Graff committed
179
180
struct dns_adbname {
	unsigned int			magic;
181
	dns_name_t			name;
182
	dns_adb_t		       *adb;
Michael Graff's avatar
Michael Graff committed
183
	unsigned int			partial_result;
184
	unsigned int			flags;
Michael Graff's avatar
Michael Graff committed
185
	int				lock_bucket;
186
187
	dns_name_t			target;
	isc_stdtime_t			expire_target;
Michael Graff's avatar
Michael Graff committed
188
189
	isc_stdtime_t			expire_v4;
	isc_stdtime_t			expire_v6;
Bob Halley's avatar
Bob Halley committed
190
	unsigned int			chains;
Michael Graff's avatar
Michael Graff committed
191
192
	dns_adbnamehooklist_t		v4;
	dns_adbnamehooklist_t		v6;
193
194
	dns_adbfetch_t		       *fetch_a;
	dns_adbfetch_t		       *fetch_aaaa;
Michael Graff's avatar
Michael Graff committed
195
196
	unsigned int			fetch_err;
	unsigned int			fetch6_err;
Bob Halley's avatar
Bob Halley committed
197
	dns_adbfindlist_t		finds;
198
	ISC_LINK(dns_adbname_t)		plink;
Michael Graff's avatar
Michael Graff committed
199
200
};

201
/*% The adbfetch structure */
Michael Graff's avatar
Michael Graff committed
202
203
204
205
206
207
208
209
struct dns_adbfetch {
	unsigned int			magic;
	dns_adbnamehook_t	       *namehook;
	dns_adbentry_t		       *entry;
	dns_fetch_t		       *fetch;
	dns_rdataset_t			rdataset;
};

210
/*%
Michael Graff's avatar
Michael Graff committed
211
212
213
214
215
216
 * 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;
217
	dns_adbentry_t		       *entry;
218
	ISC_LINK(dns_adbnamehook_t)	plink;
Michael Graff's avatar
Michael Graff committed
219
220
};

221
/*%
222
 * This is a small widget that holds qname-specific information about an
Michael Graff's avatar
Michael Graff committed
223
224
225
 * address.  Currently limited to lameness, but could just as easily be
 * extended to other types of information about zones.
 */
226
struct dns_adblameinfo {
Michael Graff's avatar
Michael Graff committed
227
228
	unsigned int			magic;

229
230
	dns_name_t			qname;
	dns_rdatatype_t			qtype;
231
	isc_stdtime_t			lame_timer;
Michael Graff's avatar
Michael Graff committed
232

233
	ISC_LINK(dns_adblameinfo_t)	plink;
Michael Graff's avatar
Michael Graff committed
234
235
};

236
/*%
Michael Graff's avatar
Michael Graff committed
237
 * An address entry.  It holds quite a bit of information about addresses,
238
239
 * including edns state (in "flags"), rtt, and of course the address of
 * the host.
Michael Graff's avatar
Michael Graff committed
240
 */
Michael Graff's avatar
Michael Graff committed
241
struct dns_adbentry {
Michael Graff's avatar
Michael Graff committed
242
243
	unsigned int			magic;

244
	int				lock_bucket;
Michael Graff's avatar
Michael Graff committed
245
	unsigned int			refcnt;
Michael Graff's avatar
Michael Graff committed
246
247
248
249

	unsigned int			flags;
	unsigned int			srtt;
	isc_sockaddr_t			sockaddr;
Mark Andrews's avatar
Mark Andrews committed
250

251
	isc_stdtime_t			expires;
252
	/*%<
Andreas Gustafsson's avatar
Andreas Gustafsson committed
253
254
255
256
257
258
	 * A nonzero 'expires' field indicates that the entry should
	 * persist until that time.  This allows entries found
	 * using dns_adb_findaddrinfo() to persist for a limited time
	 * even though they are not necessarily associated with a
	 * name.
	 */
Michael Graff's avatar
Michael Graff committed
259

260
	ISC_LIST(dns_adblameinfo_t)	lameinfo;
261
	ISC_LINK(dns_adbentry_t)	plink;
Michael Graff's avatar
Michael Graff committed
262
263
};

Michael Graff's avatar
Michael Graff committed
264
/*
265
266
 * Internal functions (and prototypes).
 */
267
static inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *);
Michael Graff's avatar
Michael Graff committed
268
269
270
271
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 **);
272
273
274
static inline dns_adblameinfo_t *new_adblameinfo(dns_adb_t *, dns_name_t *,
						 dns_rdatatype_t);
static inline void free_adblameinfo(dns_adb_t *, dns_adblameinfo_t **);
Michael Graff's avatar
Michael Graff committed
275
276
static inline dns_adbentry_t *new_adbentry(dns_adb_t *);
static inline void free_adbentry(dns_adb_t *, dns_adbentry_t **);
277
static inline dns_adbfind_t *new_adbfind(dns_adb_t *);
Michael Graff's avatar
Michael Graff committed
278
static inline isc_boolean_t free_adbfind(dns_adb_t *, dns_adbfind_t **);
279
280
static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *,
						 in_port_t);
Michael Graff's avatar
Michael Graff committed
281
282
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
283
static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
284
						unsigned int, int *);
Michael Graff's avatar
Michael Graff committed
285
286
static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
						  isc_sockaddr_t *, int *);
287
static void dump_adb(dns_adb_t *, FILE *, isc_boolean_t debug, isc_stdtime_t);
Michael Graff's avatar
Michael Graff committed
288
static void print_dns_name(FILE *, dns_name_t *);
289
290
static void print_namehook_list(FILE *, const char *legend,
				dns_adbnamehooklist_t *list,
291
292
				isc_boolean_t debug,
				isc_stdtime_t now);
293
static void print_find_list(FILE *, dns_adbname_t *);
294
static void print_fetch_list(FILE *, dns_adbname_t *);
Michael Graff's avatar
Michael Graff committed
295
296
static inline isc_boolean_t dec_adb_irefcnt(dns_adb_t *);
static inline void inc_adb_irefcnt(dns_adb_t *);
297
static inline void inc_adb_erefcnt(dns_adb_t *);
Michael Graff's avatar
Michael Graff committed
298
299
static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
				    isc_boolean_t);
Michael Graff's avatar
Michael Graff committed
300
static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
Mark Andrews's avatar
Mark Andrews committed
301
					     isc_boolean_t);
302
static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
Michael Graff's avatar
Michael Graff committed
303
static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
304
static void clean_target(dns_adb_t *, dns_name_t *);
305
306
static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
				unsigned int);
Michael Graff's avatar
Michael Graff committed
307
static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t,
Mark Andrews's avatar
Mark Andrews committed
308
					    isc_boolean_t);
309
static void cancel_fetches_at_name(dns_adbname_t *);
310
static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
311
				dns_rdatatype_t);
312
313
static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
			       dns_rdatatype_t);
Michael Graff's avatar
Michael Graff committed
314
static inline void check_exit(dns_adb_t *);
Michael Graff's avatar
Michael Graff committed
315
static void timer_cleanup(isc_task_t *, isc_event_t *);
316
static void destroy(dns_adb_t *);
Michael Graff's avatar
Michael Graff committed
317
318
static isc_boolean_t shutdown_names(dns_adb_t *);
static isc_boolean_t shutdown_entries(dns_adb_t *);
Michael Graff's avatar
Michael Graff committed
319
static inline void link_name(dns_adb_t *, int, dns_adbname_t *);
Michael Graff's avatar
Michael Graff committed
320
static inline isc_boolean_t unlink_name(dns_adb_t *, dns_adbname_t *);
321
static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *);
Michael Graff's avatar
Michael Graff committed
322
323
static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *);
static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t);
324
325
static void water(void *, int);
static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
Michael Graff's avatar
Michael Graff committed
326

327
328
329
330
331
/*
 * MUST NOT overlap DNS_ADBFIND_* flags!
 */
#define FIND_EVENT_SENT		0x40000000
#define FIND_EVENT_FREED	0x80000000
332
333
#define FIND_EVENTSENT(h)	(((h)->flags & FIND_EVENT_SENT) != 0)
#define FIND_EVENTFREED(h)	(((h)->flags & FIND_EVENT_FREED) != 0)
334

335
336
#define NAME_NEEDS_POKE		0x80000000
#define NAME_IS_DEAD		0x40000000
337
338
#define NAME_HINT_OK		DNS_ADBFIND_HINTOK
#define NAME_GLUE_OK		DNS_ADBFIND_GLUEOK
339
#define NAME_STARTATZONE	DNS_ADBFIND_STARTATZONE
340
341
#define NAME_DEAD(n)		(((n)->flags & NAME_IS_DEAD) != 0)
#define NAME_NEEDSPOKE(n)	(((n)->flags & NAME_NEEDS_POKE) != 0)
342
#define NAME_GLUEOK(n)		(((n)->flags & NAME_GLUE_OK) != 0)
David Lawrence's avatar
David Lawrence committed
343
#define NAME_HINTOK(n)		(((n)->flags & NAME_HINT_OK) != 0)
344

345
346
/*
 * To the name, address classes are all that really exist.  If it has a
347
 * V6 address it doesn't care if it came from a AAAA query.
348
349
350
351
 */
#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
352

353
/*
354
 * Fetches are broken out into A and AAAA types.  In some cases,
355
356
 * however, it makes more sense to test for a particular class of fetches,
 * like V4 or V6 above.
357
358
 * Note: since we have removed the support of A6 in adb, FETCH_A and FETCH_AAAA
 * are now equal to FETCH_V4 and FETCH_V6, respectively.
359
 */
360
361
362
#define NAME_FETCH_A(n)		((n)->fetch_a != NULL)
#define NAME_FETCH_AAAA(n)	((n)->fetch_aaaa != NULL)
#define NAME_FETCH_V4(n)	(NAME_FETCH_A(n))
363
#define NAME_FETCH_V6(n)	(NAME_FETCH_AAAA(n))
364
#define NAME_FETCH(n)		(NAME_FETCH_V4(n) || NAME_FETCH_V6(n))
365

366
367
368
369
370
/*
 * 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
371
372
#define FIND_AVOIDFETCHES(fn)	(((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
				 != 0)
373
#define FIND_STARTATZONE(fn)	(((fn)->options & DNS_ADBFIND_STARTATZONE) \
Bob Halley's avatar
Bob Halley committed
374
				 != 0)
375
376
#define FIND_HINTOK(fn)		(((fn)->options & DNS_ADBFIND_HINTOK) != 0)
#define FIND_GLUEOK(fn)		(((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
377
#define FIND_HAS_ADDRS(fn)	(!ISC_LIST_EMPTY((fn)->list))
Michael Graff's avatar
Michael Graff committed
378
#define FIND_RETURNLAME(fn)	(((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
Bob Halley's avatar
Bob Halley committed
379

380
381
382
383
384
385
386
/*
 * 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)

387
388
#define EXPIRE_OK(exp, now)	((exp == INT_MAX) || (exp < now))

389
390
391
392
393
394
395
396
/*
 * 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))
397
398
#define STARTATZONE_MATCHES(nf, o) (((nf)->flags & NAME_STARTATZONE) == \
				    ((o) & DNS_ADBFIND_STARTATZONE))
399

400
#define ENTER_LEVEL		ISC_LOG_DEBUG(50)
401
#define EXIT_LEVEL		ENTER_LEVEL
402
403
404
#define CLEAN_LEVEL		ISC_LOG_DEBUG(100)
#define DEF_LEVEL		ISC_LOG_DEBUG(5)
#define NCACHE_LEVEL		ISC_LOG_DEBUG(20)
405

406
407
#define NCACHE_RESULT(r)	((r) == DNS_R_NCACHENXDOMAIN || \
				 (r) == DNS_R_NCACHENXRRSET)
Bob Halley's avatar
Bob Halley committed
408
409
#define AUTH_NX(r)		((r) == DNS_R_NXDOMAIN || \
				 (r) == DNS_R_NXRRSET)
Michael Graff's avatar
Michael Graff committed
410
411
#define NXDOMAIN_RESULT(r)	((r) == DNS_R_NXDOMAIN || \
				 (r) == DNS_R_NCACHENXDOMAIN)
412
#define NXRRSET_RESULT(r)	((r) == DNS_R_NCACHENXRRSET || \
413
414
				 (r) == DNS_R_NXRRSET || \
				 (r) == DNS_R_HINTNXRRSET)
415

Michael Graff's avatar
Michael Graff committed
416
417
418
419
420
421
422
423
424
425
426
427
428
/*
 * Error state rankings.
 */

#define FIND_ERR_SUCCESS		0  /* highest rank */
#define FIND_ERR_CANCELED		1
#define FIND_ERR_FAILURE		2
#define FIND_ERR_NXDOMAIN		3
#define FIND_ERR_NXRRSET		4
#define FIND_ERR_UNEXPECTED		5
#define FIND_ERR_NOTFOUND		6
#define FIND_ERR_MAX			7

429
430
431
432
433
434
435
436
437
438
static const char *errnames[] = {
	"success",
	"canceled",
	"failure",
	"nxdomain",
	"nxrrset",
	"unexpected",
	"not_found"
};

Michael Graff's avatar
Michael Graff committed
439
440
441
442
443
444
445
446
447
448
449
#define NEWERR(old, new)	(ISC_MIN((old), (new)))

static isc_result_t find_err_map[FIND_ERR_MAX] = {
	ISC_R_SUCCESS,
	ISC_R_CANCELED,
	ISC_R_FAILURE,
	DNS_R_NXDOMAIN,
	DNS_R_NXRRSET,
	ISC_R_UNEXPECTED,
	ISC_R_NOTFOUND		/* not YET found */
};
450

451
452
453
static void
DP(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);

454
static void
David Lawrence's avatar
David Lawrence committed
455
DP(int level, const char *format, ...) {
456
457
458
459
460
	va_list args;

	va_start(args, format);
	isc_log_vwrite(dns_lctx,
		       DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
461
		       level, format, args);
462
463
464
	va_end(args);
}

465
466
467
468
469
470
471
472
473
474
static inline dns_ttl_t
ttlclamp(dns_ttl_t ttl) {
	if (ttl < ADB_CACHE_MINIMUM)
		ttl = ADB_CACHE_MINIMUM;
	if (ttl > ADB_CACHE_MAXIMUM)
		ttl = ADB_CACHE_MAXIMUM;

	return (ttl);
}

475
476
/*
 * Requires the adbname bucket be locked and that no entry buckets be locked.
477
478
 *
 * This code handles A and AAAA rdatasets only.
479
480
 */
static isc_result_t
481
482
import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
		isc_stdtime_t now)
483
484
{
	isc_result_t result;
Michael Graff's avatar
Michael Graff committed
485
	dns_adb_t *adb;
486
	dns_adbnamehook_t *nh;
487
	dns_adbnamehook_t *anh;
488
	dns_rdata_t rdata = DNS_RDATA_INIT;
489
	struct in_addr ina;
490
	struct in6_addr in6a;
491
492
493
494
	isc_sockaddr_t sockaddr;
	dns_adbentry_t *foundentry;  /* NO CLEAN UP! */
	int addr_bucket;
	isc_boolean_t new_addresses_added;
495
	dns_rdatatype_t rdtype;
496
	unsigned int findoptions;
497

Michael Graff's avatar
Michael Graff committed
498
499
500
501
	INSIST(DNS_ADBNAME_VALID(adbname));
	adb = adbname->adb;
	INSIST(DNS_ADB_VALID(adb));

502
503
	rdtype = rdataset->type;
	INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));
504
505
	if (rdtype == dns_rdatatype_a)
		findoptions = DNS_ADBFIND_INET;
506
	else
507
		findoptions = DNS_ADBFIND_INET6;
Michael Graff's avatar
Michael Graff committed
508

509
510
	addr_bucket = DNS_ADB_INVALIDBUCKET;
	new_addresses_added = ISC_FALSE;
511

512
	nh = NULL;
513
514
	result = dns_rdataset_first(rdataset);
	while (result == ISC_R_SUCCESS) {
515
		dns_rdata_reset(&rdata);
516
		dns_rdataset_current(rdataset, &rdata);
517
518
519
		if (rdtype == dns_rdatatype_a) {
			INSIST(rdata.length == 4);
			memcpy(&ina.s_addr, rdata.data, 4);
520
			isc_sockaddr_fromin(&sockaddr, &ina, 0);
521
		} else {
522
			INSIST(rdata.length == 16);
Mark Andrews's avatar
Mark Andrews committed
523
			memcpy(in6a.s6_addr, rdata.data, 16);
524
			isc_sockaddr_fromin6(&sockaddr, &in6a, 0);
525
526
		}

527
528
529
530
531
532
533
534
		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
535
536
537
538
539
540
		foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket);
		if (foundentry == NULL) {
			dns_adbentry_t *entry;

			entry = new_adbentry(adb);
			if (entry == NULL) {
541
				adbname->partial_result |= findoptions;
Michael Graff's avatar
Michael Graff committed
542
543
544
545
546
547
548
549
550
				result = ISC_R_NOMEMORY;
				goto fail;
			}

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

			nh->entry = entry;

551
			link_entry(adb, addr_bucket, entry);
Michael Graff's avatar
Michael Graff committed
552
		} else {
553
554
555
556
557
558
559
560
561
562
			for (anh = ISC_LIST_HEAD(adbname->v4);
			     anh != NULL;
			     anh = ISC_LIST_NEXT(anh, plink))
				if (anh->entry == foundentry)
					break;
			if (anh == NULL) {
				foundentry->refcnt++;
				nh->entry = foundentry;
			} else
				free_adbnamehook(adb, &nh);
Michael Graff's avatar
Michael Graff committed
563
564
565
		}

		new_addresses_added = ISC_TRUE;
566
567
568
569
570
571
		if (nh != NULL) {
			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
572
573
574
575
576
577
578
579
580
581
582
		nh = NULL;
		result = dns_rdataset_next(rdataset);
	}

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

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

583
584
585
586
587
	if (rdataset->trust == dns_trust_glue ||
	    rdataset->trust == dns_trust_additional)
		rdataset->ttl = ADB_CACHE_MINIMUM;
	else
		rdataset->ttl = ttlclamp(rdataset->ttl);
588

589
590
591
592
593
594
595
596
597
598
599
	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
600

601
	if (new_addresses_added) {
602
603
604
605
		/*
		 * 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
606
		return (ISC_R_SUCCESS);
607
	}
608
609
610
611

	return (result);
}

Michael Graff's avatar
Michael Graff committed
612
613
614
/*
 * Requires the name's bucket be locked.
 */
Michael Graff's avatar
Michael Graff committed
615
static isc_boolean_t
616
kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
Michael Graff's avatar
Michael Graff committed
617
	dns_adbname_t *name;
Michael Graff's avatar
Michael Graff committed
618
619
	isc_boolean_t result = ISC_FALSE;
	isc_boolean_t result4, result6;
Michael Graff's avatar
Michael Graff committed
620
	dns_adb_t *adb;
Michael Graff's avatar
Michael Graff committed
621
622
623
624
625

	INSIST(n != NULL);
	name = *n;
	*n = NULL;
	INSIST(DNS_ADBNAME_VALID(name));
Michael Graff's avatar
Michael Graff committed
626
627
	adb = name->adb;
	INSIST(DNS_ADB_VALID(adb));
Michael Graff's avatar
Michael Graff committed
628

629
	DP(DEF_LEVEL, "killing name %p", name);
630

631
632
633
634
	/*
	 * If we're dead already, just check to see if we should go
	 * away now or not.
	 */
635
	if (NAME_DEAD(name) && !NAME_FETCH(name)) {
Michael Graff's avatar
Michael Graff committed
636
		result = unlink_name(adb, name);
637
		free_adbname(adb, &name);
Michael Graff's avatar
Michael Graff committed
638
639
640
		if (result)
			result = dec_adb_irefcnt(adb);
		return (result);
641
642
643
644
645
646
	}

	/*
	 * Clean up the name's various lists.  These two are destructive
	 * in that they will always empty the list.
	 */
647
	clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK);
Michael Graff's avatar
Michael Graff committed
648
649
	result4 = clean_namehooks(adb, &name->v4);
	result6 = clean_namehooks(adb, &name->v6);
650
	clean_target(adb, &name->target);
Michael Graff's avatar
Michael Graff committed
651
	result = ISC_TF(result4 || result6);
Michael Graff's avatar
Michael Graff committed
652

653
654
655
656
	/*
	 * If fetches are running, cancel them.  If none are running, we can
	 * just kill the name here.
	 */
657
	if (!NAME_FETCH(name)) {
Michael Graff's avatar
Michael Graff committed
658
659
		INSIST(result == ISC_FALSE);
		result = unlink_name(adb, name);
Michael Graff's avatar
Michael Graff committed
660
		free_adbname(adb, &name);
Michael Graff's avatar
Michael Graff committed
661
662
		if (result)
			result = dec_adb_irefcnt(adb);
Michael Graff's avatar
Michael Graff committed
663
	} else {
664
		name->flags |= NAME_IS_DEAD;
665
		cancel_fetches_at_name(name);
Michael Graff's avatar
Michael Graff committed
666
	}
Michael Graff's avatar
Michael Graff committed
667
	return (result);
Michael Graff's avatar
Michael Graff committed
668
669
}

Michael Graff's avatar
Michael Graff committed
670
671
672
/*
 * Requires the name's bucket be locked and no entry buckets be locked.
 */
Michael Graff's avatar
Michael Graff committed
673
static isc_boolean_t
674
675
676
check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now,
		       isc_boolean_t overmem)
{
Michael Graff's avatar
Michael Graff committed
677
	dns_adb_t *adb;
678
	isc_boolean_t expire;
Michael Graff's avatar
Michael Graff committed
679
680
	isc_boolean_t result4 = ISC_FALSE;
	isc_boolean_t result6 = ISC_FALSE;
Michael Graff's avatar
Michael Graff committed
681
682
683
684

	INSIST(DNS_ADBNAME_VALID(name));
	adb = name->adb;
	INSIST(DNS_ADB_VALID(adb));
Mark Andrews's avatar
Mark Andrews committed
685

686
687
	if (overmem) {
		isc_uint32_t val;
Mark Andrews's avatar
Mark Andrews committed
688
689

		isc_random_get(&val);
690
691
692
693

		expire = ISC_TF((val % 4) == 0);
	} else
		expire = ISC_FALSE;
Michael Graff's avatar
Michael Graff committed
694
695
696
697

	/*
	 * Check to see if we need to remove the v4 addresses
	 */
698
699
	if (!NAME_FETCH_V4(name) &&
	    (expire || EXPIRE_OK(name->expire_v4, now))) {
700
		if (NAME_HAS_V4(name)) {
701
			DP(DEF_LEVEL, "expiring v4 for name %p", name);
Michael Graff's avatar
Michael Graff committed
702
			result4 = clean_namehooks(adb, &name->v4);
703
			name->partial_result &= ~DNS_ADBFIND_INET;
704
		}
705
		name->expire_v4 = INT_MAX;
706
		name->fetch_err = FIND_ERR_UNEXPECTED;
707
708
	}

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

	/*
	 * Check to see if we need to remove the alias target.
	 */
726
	if (expire || EXPIRE_OK(name->expire_target, now)) {
727
728
729
		clean_target(adb, &name->target);
		name->expire_target = INT_MAX;
	}
Michael Graff's avatar
Michael Graff committed
730
	return (ISC_TF(result4 || result6));
Michael Graff's avatar
Michael Graff committed
731
732
}

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

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

/*
 * Requires the name's bucket be locked.
 */
Michael Graff's avatar
Michael Graff committed
748
static inline isc_boolean_t
749
unlink_name(dns_adb_t *adb, dns_adbname_t *name) {
Michael Graff's avatar
Michael Graff committed
750
	int bucket;
Michael Graff's avatar
Michael Graff committed
751
	isc_boolean_t result = ISC_FALSE;
Michael Graff's avatar
Michael Graff committed
752
753
754
755

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

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

765
766
767
768
/*
 * Requires the entry's bucket be locked.
 */
static inline void
769
link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) {
770
771
772
773
774
775
776
777
	ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
	entry->lock_bucket = bucket;
	adb->entry_refcnt[bucket]++;
}

/*
 * Requires the entry's bucket be locked.
 */
Michael Graff's avatar
Michael Graff committed
778
static inline isc_boolean_t
779
unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) {
780
	int bucket;
Michael Graff's avatar
Michael Graff committed
781
	isc_boolean_t result = ISC_FALSE;
782
783
784
785
786
787
788
789

	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]--;
790
	if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0)
Michael Graff's avatar
Michael Graff committed
791
792
		result = ISC_TRUE;
	return (result);
793
794
}

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

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

Andreas Gustafsson's avatar
spacing    
Andreas Gustafsson committed
815
	for (bucket = 0; bucket < NBUCKETS; bucket++) {
816
817
818
819
		LOCK(&adb->namelocks[bucket]);
		adb->name_sd[bucket] = ISC_TRUE;

		name = ISC_LIST_HEAD(adb->names[bucket]);
820
821
822
823
824
825
		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.
			 */
Michael Graff's avatar
Michael Graff committed
826
827
			INSIST(result == ISC_FALSE);
			result = dec_adb_irefcnt(adb);
828
829
830
831
832
833
834
835
836
		} 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);
Michael Graff's avatar
Michael Graff committed
837
838
839
				INSIST(result == ISC_FALSE);
				result = kill_name(&name,
						   DNS_EVENT_ADBSHUTDOWN);
840
841
				name = next_name;
			}
842
843
844
845
		}

		UNLOCK(&adb->namelocks[bucket]);
	}
Michael Graff's avatar
Michael Graff committed
846
	return (result);
847
848
}

849
850
851
852
/*
 * The ADB _MUST_ be locked before calling.  Also, exit conditions must be
 * checked after calling this function.
 */
Michael Graff's avatar
Michael Graff committed
853
static isc_boolean_t
854
shutdown_entries(dns_adb_t *adb) {
855
	int bucket;
Michael Graff's avatar
Michael Graff committed
856
	isc_boolean_t result = ISC_FALSE;
857
858
859
	dns_adbentry_t *entry;
	dns_adbentry_t *next_entry;

Andreas Gustafsson's avatar
spacing    
Andreas Gustafsson committed
860
	for (bucket = 0; bucket < NBUCKETS; bucket++) {
861
862
863
864
		LOCK(&adb->entrylocks[bucket]);
		adb->entry_sd[bucket] = ISC_TRUE;

		entry = ISC_LIST_HEAD(adb->entries[bucket]);
865
866
867
868
869
870
		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.
			 */
Michael Graff's avatar
Michael Graff committed
871
			result = dec_adb_irefcnt(adb);
872
873
874
875
876
877
878
879
880
		} 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) {
Michael Graff's avatar
Michael Graff committed
881
					result = unlink_entry(adb, entry);
882
					free_adbentry(adb, &entry);
Michael Graff's avatar
Michael Graff committed
883
884
					if (result)
						result = dec_adb_irefcnt(adb);
885
886
				}
				entry = next_entry;
887
888
889
			}
		}

890
		UNLOCK(&adb->entrylocks[bucket]);
891
	}
Michael Graff's avatar
Michael Graff committed
892
	return (result);
893
894
}

Michael Graff's avatar
Michael Graff committed
895
896
897
898
/*
 * Name bucket must be locked
 */
static void
899
cancel_fetches_at_name(dns_adbname_t *name) {
900
	if (NAME_FETCH_A(name))
901
	    dns_resolver_cancelfetch(name->fetch_a->fetch);
902

903
	if (NAME_FETCH_AAAA(name))
904
	    dns_resolver_cancelfetch(name->fetch_aaaa->fetch);
Michael Graff's avatar
Michael Graff committed
905
906
}

Michael Graff's avatar
Michael Graff committed
907
908
909
/*
 * Assumes the name bucket is locked.
 */
Michael Graff's avatar
Michael Graff committed
910
static isc_boolean_t
911
clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
912
913
914
	dns_adbentry_t *entry;
	dns_adbnamehook_t *namehook;
	int addr_bucket;
Michael Graff's avatar
Michael Graff committed
91