1999-09-21 22:46:42 +00:00
|
|
|
/*
|
2000-02-03 23:50:32 +00:00
|
|
|
* Copyright (C) 1999, 2000 Internet Software Consortium.
|
2000-08-01 01:33:37 +00:00
|
|
|
*
|
1999-09-21 22:46:42 +00:00
|
|
|
* 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.
|
2000-08-01 01:33:37 +00:00
|
|
|
*
|
2000-07-27 09:55:03 +00:00
|
|
|
* 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.
|
1999-09-21 22:46:42 +00:00
|
|
|
*/
|
|
|
|
|
2000-08-26 01:37:00 +00:00
|
|
|
/* $Id: adb.c,v 1.148 2000/08/26 01:36:45 bwelling Exp $ */
|
2000-06-22 22:00:42 +00:00
|
|
|
|
1999-09-23 00:43:10 +00:00
|
|
|
/*
|
|
|
|
* Implementation notes
|
|
|
|
* --------------------
|
|
|
|
*
|
1999-10-29 18:30:48 +00:00
|
|
|
* In finds, if task == NULL, no events will be generated, and no events
|
1999-09-23 00:43:10 +00:00
|
|
|
* have been sent. If task != NULL but taskaction == NULL, an event has been
|
1999-11-25 01:23:32 +00:00
|
|
|
* posted but not yet freed. If neither are NULL, no event was posted.
|
1999-09-23 00:43:10 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
1999-11-24 19:23:27 +00:00
|
|
|
/*
|
|
|
|
* After we have cleaned all buckets, dump the database contents.
|
|
|
|
*/
|
2000-06-08 01:43:21 +00:00
|
|
|
#if 0
|
1999-11-24 19:23:27 +00:00
|
|
|
#define DUMP_ADB_AFTER_CLEANING
|
2000-06-08 01:43:21 +00:00
|
|
|
#endif
|
1999-11-24 19:23:27 +00:00
|
|
|
|
1999-09-21 22:46:42 +00:00
|
|
|
#include <config.h>
|
|
|
|
|
2000-01-21 02:13:38 +00:00
|
|
|
#include <limits.h>
|
2000-05-08 14:38:29 +00:00
|
|
|
|
1999-09-24 23:54:42 +00:00
|
|
|
#include <isc/mutexblock.h>
|
1999-10-20 23:26:06 +00:00
|
|
|
#include <isc/random.h>
|
2000-05-08 19:23:32 +00:00
|
|
|
#include <isc/string.h> /* Required for HP/UX (and others?) */
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/task.h>
|
1999-10-25 22:53:15 +00:00
|
|
|
#include <isc/timer.h>
|
1999-12-16 22:24:22 +00:00
|
|
|
#include <isc/util.h>
|
1999-09-22 00:26:20 +00:00
|
|
|
|
1999-10-30 01:22:16 +00:00
|
|
|
#include <dns/a6.h>
|
1999-10-22 01:02:38 +00:00
|
|
|
#include <dns/adb.h>
|
1999-10-21 01:18:06 +00:00
|
|
|
#include <dns/db.h>
|
1999-10-16 00:38:21 +00:00
|
|
|
#include <dns/events.h>
|
1999-10-29 22:28:57 +00:00
|
|
|
#include <dns/log.h>
|
1999-10-05 23:50:43 +00:00
|
|
|
#include <dns/rdata.h>
|
|
|
|
#include <dns/rdataset.h>
|
1999-10-25 21:39:08 +00:00
|
|
|
#include <dns/resolver.h>
|
2000-05-02 03:54:17 +00:00
|
|
|
#include <dns/result.h>
|
1999-09-23 00:43:10 +00:00
|
|
|
|
1999-09-25 01:25:46 +00:00
|
|
|
#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)
|
1999-10-29 01:26:45 +00:00
|
|
|
#define DNS_ADBFETCH_MAGIC 0x61644634 /* adF4. */
|
1999-10-25 21:02:54 +00:00
|
|
|
#define DNS_ADBFETCH_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
|
1999-10-30 01:22:16 +00:00
|
|
|
#define DNS_ADBFETCH6_MAGIC 0x61644636 /* adF6. */
|
|
|
|
#define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
|
1999-09-22 00:26:20 +00:00
|
|
|
|
1999-09-23 00:43:10 +00:00
|
|
|
/*
|
1999-11-25 01:23:32 +00:00
|
|
|
* 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).
|
1999-09-23 00:43:10 +00:00
|
|
|
*/
|
1999-12-01 02:05:16 +00:00
|
|
|
#define NBUCKETS 1009 /* how many buckets for names/addrs */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For type 3 negative cache entries, we will remember that the address is
|
1999-12-11 02:30:24 +00:00
|
|
|
* 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.
|
1999-12-01 02:05:16 +00:00
|
|
|
*/
|
2000-01-19 01:43:58 +00:00
|
|
|
#define ADB_CACHE_MINIMUM 10 /* seconds */
|
2000-06-07 20:15:48 +00:00
|
|
|
#define ADB_CACHE_MAXIMUM 86400 /* seconds (86400 = 24 hours) */
|
1999-09-23 00:43:10 +00:00
|
|
|
|
1999-11-25 01:23:32 +00:00
|
|
|
/*
|
2000-02-18 03:53:00 +00:00
|
|
|
* Clean CLEAN_BUCKETS buckets every CLEAN_SECONDS.
|
1999-11-25 01:23:32 +00:00
|
|
|
*/
|
2000-02-18 03:53:00 +00:00
|
|
|
#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)
|
1999-12-01 02:05:16 +00:00
|
|
|
#if CLEAN_SECONDS < 1
|
|
|
|
#undef CLEAN_SECONDS
|
|
|
|
#define CLEAN_SECONDS 1
|
|
|
|
#endif
|
1999-10-25 22:53:15 +00:00
|
|
|
|
2000-04-19 17:48:25 +00:00
|
|
|
#define FREE_ITEMS 64 /* free count for memory pools */
|
|
|
|
#define FILL_COUNT 16 /* fill count for memory pools */
|
1999-09-22 01:01:14 +00:00
|
|
|
|
1999-10-02 01:59:09 +00:00
|
|
|
#define DNS_ADB_INVALIDBUCKET (-1) /* invalid bucket address */
|
|
|
|
|
1999-09-22 01:01:14 +00:00
|
|
|
typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
|
1999-09-22 00:26:20 +00:00
|
|
|
typedef struct dns_adbnamehook dns_adbnamehook_t;
|
1999-10-29 01:26:45 +00:00
|
|
|
typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
|
1999-09-22 00:26:20 +00:00
|
|
|
typedef struct dns_adbzoneinfo dns_adbzoneinfo_t;
|
1999-09-23 00:43:10 +00:00
|
|
|
typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
|
1999-10-25 21:02:54 +00:00
|
|
|
typedef struct dns_adbfetch dns_adbfetch_t;
|
1999-10-30 01:22:16 +00:00
|
|
|
typedef struct dns_adbfetch6 dns_adbfetch6_t;
|
1999-09-21 22:46:42 +00:00
|
|
|
|
|
|
|
struct dns_adb {
|
1999-09-22 00:26:20 +00:00
|
|
|
unsigned int magic;
|
|
|
|
|
|
|
|
isc_mutex_t lock;
|
2000-01-13 20:42:43 +00:00
|
|
|
isc_mutex_t ilock;
|
1999-09-22 00:26:20 +00:00
|
|
|
isc_mem_t *mctx;
|
1999-10-08 23:12:21 +00:00
|
|
|
dns_view_t *view;
|
1999-10-25 21:39:08 +00:00
|
|
|
isc_timermgr_t *timermgr;
|
1999-10-25 22:53:15 +00:00
|
|
|
isc_timer_t *timer;
|
1999-10-25 21:39:08 +00:00
|
|
|
isc_taskmgr_t *taskmgr;
|
1999-10-25 22:53:15 +00:00
|
|
|
isc_task_t *task;
|
1999-10-29 23:53:12 +00:00
|
|
|
|
1999-10-25 22:53:15 +00:00
|
|
|
isc_interval_t tick_interval;
|
2000-01-12 03:00:33 +00:00
|
|
|
int next_cleanbucket;
|
1999-09-22 00:26:20 +00:00
|
|
|
|
1999-10-19 01:37:22 +00:00
|
|
|
unsigned int irefcnt;
|
|
|
|
unsigned int erefcnt;
|
1999-10-05 23:50:43 +00:00
|
|
|
|
1999-09-23 00:43:10 +00:00
|
|
|
isc_mutex_t mplock;
|
1999-09-22 00:26:20 +00:00
|
|
|
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 */
|
1999-10-29 18:07:32 +00:00
|
|
|
isc_mempool_t *ahmp; /* dns_adbfind_t */
|
1999-09-22 00:26:20 +00:00
|
|
|
isc_mempool_t *aimp; /* dns_adbaddrinfo_t */
|
1999-10-25 21:02:54 +00:00
|
|
|
isc_mempool_t *afmp; /* dns_adbfetch_t */
|
1999-10-30 01:22:16 +00:00
|
|
|
isc_mempool_t *af6mp; /* dns_adbfetch6_t */
|
1999-09-22 00:26:20 +00:00
|
|
|
|
1999-10-20 23:26:06 +00:00
|
|
|
isc_random_t rand;
|
|
|
|
|
1999-09-22 01:01:14 +00:00
|
|
|
/*
|
|
|
|
* Bucketized locks and lists for names.
|
1999-11-25 01:23:32 +00:00
|
|
|
*
|
|
|
|
* XXXRTH Have a per-bucket structure that contains all of these?
|
1999-09-22 01:01:14 +00:00
|
|
|
*/
|
1999-11-05 02:05:06 +00:00
|
|
|
dns_adbnamelist_t names[NBUCKETS];
|
|
|
|
isc_mutex_t namelocks[NBUCKETS];
|
|
|
|
isc_boolean_t name_sd[NBUCKETS];
|
|
|
|
unsigned int name_refcnt[NBUCKETS];
|
1999-09-22 01:01:14 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Bucketized locks for entries.
|
1999-11-25 01:23:32 +00:00
|
|
|
*
|
|
|
|
* XXXRTH Have a per-bucket structure that contains all of these?
|
1999-09-22 01:01:14 +00:00
|
|
|
*/
|
1999-11-05 02:05:06 +00:00
|
|
|
dns_adbentrylist_t entries[NBUCKETS];
|
|
|
|
isc_mutex_t entrylocks[NBUCKETS];
|
2000-01-12 03:00:33 +00:00
|
|
|
isc_boolean_t entry_sd[NBUCKETS];
|
|
|
|
unsigned int entry_refcnt[NBUCKETS];
|
1999-11-22 19:57:58 +00:00
|
|
|
|
|
|
|
isc_event_t cevent;
|
|
|
|
isc_boolean_t cevent_sent;
|
|
|
|
isc_boolean_t shutting_down;
|
|
|
|
isc_eventlist_t whenshutdown;
|
1999-09-21 22:46:42 +00:00
|
|
|
};
|
|
|
|
|
1999-11-25 01:23:32 +00:00
|
|
|
/*
|
|
|
|
* XXXMLG Document these structures.
|
|
|
|
*/
|
|
|
|
|
1999-09-22 00:26:20 +00:00
|
|
|
struct dns_adbname {
|
|
|
|
unsigned int magic;
|
1999-09-23 00:43:10 +00:00
|
|
|
dns_name_t name;
|
1999-10-27 19:36:58 +00:00
|
|
|
dns_adb_t *adb;
|
1999-10-28 21:50:27 +00:00
|
|
|
unsigned int partial_result;
|
1999-10-30 01:58:02 +00:00
|
|
|
unsigned int flags;
|
1999-10-29 22:09:31 +00:00
|
|
|
int lock_bucket;
|
2000-01-19 01:43:58 +00:00
|
|
|
dns_name_t target;
|
|
|
|
isc_stdtime_t expire_target;
|
1999-10-29 01:26:45 +00:00
|
|
|
isc_stdtime_t expire_v4;
|
|
|
|
isc_stdtime_t expire_v6;
|
1999-10-30 01:22:16 +00:00
|
|
|
unsigned int chains;
|
1999-10-29 01:26:45 +00:00
|
|
|
dns_adbnamehooklist_t v4;
|
|
|
|
dns_adbnamehooklist_t v6;
|
1999-10-29 21:48:51 +00:00
|
|
|
dns_adbfetch_t *fetch_a;
|
|
|
|
dns_adbfetch_t *fetch_aaaa;
|
1999-10-30 01:22:16 +00:00
|
|
|
ISC_LIST(dns_adbfetch6_t) fetches_a6;
|
1999-11-05 09:49:53 +00:00
|
|
|
dns_adbfindlist_t finds;
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LINK(dns_adbname_t) plink;
|
1999-09-22 00:26:20 +00:00
|
|
|
};
|
|
|
|
|
1999-10-25 21:02:54 +00:00
|
|
|
struct dns_adbfetch {
|
|
|
|
unsigned int magic;
|
|
|
|
dns_adbnamehook_t *namehook;
|
|
|
|
dns_adbentry_t *entry;
|
|
|
|
dns_fetch_t *fetch;
|
|
|
|
dns_rdataset_t rdataset;
|
|
|
|
};
|
|
|
|
|
1999-10-30 01:22:16 +00:00
|
|
|
struct dns_adbfetch6 {
|
|
|
|
unsigned int magic;
|
1999-11-02 00:29:45 +00:00
|
|
|
unsigned int flags;
|
1999-10-30 01:22:16 +00:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
1999-09-22 00:26:20 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
1999-09-23 00:43:10 +00:00
|
|
|
dns_adbentry_t *entry;
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LINK(dns_adbnamehook_t) plink;
|
1999-09-21 22:46:42 +00:00
|
|
|
};
|
|
|
|
|
1999-09-22 00:26:20 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
1999-10-08 23:12:21 +00:00
|
|
|
dns_name_t zone;
|
1999-10-19 20:55:04 +00:00
|
|
|
isc_stdtime_t lame_timer;
|
1999-09-22 00:26:20 +00:00
|
|
|
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LINK(dns_adbzoneinfo_t) plink;
|
1999-09-22 00:26:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* An address entry. It holds quite a bit of information about addresses,
|
|
|
|
* including edns state, rtt, and of course the address of the host.
|
|
|
|
*/
|
1999-09-21 22:46:42 +00:00
|
|
|
struct dns_adbentry {
|
1999-09-22 00:26:20 +00:00
|
|
|
unsigned int magic;
|
|
|
|
|
1999-09-23 00:43:10 +00:00
|
|
|
int lock_bucket;
|
1999-10-08 23:12:21 +00:00
|
|
|
unsigned int refcnt;
|
1999-09-22 00:26:20 +00:00
|
|
|
|
|
|
|
unsigned int flags;
|
1999-10-20 23:26:06 +00:00
|
|
|
int edns_level; /* must be int! */
|
|
|
|
int goodness; /* bad < 0 <= good */
|
1999-09-22 00:26:20 +00:00
|
|
|
unsigned int srtt;
|
|
|
|
isc_sockaddr_t sockaddr;
|
2000-01-12 03:00:33 +00:00
|
|
|
isc_stdtime_t expires;
|
2000-02-16 00:16:36 +00:00
|
|
|
isc_stdtime_t avoid_bitstring;
|
1999-09-22 00:26:20 +00:00
|
|
|
|
|
|
|
ISC_LIST(dns_adbzoneinfo_t) zoneinfo;
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LINK(dns_adbentry_t) plink;
|
1999-09-21 22:46:42 +00:00
|
|
|
};
|
|
|
|
|
1999-09-22 00:26:20 +00:00
|
|
|
/*
|
1999-09-23 00:43:10 +00:00
|
|
|
* Internal functions (and prototypes).
|
|
|
|
*/
|
1999-10-19 20:55:04 +00:00
|
|
|
static inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *);
|
1999-10-08 23:12:21 +00:00
|
|
|
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 **);
|
1999-10-19 21:10:29 +00:00
|
|
|
static inline dns_adbzoneinfo_t *new_adbzoneinfo(dns_adb_t *, dns_name_t *);
|
1999-10-08 23:12:21 +00:00
|
|
|
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 **);
|
1999-10-29 18:30:48 +00:00
|
|
|
static inline dns_adbfind_t *new_adbfind(dns_adb_t *);
|
|
|
|
static inline void free_adbfind(dns_adb_t *, dns_adbfind_t **);
|
2000-06-01 00:30:58 +00:00
|
|
|
static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *,
|
|
|
|
in_port_t);
|
1999-10-29 01:26:45 +00:00
|
|
|
static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *);
|
|
|
|
static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
|
1999-10-30 02:26:03 +00:00
|
|
|
static inline dns_adbfetch6_t *new_adbfetch6(dns_adb_t *, dns_adbname_t *,
|
|
|
|
dns_a6context_t *);
|
1999-10-30 01:22:16 +00:00
|
|
|
static inline void free_adbfetch6(dns_adb_t *, dns_adbfetch6_t **);
|
1999-10-08 23:12:21 +00:00
|
|
|
static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
|
2000-02-02 23:24:04 +00:00
|
|
|
unsigned int, int *);
|
1999-10-08 23:12:21 +00:00
|
|
|
static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
|
|
|
|
isc_sockaddr_t *, int *);
|
1999-10-27 19:36:58 +00:00
|
|
|
static void dump_adb(dns_adb_t *, FILE *);
|
1999-10-08 23:12:21 +00:00
|
|
|
static void print_dns_name(FILE *, dns_name_t *);
|
|
|
|
static void print_namehook_list(FILE *, dns_adbname_t *);
|
1999-10-29 18:30:48 +00:00
|
|
|
static void print_find_list(FILE *, dns_adbname_t *);
|
1999-10-27 19:36:58 +00:00
|
|
|
static void print_fetch_list(FILE *, dns_adbname_t *);
|
2000-01-13 20:42:43 +00:00
|
|
|
static inline void dec_adb_irefcnt(dns_adb_t *);
|
1999-10-19 01:37:22 +00:00
|
|
|
static inline void inc_adb_erefcnt(dns_adb_t *, isc_boolean_t);
|
1999-10-26 23:44:36 +00:00
|
|
|
static inline void dec_adb_erefcnt(dns_adb_t *, isc_boolean_t);
|
1999-10-08 23:12:21 +00:00
|
|
|
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);
|
1999-10-19 20:55:04 +00:00
|
|
|
static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
|
1999-10-29 01:26:45 +00:00
|
|
|
static void clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
|
2000-01-19 01:43:58 +00:00
|
|
|
static void clean_target(dns_adb_t *, dns_name_t *);
|
1999-10-30 01:58:02 +00:00
|
|
|
static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
|
|
|
|
unsigned int);
|
1999-10-29 01:26:45 +00:00
|
|
|
static void check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
|
2000-01-21 02:50:27 +00:00
|
|
|
static void cancel_fetches_at_name(dns_adbname_t *);
|
1999-11-02 00:29:45 +00:00
|
|
|
static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
|
2000-02-02 23:24:04 +00:00
|
|
|
dns_rdatatype_t);
|
2000-01-19 01:43:58 +00:00
|
|
|
static isc_result_t fetch_name_v4(dns_adbname_t *, isc_boolean_t);
|
|
|
|
static isc_result_t fetch_name_aaaa(dns_adbname_t *);
|
2000-02-02 23:24:04 +00:00
|
|
|
static isc_result_t fetch_name_a6(dns_adbname_t *, isc_boolean_t);
|
1999-10-26 23:44:36 +00:00
|
|
|
static inline void check_exit(dns_adb_t *);
|
1999-10-25 22:53:15 +00:00
|
|
|
static void timer_cleanup(isc_task_t *, isc_event_t *);
|
1999-10-25 23:18:19 +00:00
|
|
|
static void destroy(dns_adb_t *);
|
1999-10-26 23:44:36 +00:00
|
|
|
static void shutdown_names(dns_adb_t *);
|
2000-01-12 03:00:33 +00:00
|
|
|
static void shutdown_entries(dns_adb_t *);
|
1999-10-26 23:44:36 +00:00
|
|
|
static inline void link_name(dns_adb_t *, int, dns_adbname_t *);
|
|
|
|
static inline void unlink_name(dns_adb_t *, dns_adbname_t *);
|
2000-01-12 03:00:33 +00:00
|
|
|
static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *);
|
|
|
|
static inline void unlink_entry(dns_adb_t *, dns_adbentry_t *);
|
1999-10-30 02:26:03 +00:00
|
|
|
static void kill_name(dns_adbname_t **, isc_eventtype_t);
|
|
|
|
static void fetch_callback_a6(isc_task_t *, isc_event_t *);
|
2000-02-02 23:24:04 +00:00
|
|
|
static isc_result_t dbfind_a6(dns_adbname_t *, isc_stdtime_t);
|
1999-10-29 01:26:45 +00:00
|
|
|
|
1999-10-30 01:58:02 +00:00
|
|
|
/*
|
|
|
|
* MUST NOT overlap DNS_ADBFIND_* flags!
|
|
|
|
*/
|
|
|
|
#define FIND_EVENT_SENT 0x40000000
|
|
|
|
#define FIND_EVENT_FREED 0x80000000
|
1999-11-04 08:48:47 +00:00
|
|
|
#define FIND_EVENTSENT(h) (((h)->flags & FIND_EVENT_SENT) != 0)
|
|
|
|
#define FIND_EVENTFREED(h) (((h)->flags & FIND_EVENT_FREED) != 0)
|
1999-10-29 18:00:31 +00:00
|
|
|
|
1999-10-30 01:58:02 +00:00
|
|
|
#define NAME_NEEDS_POKE 0x80000000
|
|
|
|
#define NAME_IS_DEAD 0x40000000
|
2000-02-02 23:24:04 +00:00
|
|
|
#define NAME_HINT_OK DNS_ADBFIND_HINTOK
|
|
|
|
#define NAME_GLUE_OK DNS_ADBFIND_GLUEOK
|
1999-10-30 01:58:02 +00:00
|
|
|
#define NAME_DEAD(n) (((n)->flags & NAME_IS_DEAD) != 0)
|
|
|
|
#define NAME_NEEDSPOKE(n) (((n)->flags & NAME_NEEDS_POKE) != 0)
|
2000-02-02 23:24:04 +00:00
|
|
|
#define NAME_GLUEOK(n) (((n)->flags & NAME_GLUE_OK) != 0)
|
Silence IRIX warnings:
"adb.c", line 2042: remark(1552): variable "result" was set but never used
isc_result_t result;
^
"adb.c", line 3082: warning(1185): enumerated type mixed with another type
NAME_GLUEOK(adbname), NAME_HINTOK(adbname),
^
"adb.c", line 3187: warning(1185): enumerated type mixed with another type
now, NAME_GLUEOK(adbname), NAME_HINTOK(adbname),
Note that the first is in timer_cleanup, a function returning void in a context
that can't do anything with something other than void (as an isc_taskaction_t).
It calls isc_timer_reset, which could conceivably return ISC_R_NOMEMORY or
ISC_R_UNEXPECTED. For now the call has been cast to void, but someone
who knows the code better should have a look and see whether something more
intelligent could be done with an error (and, if not, remove my XXX and
make sure the comment is clear as to why ignoring the return is the
best that can be done).
2000-05-13 20:15:16 +00:00
|
|
|
#define NAME_HINTOK(n) (((n)->flags & NAME_HINT_OK) != 0)
|
1999-11-02 00:29:45 +00:00
|
|
|
|
1999-11-04 08:48:47 +00:00
|
|
|
/*
|
|
|
|
* 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))
|
1999-10-26 23:44:36 +00:00
|
|
|
|
1999-11-04 08:48:47 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
1999-11-02 18:36:54 +00:00
|
|
|
#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))
|
1999-10-29 21:48:51 +00:00
|
|
|
|
1999-11-04 08:48:47 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2000-02-02 23:24:04 +00:00
|
|
|
#define FETCH_FIRST_A6 0x80000000
|
1999-11-04 08:48:47 +00:00
|
|
|
#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)
|
1999-12-14 00:10:06 +00:00
|
|
|
#define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
|
|
|
|
!= 0)
|
2000-01-06 00:56:37 +00:00
|
|
|
#define FIND_STARTATROOT(fn) (((fn)->options & DNS_ADBFIND_STARTATROOT) \
|
|
|
|
!= 0)
|
2000-02-02 23:24:04 +00:00
|
|
|
#define FIND_HINTOK(fn) (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
|
|
|
|
#define FIND_GLUEOK(fn) (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
|
1999-11-04 08:48:47 +00:00
|
|
|
#define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list))
|
2000-02-02 23:27:39 +00:00
|
|
|
#define FIND_RETURNLAME(fn) (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
|
1999-12-14 00:10:06 +00:00
|
|
|
|
1999-11-04 08:48:47 +00:00
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
|
1999-11-04 06:46:05 +00:00
|
|
|
#define EXPIRE_OK(exp, now) ((exp == INT_MAX) || (exp < now))
|
|
|
|
|
2000-02-02 23:24:04 +00:00
|
|
|
/*
|
|
|
|
* 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))
|
|
|
|
|
1999-11-01 20:16:35 +00:00
|
|
|
#define ENTER_LEVEL 50
|
|
|
|
#define EXIT_LEVEL ENTER_LEVEL
|
|
|
|
#define CLEAN_LEVEL 100
|
|
|
|
#define DEF_LEVEL 5
|
1999-12-01 02:05:16 +00:00
|
|
|
#define NCACHE_LEVEL 20
|
1999-11-01 20:16:35 +00:00
|
|
|
|
1999-11-24 19:23:27 +00:00
|
|
|
#define NCACHE_RESULT(r) ((r) == DNS_R_NCACHENXDOMAIN || \
|
|
|
|
(r) == DNS_R_NCACHENXRRSET)
|
2000-01-15 00:45:49 +00:00
|
|
|
#define AUTH_NX(r) ((r) == DNS_R_NXDOMAIN || \
|
|
|
|
(r) == DNS_R_NXRRSET)
|
1999-11-24 19:23:27 +00:00
|
|
|
|
|
|
|
|
1999-10-29 22:28:57 +00:00
|
|
|
static void
|
2000-06-01 18:26:56 +00:00
|
|
|
DP(int level, const char *format, ...) {
|
1999-10-29 22:28:57 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2000-06-07 20:15:48 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
1999-10-27 22:24:40 +00:00
|
|
|
/*
|
|
|
|
* Requires the adbname bucket be locked and that no entry buckets be locked.
|
1999-10-29 19:42:06 +00:00
|
|
|
*
|
|
|
|
* This code handles A and AAAA rdatasets only.
|
1999-10-27 22:24:40 +00:00
|
|
|
*/
|
|
|
|
static isc_result_t
|
1999-10-29 19:42:06 +00:00
|
|
|
import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
|
|
|
|
isc_stdtime_t now)
|
1999-10-27 22:24:40 +00:00
|
|
|
{
|
|
|
|
isc_result_t result;
|
1999-10-29 01:26:45 +00:00
|
|
|
dns_adb_t *adb;
|
1999-10-27 22:24:40 +00:00
|
|
|
dns_adbnamehook_t *nh;
|
|
|
|
dns_rdata_t rdata;
|
|
|
|
struct in_addr ina;
|
1999-10-29 19:42:06 +00:00
|
|
|
struct in6_addr in6a;
|
1999-10-27 22:24:40 +00:00
|
|
|
isc_sockaddr_t sockaddr;
|
|
|
|
dns_adbentry_t *foundentry; /* NO CLEAN UP! */
|
|
|
|
int addr_bucket;
|
|
|
|
isc_boolean_t new_addresses_added;
|
1999-10-29 19:42:06 +00:00
|
|
|
dns_rdatatype_t rdtype;
|
1999-10-29 21:48:51 +00:00
|
|
|
unsigned int findoptions;
|
1999-10-27 22:24:40 +00:00
|
|
|
|
1999-10-29 01:26:45 +00:00
|
|
|
INSIST(DNS_ADBNAME_VALID(adbname));
|
|
|
|
adb = adbname->adb;
|
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
|
|
|
|
1999-10-29 19:42:06 +00:00
|
|
|
rdtype = rdataset->type;
|
|
|
|
INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));
|
1999-10-29 21:48:51 +00:00
|
|
|
if (rdtype == dns_rdatatype_a)
|
|
|
|
findoptions = DNS_ADBFIND_INET;
|
1999-12-02 23:45:30 +00:00
|
|
|
else
|
1999-10-29 21:48:51 +00:00
|
|
|
findoptions = DNS_ADBFIND_INET6;
|
1999-10-29 19:20:36 +00:00
|
|
|
|
1999-10-27 22:24:40 +00:00
|
|
|
addr_bucket = DNS_ADB_INVALIDBUCKET;
|
|
|
|
new_addresses_added = ISC_FALSE;
|
1999-10-29 21:48:51 +00:00
|
|
|
|
1999-12-01 02:05:16 +00:00
|
|
|
nh = NULL;
|
1999-10-27 22:24:40 +00:00
|
|
|
result = dns_rdataset_first(rdataset);
|
|
|
|
while (result == ISC_R_SUCCESS) {
|
|
|
|
dns_rdataset_current(rdataset, &rdata);
|
1999-10-29 19:42:06 +00:00
|
|
|
if (rdtype == dns_rdatatype_a) {
|
|
|
|
INSIST(rdata.length == 4);
|
|
|
|
memcpy(&ina.s_addr, rdata.data, 4);
|
2000-06-01 00:30:58 +00:00
|
|
|
isc_sockaddr_fromin(&sockaddr, &ina, 0);
|
1999-10-27 22:24:40 +00:00
|
|
|
} else {
|
1999-10-29 19:42:06 +00:00
|
|
|
INSIST(rdata.length == 16);
|
1999-11-01 00:10:10 +00:00
|
|
|
memcpy(in6a.s6_addr, rdata.data, 16);
|
2000-06-01 00:30:58 +00:00
|
|
|
isc_sockaddr_fromin6(&sockaddr, &in6a, 0);
|
1999-10-27 22:24:40 +00:00
|
|
|
}
|
|
|
|
|
1999-12-01 02:05:16 +00:00
|
|
|
INSIST(nh == NULL);
|
|
|
|
nh = new_adbnamehook(adb, NULL);
|
|
|
|
if (nh == NULL) {
|
|
|
|
adbname->partial_result |= findoptions;
|
|
|
|
result = ISC_R_NOMEMORY;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
1999-10-29 19:20:36 +00:00
|
|
|
foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket);
|
|
|
|
if (foundentry == NULL) {
|
|
|
|
dns_adbentry_t *entry;
|
|
|
|
|
|
|
|
entry = new_adbentry(adb);
|
|
|
|
if (entry == NULL) {
|
1999-10-29 21:48:51 +00:00
|
|
|
adbname->partial_result |= findoptions;
|
1999-10-29 19:20:36 +00:00
|
|
|
result = ISC_R_NOMEMORY;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
entry->sockaddr = sockaddr;
|
|
|
|
entry->refcnt = 1;
|
|
|
|
|
|
|
|
nh->entry = entry;
|
|
|
|
|
2000-01-12 03:00:33 +00:00
|
|
|
link_entry(adb, addr_bucket, entry);
|
1999-10-29 19:20:36 +00:00
|
|
|
} else {
|
|
|
|
foundentry->refcnt++;
|
|
|
|
nh->entry = foundentry;
|
|
|
|
}
|
|
|
|
|
|
|
|
new_addresses_added = ISC_TRUE;
|
1999-10-29 19:42:06 +00:00
|
|
|
if (rdtype == dns_rdatatype_a)
|
|
|
|
ISC_LIST_APPEND(adbname->v4, nh, plink);
|
|
|
|
else
|
|
|
|
ISC_LIST_APPEND(adbname->v6, nh, plink);
|
1999-10-29 19:20:36 +00:00
|
|
|
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]);
|
|
|
|
|
2000-06-07 20:15:48 +00:00
|
|
|
rdataset->ttl = ttlclamp(rdataset->ttl);
|
1999-12-11 02:30:24 +00:00
|
|
|
|
1999-12-01 02:05:16 +00:00
|
|
|
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);
|
|
|
|
}
|
1999-10-29 19:20:36 +00:00
|
|
|
|
1999-12-01 02:05:16 +00:00
|
|
|
if (new_addresses_added) {
|
1999-11-05 02:05:06 +00:00
|
|
|
/*
|
|
|
|
* Lie a little here. This is more or less so code that cares
|
|
|
|
* can find out if any new information was added or not.
|
|
|
|
*/
|
1999-10-29 19:20:36 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-11-05 02:05:06 +00:00
|
|
|
}
|
1999-10-27 22:24:40 +00:00
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-10-30 01:58:02 +00:00
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
import_a6(dns_a6context_t *a6ctx) {
|
1999-10-30 01:58:02 +00:00
|
|
|
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;
|
|
|
|
|
1999-11-22 19:57:58 +00:00
|
|
|
name = a6ctx->arg;
|
1999-10-30 01:58:02 +00:00
|
|
|
INSIST(DNS_ADBNAME_VALID(name));
|
|
|
|
adb = name->adb;
|
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
|
|
|
|
1999-11-02 00:39:11 +00:00
|
|
|
addr_bucket = DNS_ADB_INVALIDBUCKET;
|
1999-10-30 01:58:02 +00:00
|
|
|
|
1999-11-01 20:16:35 +00:00
|
|
|
DP(ENTER_LEVEL, "ENTER: import_a6() name %p", name);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-10-30 01:58:02 +00:00
|
|
|
nh = new_adbnamehook(adb, NULL);
|
|
|
|
if (nh == NULL) {
|
|
|
|
name->partial_result |= DNS_ADBFIND_INET6; /* clear for AAAA */
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2000-06-01 00:30:58 +00:00
|
|
|
isc_sockaddr_fromin6(&sockaddr, &a6ctx->in6addr, 0);
|
1999-12-01 02:05:16 +00:00
|
|
|
|
1999-10-30 01:58:02 +00:00
|
|
|
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;
|
2000-01-12 03:00:33 +00:00
|
|
|
link_entry(adb, addr_bucket, entry);
|
1999-10-30 01:58:02 +00:00
|
|
|
} else {
|
|
|
|
foundentry->refcnt++;
|
|
|
|
nh->entry = foundentry;
|
|
|
|
}
|
|
|
|
|
|
|
|
ISC_LIST_APPEND(name->v6, nh, plink);
|
|
|
|
nh = NULL;
|
|
|
|
|
1999-12-01 02:05:16 +00:00
|
|
|
fail:
|
|
|
|
DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) in import_v6",
|
1999-11-25 01:23:32 +00:00
|
|
|
name->expire_v6, a6ctx->expiration);
|
|
|
|
name->expire_v6 = ISC_MIN(name->expire_v6, a6ctx->expiration);
|
|
|
|
|
|
|
|
name->flags |= NAME_NEEDS_POKE;
|
|
|
|
|
1999-10-30 01:58:02 +00:00
|
|
|
if (nh != NULL)
|
|
|
|
free_adbnamehook(adb, &nh);
|
|
|
|
|
|
|
|
if (addr_bucket != DNS_ADB_INVALIDBUCKET)
|
|
|
|
UNLOCK(&adb->entrylocks[addr_bucket]);
|
|
|
|
}
|
|
|
|
|
1999-10-26 23:44:36 +00:00
|
|
|
/*
|
|
|
|
* Requires the name's bucket be locked.
|
|
|
|
*/
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
|
1999-10-26 23:44:36 +00:00
|
|
|
dns_adbname_t *name;
|
1999-10-29 01:26:45 +00:00
|
|
|
dns_adb_t *adb;
|
1999-10-26 23:44:36 +00:00
|
|
|
|
|
|
|
INSIST(n != NULL);
|
|
|
|
name = *n;
|
|
|
|
*n = NULL;
|
|
|
|
INSIST(DNS_ADBNAME_VALID(name));
|
1999-10-29 01:26:45 +00:00
|
|
|
adb = name->adb;
|
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
1999-10-26 23:44:36 +00:00
|
|
|
|
1999-11-01 20:16:35 +00:00
|
|
|
DP(DEF_LEVEL, "killing name %p", name);
|
1999-10-27 19:36:58 +00:00
|
|
|
|
1999-10-26 23:57:38 +00:00
|
|
|
/*
|
|
|
|
* If we're dead already, just check to see if we should go
|
|
|
|
* away now or not.
|
|
|
|
*/
|
1999-11-02 18:36:54 +00:00
|
|
|
if (NAME_DEAD(name) && !NAME_FETCH(name)) {
|
1999-10-26 23:57:38 +00:00
|
|
|
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.
|
|
|
|
*/
|
1999-10-30 01:58:02 +00:00
|
|
|
clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK);
|
1999-10-29 01:26:45 +00:00
|
|
|
clean_namehooks(adb, &name->v4);
|
|
|
|
clean_namehooks(adb, &name->v6);
|
2000-01-19 01:43:58 +00:00
|
|
|
clean_target(adb, &name->target);
|
1999-10-26 23:44:36 +00:00
|
|
|
|
1999-10-26 23:57:38 +00:00
|
|
|
/*
|
|
|
|
* If fetches are running, cancel them. If none are running, we can
|
|
|
|
* just kill the name here.
|
|
|
|
*/
|
1999-11-02 18:36:54 +00:00
|
|
|
if (!NAME_FETCH(name)) {
|
1999-10-26 23:44:36 +00:00
|
|
|
unlink_name(adb, name);
|
|
|
|
free_adbname(adb, &name);
|
|
|
|
} else {
|
1999-10-30 01:58:02 +00:00
|
|
|
name->flags |= NAME_IS_DEAD;
|
2000-01-21 02:50:27 +00:00
|
|
|
cancel_fetches_at_name(name);
|
1999-10-26 23:44:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-10-29 01:26:45 +00:00
|
|
|
/*
|
|
|
|
* Requires the name's bucket be locked and no entry buckets be locked.
|
|
|
|
*/
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) {
|
1999-10-29 01:26:45 +00:00
|
|
|
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
|
|
|
|
*/
|
1999-11-04 06:46:05 +00:00
|
|
|
if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) {
|
1999-11-04 08:48:47 +00:00
|
|
|
if (NAME_HAS_V4(name)) {
|
1999-11-04 08:35:45 +00:00
|
|
|
DP(DEF_LEVEL, "expiring v4 for name %p", name);
|
|
|
|
clean_namehooks(adb, &name->v4);
|
1999-11-04 08:50:12 +00:00
|
|
|
name->partial_result &= ~DNS_ADBFIND_INET;
|
1999-11-04 08:35:45 +00:00
|
|
|
}
|
1999-11-04 06:46:05 +00:00
|
|
|
name->expire_v4 = INT_MAX;
|
1999-10-29 21:48:51 +00:00
|
|
|
}
|
|
|
|
|
1999-10-29 01:26:45 +00:00
|
|
|
/*
|
|
|
|
* Check to see if we need to remove the v6 addresses
|
|
|
|
*/
|
1999-11-04 06:46:05 +00:00
|
|
|
if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) {
|
1999-11-04 08:48:47 +00:00
|
|
|
if (NAME_HAS_V6(name)) {
|
1999-11-04 08:35:45 +00:00
|
|
|
DP(DEF_LEVEL, "expiring v6 for name %p", name);
|
|
|
|
clean_namehooks(adb, &name->v6);
|
1999-11-04 08:50:12 +00:00
|
|
|
name->partial_result &= ~DNS_ADBFIND_INET6;
|
1999-11-04 08:35:45 +00:00
|
|
|
}
|
1999-11-04 06:46:05 +00:00
|
|
|
name->expire_v6 = INT_MAX;
|
1999-10-29 21:48:51 +00:00
|
|
|
}
|
2000-01-19 01:43:58 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
1999-10-29 01:26:45 +00:00
|
|
|
}
|
|
|
|
|
1999-10-26 23:44:36 +00:00
|
|
|
/*
|
|
|
|
* Requires the name's bucket be locked.
|
|
|
|
*/
|
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
link_name(dns_adb_t *adb, int bucket, dns_adbname_t *name) {
|
1999-10-26 23:44:36 +00:00
|
|
|
INSIST(name->lock_bucket == DNS_ADB_INVALIDBUCKET);
|
|
|
|
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LIST_PREPEND(adb->names[bucket], name, plink);
|
1999-10-26 23:44:36 +00:00
|
|
|
name->lock_bucket = bucket;
|
|
|
|
adb->name_refcnt[bucket]++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Requires the name's bucket be locked.
|
|
|
|
*/
|
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
unlink_name(dns_adb_t *adb, dns_adbname_t *name) {
|
1999-10-26 23:44:36 +00:00
|
|
|
int bucket;
|
|
|
|
|
|
|
|
bucket = name->lock_bucket;
|
|
|
|
INSIST(bucket != DNS_ADB_INVALIDBUCKET);
|
|
|
|
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LIST_UNLINK(adb->names[bucket], name, plink);
|
1999-10-26 23:44:36 +00:00
|
|
|
name->lock_bucket = DNS_ADB_INVALIDBUCKET;
|
|
|
|
INSIST(adb->name_refcnt[bucket] > 0);
|
|
|
|
adb->name_refcnt[bucket]--;
|
2000-01-13 20:42:43 +00:00
|
|
|
if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0)
|
|
|
|
dec_adb_irefcnt(adb);
|
1999-10-26 23:44:36 +00:00
|
|
|
}
|
1999-10-22 05:19:42 +00:00
|
|
|
|
2000-01-12 03:00:33 +00:00
|
|
|
/*
|
|
|
|
* Requires the entry's bucket be locked.
|
|
|
|
*/
|
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) {
|
2000-01-12 03:00:33 +00:00
|
|
|
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
|
2000-05-08 14:38:29 +00:00
|
|
|
unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) {
|
2000-01-12 03:00:33 +00:00
|
|
|
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]--;
|
2000-01-13 20:42:43 +00:00
|
|
|
if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0)
|
|
|
|
dec_adb_irefcnt(adb);
|
2000-01-12 03:00:33 +00:00
|
|
|
}
|
|
|
|
|
1999-10-19 01:37:22 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) {
|
1999-10-19 01:37:22 +00:00
|
|
|
if (isc_mutex_trylock(want) != ISC_R_SUCCESS) {
|
|
|
|
UNLOCK(have);
|
|
|
|
LOCK(want);
|
|
|
|
LOCK(have);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-10-22 05:19:42 +00:00
|
|
|
* The ADB _MUST_ be locked before calling. Also, exit conditions must be
|
|
|
|
* checked after calling this function.
|
1999-10-19 01:37:22 +00:00
|
|
|
*/
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
shutdown_names(dns_adb_t *adb) {
|
1999-10-19 01:37:22 +00:00
|
|
|
int bucket;
|
|
|
|
dns_adbname_t *name;
|
1999-10-26 23:44:36 +00:00
|
|
|
dns_adbname_t *next_name;
|
1999-10-19 01:37:22 +00:00
|
|
|
|
1999-11-05 02:05:06 +00:00
|
|
|
for (bucket = 0 ; bucket < NBUCKETS ; bucket++) {
|
1999-10-19 01:37:22 +00:00
|
|
|
LOCK(&adb->namelocks[bucket]);
|
|
|
|
adb->name_sd[bucket] = ISC_TRUE;
|
|
|
|
|
|
|
|
name = ISC_LIST_HEAD(adb->names[bucket]);
|
2000-01-13 20:42:43 +00:00
|
|
|
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;
|
|
|
|
}
|
1999-10-19 01:37:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UNLOCK(&adb->namelocks[bucket]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-01-12 03:00:33 +00:00
|
|
|
/*
|
|
|
|
* The ADB _MUST_ be locked before calling. Also, exit conditions must be
|
|
|
|
* checked after calling this function.
|
|
|
|
*/
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
shutdown_entries(dns_adb_t *adb) {
|
2000-01-12 03:00:33 +00:00
|
|
|
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]);
|
2000-01-13 20:42:43 +00:00
|
|
|
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;
|
2000-01-12 03:00:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-01-12 22:22:20 +00:00
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
2000-01-12 03:00:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-10-26 23:44:36 +00:00
|
|
|
/*
|
|
|
|
* Name bucket must be locked
|
|
|
|
*/
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
cancel_fetches_at_name(dns_adbname_t *name) {
|
1999-11-02 00:29:45 +00:00
|
|
|
dns_adbfetch6_t *fetch6;
|
|
|
|
|
1999-11-02 18:36:54 +00:00
|
|
|
if (NAME_FETCH_A(name))
|
2000-01-21 02:50:27 +00:00
|
|
|
dns_resolver_cancelfetch(name->fetch_a->fetch);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-10-26 23:44:36 +00:00
|
|
|
|
1999-11-02 18:36:54 +00:00
|
|
|
if (NAME_FETCH_AAAA(name))
|
2000-01-21 02:50:27 +00:00
|
|
|
dns_resolver_cancelfetch(name->fetch_aaaa->fetch);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-11-02 00:29:45 +00:00
|
|
|
|
|
|
|
fetch6 = ISC_LIST_HEAD(name->fetches_a6);
|
|
|
|
while (fetch6 != NULL) {
|
2000-01-21 02:50:27 +00:00
|
|
|
dns_resolver_cancelfetch(fetch6->fetch);
|
1999-11-02 00:29:45 +00:00
|
|
|
fetch6 = ISC_LIST_NEXT(fetch6, plink);
|
|
|
|
}
|
1999-10-26 23:44:36 +00:00
|
|
|
}
|
|
|
|
|
1999-10-20 23:26:06 +00:00
|
|
|
/*
|
|
|
|
* Assumes the name bucket is locked.
|
|
|
|
*/
|
1999-10-19 01:37:22 +00:00
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
|
1999-10-19 01:37:22 +00:00
|
|
|
dns_adbentry_t *entry;
|
|
|
|
dns_adbnamehook_t *namehook;
|
|
|
|
int addr_bucket;
|
|
|
|
|
|
|
|
addr_bucket = DNS_ADB_INVALIDBUCKET;
|
1999-10-29 01:26:45 +00:00
|
|
|
namehook = ISC_LIST_HEAD(*namehooks);
|
1999-10-19 01:37:22 +00:00
|
|
|
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;
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LIST_UNLINK(*namehooks, namehook, plink);
|
1999-10-19 01:37:22 +00:00
|
|
|
free_adbnamehook(adb, &namehook);
|
|
|
|
|
1999-10-29 01:26:45 +00:00
|
|
|
namehook = ISC_LIST_HEAD(*namehooks);
|
1999-10-19 01:37:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (addr_bucket != DNS_ADB_INVALIDBUCKET)
|
|
|
|
UNLOCK(&adb->entrylocks[addr_bucket]);
|
|
|
|
}
|
|
|
|
|
2000-01-19 01:43:58 +00:00
|
|
|
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;
|
|
|
|
|
2000-01-21 02:50:27 +00:00
|
|
|
REQUIRE(dns_name_countlabels(target) == 0);
|
|
|
|
|
2000-01-19 01:43:58 +00:00
|
|
|
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.
|
|
|
|
*/
|
|
|
|
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);
|
|
|
|
/*
|
|
|
|
* Construct the new target name.
|
|
|
|
*/
|
|
|
|
dns_fixedname_init(&fixed1);
|
|
|
|
prefix = dns_fixedname_name(&fixed1);
|
|
|
|
dns_fixedname_init(&fixed2);
|
|
|
|
new_target = dns_fixedname_name(&fixed2);
|
|
|
|
result = dns_name_split(name, nlabels, nbits, prefix, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
result = dns_name_concatenate(prefix, &tname, new_target,
|
|
|
|
NULL);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
result = dns_name_dup(new_target, adb->mctx, target);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
1999-10-29 18:00:31 +00:00
|
|
|
/*
|
|
|
|
* Assumes nothing is locked, since this is called by the client.
|
|
|
|
*/
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
event_free(isc_event_t *event) {
|
1999-10-29 18:30:48 +00:00
|
|
|
dns_adbfind_t *find;
|
1999-10-29 18:00:31 +00:00
|
|
|
|
|
|
|
INSIST(event != NULL);
|
2000-04-17 19:22:44 +00:00
|
|
|
find = event->ev_destroy_arg;
|
1999-10-29 18:30:48 +00:00
|
|
|
INSIST(DNS_ADBFIND_VALID(find));
|
1999-10-29 18:00:31 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
LOCK(&find->lock);
|
|
|
|
find->flags |= FIND_EVENT_FREED;
|
2000-04-17 19:22:44 +00:00
|
|
|
event->ev_destroy_arg = NULL;
|
1999-10-29 18:30:48 +00:00
|
|
|
UNLOCK(&find->lock);
|
1999-10-29 18:00:31 +00:00
|
|
|
}
|
|
|
|
|
1999-10-20 23:26:06 +00:00
|
|
|
/*
|
|
|
|
* Assumes the name bucket is locked.
|
|
|
|
*/
|
1999-10-19 01:37:22 +00:00
|
|
|
static void
|
1999-10-30 01:58:02 +00:00
|
|
|
clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
|
|
|
|
unsigned int addrs)
|
1999-10-19 01:37:22 +00:00
|
|
|
{
|
|
|
|
isc_event_t *ev;
|
|
|
|
isc_task_t *task;
|
1999-10-29 18:30:48 +00:00
|
|
|
dns_adbfind_t *find;
|
1999-10-30 01:58:02 +00:00
|
|
|
dns_adbfind_t *next_find;
|
1999-11-01 20:16:35 +00:00
|
|
|
isc_boolean_t process;
|
|
|
|
unsigned int wanted;
|
|
|
|
|
|
|
|
DP(ENTER_LEVEL,
|
|
|
|
"ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x",
|
|
|
|
name, evtype, addrs);
|
1999-10-19 01:37:22 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
find = ISC_LIST_HEAD(name->finds);
|
|
|
|
while (find != NULL) {
|
|
|
|
LOCK(&find->lock);
|
1999-10-30 01:58:02 +00:00
|
|
|
next_find = ISC_LIST_NEXT(find, plink);
|
1999-10-19 01:37:22 +00:00
|
|
|
|
1999-11-01 20:16:35 +00:00
|
|
|
process = ISC_FALSE;
|
|
|
|
wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
|
|
|
|
|
|
|
|
switch (evtype) {
|
|
|
|
case DNS_EVENT_ADBMOREADDRESSES:
|
1999-11-23 20:52:34 +00:00
|
|
|
DP(3, "DNS_EVENT_ADBMOREADDRESSES");
|
1999-11-01 20:16:35 +00:00
|
|
|
if ((wanted & addrs) != 0) {
|
1999-11-23 20:52:34 +00:00
|
|
|
DP(3, "processing");
|
1999-11-01 20:16:35 +00:00
|
|
|
find->flags &= ~addrs;
|
|
|
|
process = ISC_TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DNS_EVENT_ADBNOMOREADDRESSES:
|
1999-11-23 20:52:34 +00:00
|
|
|
DP(3, "DNS_EVENT_ADBNOMOREADDRESSES");
|
1999-11-01 20:16:35 +00:00
|
|
|
find->flags &= ~addrs;
|
|
|
|
wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
|
|
|
|
if (wanted == 0) {
|
|
|
|
process = ISC_TRUE;
|
1999-11-23 20:52:34 +00:00
|
|
|
DP(3, "processing");
|
1999-11-01 20:16:35 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
find->flags &= ~addrs;
|
|
|
|
process = ISC_TRUE;
|
1999-10-30 01:58:02 +00:00
|
|
|
}
|
1999-10-19 01:37:22 +00:00
|
|
|
|
1999-11-01 20:16:35 +00:00
|
|
|
if (process) {
|
|
|
|
DP(DEF_LEVEL, "cfan: processing find %p", find);
|
|
|
|
/*
|
|
|
|
* Unlink the find from the name, letting the caller
|
|
|
|
* call dns_adb_destroyfind() on it to clean it up
|
|
|
|
* later.
|
|
|
|
*/
|
|
|
|
ISC_LIST_UNLINK(name->finds, find, plink);
|
|
|
|
find->adbname = NULL;
|
|
|
|
find->name_bucket = DNS_ADB_INVALIDBUCKET;
|
1999-10-29 18:00:31 +00:00
|
|
|
|
1999-11-04 08:48:47 +00:00
|
|
|
INSIST(!FIND_EVENTSENT(find));
|
1999-10-29 03:05:24 +00:00
|
|
|
|
1999-11-01 20:16:35 +00:00
|
|
|
ev = &find->event;
|
2000-04-17 19:22:44 +00:00
|
|
|
task = ev->ev_sender;
|
|
|
|
ev->ev_sender = find;
|
|
|
|
ev->ev_type = evtype;
|
|
|
|
ev->ev_destroy = event_free;
|
|
|
|
ev->ev_destroy_arg = find;
|
1999-10-29 03:05:24 +00:00
|
|
|
|
1999-11-01 20:16:35 +00:00
|
|
|
DP(DEF_LEVEL,
|
|
|
|
"Sending event %p to task %p for find %p",
|
|
|
|
ev, task, find);
|
|
|
|
|
|
|
|
isc_task_sendanddetach(&task, &ev);
|
|
|
|
} else {
|
|
|
|
DP(DEF_LEVEL, "cfan: skipping find %p", find);
|
|
|
|
}
|
1999-10-27 19:36:58 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
UNLOCK(&find->lock);
|
1999-10-30 01:58:02 +00:00
|
|
|
find = next_find;
|
1999-10-19 01:37:22 +00:00
|
|
|
}
|
1999-11-01 20:16:35 +00:00
|
|
|
|
|
|
|
DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name);
|
1999-10-19 01:37:22 +00:00
|
|
|
}
|
|
|
|
|
1999-10-26 23:44:36 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
check_exit(dns_adb_t *adb) {
|
2000-04-17 19:22:44 +00:00
|
|
|
isc_event_t *event;
|
1999-11-22 19:57:58 +00:00
|
|
|
isc_task_t *etask;
|
2000-01-13 20:42:43 +00:00
|
|
|
isc_boolean_t zeroirefcnt;
|
1999-11-22 19:57:58 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The caller must be holding the adb lock.
|
|
|
|
*/
|
|
|
|
|
2000-01-13 20:42:43 +00:00
|
|
|
LOCK(&adb->ilock);
|
|
|
|
if (adb->irefcnt == 0)
|
|
|
|
zeroirefcnt = ISC_TRUE;
|
|
|
|
else
|
|
|
|
zeroirefcnt = ISC_FALSE;
|
|
|
|
UNLOCK(&adb->ilock);
|
|
|
|
|
|
|
|
if (adb->shutting_down && zeroirefcnt &&
|
1999-11-22 19:57:58 +00:00
|
|
|
isc_mempool_getallocated(adb->ahmp) == 0) {
|
|
|
|
/*
|
|
|
|
* We're now shutdown. Send any whenshutdown events.
|
|
|
|
*/
|
2000-04-17 19:22:44 +00:00
|
|
|
event = ISC_LIST_HEAD(adb->whenshutdown);
|
|
|
|
while (event != NULL) {
|
|
|
|
ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link);
|
|
|
|
etask = event->ev_sender;
|
|
|
|
event->ev_sender = adb;
|
1999-11-22 19:57:58 +00:00
|
|
|
isc_task_sendanddetach(&etask, &event);
|
2000-04-17 19:22:44 +00:00
|
|
|
event = ISC_LIST_HEAD(adb->whenshutdown);
|
1999-11-22 19:57:58 +00:00
|
|
|
}
|
2000-04-17 19:22:44 +00:00
|
|
|
|
1999-11-22 19:57:58 +00:00
|
|
|
/*
|
|
|
|
* If there aren't any external references either, we're
|
|
|
|
* done. Send the control event to initiate shutdown.
|
|
|
|
*/
|
|
|
|
if (adb->erefcnt == 0) {
|
|
|
|
INSIST(!adb->cevent_sent); /* Sanity check. */
|
|
|
|
event = &adb->cevent;
|
|
|
|
isc_task_send(adb->task, &event);
|
|
|
|
adb->cevent_sent = ISC_TRUE;
|
|
|
|
}
|
|
|
|
}
|
1999-10-22 05:19:42 +00:00
|
|
|
}
|
|
|
|
|
1999-10-19 01:37:22 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
dec_adb_irefcnt(dns_adb_t *adb) {
|
2000-01-13 20:42:43 +00:00
|
|
|
LOCK(&adb->ilock);
|
1999-10-19 01:37:22 +00:00
|
|
|
|
|
|
|
INSIST(adb->irefcnt > 0);
|
|
|
|
adb->irefcnt--;
|
|
|
|
|
2000-01-13 20:42:43 +00:00
|
|
|
UNLOCK(&adb->ilock);
|
1999-10-19 01:37:22 +00:00
|
|
|
}
|
1999-10-05 23:50:43 +00:00
|
|
|
|
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
inc_adb_erefcnt(dns_adb_t *adb, isc_boolean_t lock) {
|
1999-10-05 23:50:43 +00:00
|
|
|
if (lock)
|
|
|
|
LOCK(&adb->lock);
|
|
|
|
|
1999-10-19 01:37:22 +00:00
|
|
|
adb->erefcnt++;
|
1999-10-05 23:50:43 +00:00
|
|
|
|
|
|
|
if (lock)
|
|
|
|
UNLOCK(&adb->lock);
|
|
|
|
}
|
|
|
|
|
1999-10-26 23:44:36 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
dec_adb_erefcnt(dns_adb_t *adb, isc_boolean_t lock) {
|
1999-10-05 23:50:43 +00:00
|
|
|
if (lock)
|
|
|
|
LOCK(&adb->lock);
|
|
|
|
|
1999-10-19 01:37:22 +00:00
|
|
|
INSIST(adb->erefcnt > 0);
|
|
|
|
adb->erefcnt--;
|
1999-10-05 23:50:43 +00:00
|
|
|
|
2000-01-13 20:42:43 +00:00
|
|
|
if (adb->erefcnt == 0)
|
|
|
|
check_exit(adb);
|
1999-10-05 23:50:43 +00:00
|
|
|
|
|
|
|
if (lock)
|
|
|
|
UNLOCK(&adb->lock);
|
|
|
|
}
|
|
|
|
|
1999-10-08 23:12:21 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
inc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
|
1999-10-08 23:12:21 +00:00
|
|
|
int bucket;
|
|
|
|
|
|
|
|
bucket = entry->lock_bucket;
|
|
|
|
|
|
|
|
if (lock)
|
|
|
|
LOCK(&adb->entrylocks[bucket]);
|
|
|
|
|
|
|
|
entry->refcnt++;
|
|
|
|
|
|
|
|
if (lock)
|
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
dec_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
|
1999-10-08 23:12:21 +00:00
|
|
|
int bucket;
|
|
|
|
isc_boolean_t destroy_entry;
|
|
|
|
|
|
|
|
bucket = entry->lock_bucket;
|
|
|
|
|
|
|
|
if (lock)
|
|
|
|
LOCK(&adb->entrylocks[bucket]);
|
|
|
|
|
|
|
|
INSIST(entry->refcnt > 0);
|
|
|
|
entry->refcnt--;
|
|
|
|
|
|
|
|
destroy_entry = ISC_FALSE;
|
2000-01-21 02:50:27 +00:00
|
|
|
if (entry->refcnt == 0 &&
|
|
|
|
(adb->entry_sd[bucket] || entry->expires == 0)) {
|
1999-10-08 23:12:21 +00:00
|
|
|
destroy_entry = ISC_TRUE;
|
2000-01-12 03:00:33 +00:00
|
|
|
unlink_entry(adb, entry);
|
1999-10-08 23:12:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (lock)
|
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
|
|
|
|
|
|
|
if (!destroy_entry)
|
|
|
|
return;
|
|
|
|
|
|
|
|
entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
|
|
|
|
|
|
|
|
free_adbentry(adb, &entry);
|
|
|
|
}
|
|
|
|
|
1999-10-05 23:50:43 +00:00
|
|
|
static inline dns_adbname_t *
|
2000-05-08 14:38:29 +00:00
|
|
|
new_adbname(dns_adb_t *adb, dns_name_t *dnsname) {
|
1999-09-23 00:43:10 +00:00
|
|
|
dns_adbname_t *name;
|
|
|
|
|
|
|
|
name = isc_mempool_get(adb->nmp);
|
|
|
|
if (name == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
dns_name_init(&name->name, NULL);
|
1999-10-19 20:55:04 +00:00
|
|
|
if (dns_name_dup(dnsname, adb->mctx, &name->name) != ISC_R_SUCCESS) {
|
|
|
|
isc_mempool_put(adb->nmp, name);
|
|
|
|
return (NULL);
|
|
|
|
}
|
2000-01-19 01:43:58 +00:00
|
|
|
dns_name_init(&name->target, NULL);
|
1999-10-19 20:55:04 +00:00
|
|
|
name->magic = DNS_ADBNAME_MAGIC;
|
1999-10-27 19:36:58 +00:00
|
|
|
name->adb = adb;
|
1999-10-28 21:50:27 +00:00
|
|
|
name->partial_result = 0;
|
1999-10-30 01:58:02 +00:00
|
|
|
name->flags = 0;
|
1999-10-29 01:26:45 +00:00
|
|
|
name->expire_v4 = INT_MAX;
|
|
|
|
name->expire_v6 = INT_MAX;
|
2000-01-19 01:43:58 +00:00
|
|
|
name->expire_target = INT_MAX;
|
1999-10-30 01:22:16 +00:00
|
|
|
name->chains = 0;
|
1999-10-26 23:44:36 +00:00
|
|
|
name->lock_bucket = DNS_ADB_INVALIDBUCKET;
|
1999-10-29 01:26:45 +00:00
|
|
|
ISC_LIST_INIT(name->v4);
|
|
|
|
ISC_LIST_INIT(name->v6);
|
1999-10-29 21:48:51 +00:00
|
|
|
name->fetch_a = NULL;
|
|
|
|
name->fetch_aaaa = NULL;
|
1999-10-29 22:28:57 +00:00
|
|
|
ISC_LIST_INIT(name->fetches_a6);
|
1999-10-29 18:30:48 +00:00
|
|
|
ISC_LIST_INIT(name->finds);
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LINK_INIT(name, plink);
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
return (name);
|
|
|
|
}
|
|
|
|
|
1999-10-05 23:50:43 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
free_adbname(dns_adb_t *adb, dns_adbname_t **name) {
|
1999-10-02 01:59:09 +00:00
|
|
|
dns_adbname_t *n;
|
|
|
|
|
|
|
|
INSIST(name != NULL && DNS_ADBNAME_VALID(*name));
|
|
|
|
n = *name;
|
|
|
|
*name = NULL;
|
|
|
|
|
1999-11-04 08:48:47 +00:00
|
|
|
INSIST(!NAME_HAS_V4(n));
|
|
|
|
INSIST(!NAME_HAS_V6(n));
|
1999-11-02 18:36:54 +00:00
|
|
|
INSIST(!NAME_FETCH(n));
|
1999-10-29 18:30:48 +00:00
|
|
|
INSIST(ISC_LIST_EMPTY(n->finds));
|
1999-10-29 01:53:20 +00:00
|
|
|
INSIST(!ISC_LINK_LINKED(n, plink));
|
1999-10-26 23:44:36 +00:00
|
|
|
INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET);
|
1999-10-27 19:36:58 +00:00
|
|
|
INSIST(n->adb == adb);
|
1999-10-02 01:59:09 +00:00
|
|
|
|
|
|
|
n->magic = 0;
|
|
|
|
dns_name_free(&n->name, adb->mctx);
|
|
|
|
|
|
|
|
isc_mempool_put(adb->nmp, n);
|
|
|
|
}
|
|
|
|
|
1999-10-05 23:50:43 +00:00
|
|
|
static inline dns_adbnamehook_t *
|
2000-05-08 14:38:29 +00:00
|
|
|
new_adbnamehook(dns_adb_t *adb, dns_adbentry_t *entry) {
|
1999-09-23 00:43:10 +00:00
|
|
|
dns_adbnamehook_t *nh;
|
|
|
|
|
|
|
|
nh = isc_mempool_get(adb->nhmp);
|
|
|
|
if (nh == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
nh->magic = DNS_ADBNAMEHOOK_MAGIC;
|
|
|
|
nh->entry = entry;
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LINK_INIT(nh, plink);
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
return (nh);
|
|
|
|
}
|
|
|
|
|
1999-10-05 23:50:43 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
free_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) {
|
1999-10-02 01:59:09 +00:00
|
|
|
dns_adbnamehook_t *nh;
|
|
|
|
|
|
|
|
INSIST(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook));
|
|
|
|
nh = *namehook;
|
|
|
|
*namehook = NULL;
|
|
|
|
|
|
|
|
INSIST(nh->entry == NULL);
|
1999-10-29 01:53:20 +00:00
|
|
|
INSIST(!ISC_LINK_LINKED(nh, plink));
|
1999-10-02 01:59:09 +00:00
|
|
|
|
|
|
|
nh->magic = 0;
|
|
|
|
isc_mempool_put(adb->nhmp, nh);
|
|
|
|
}
|
|
|
|
|
1999-10-05 23:50:43 +00:00
|
|
|
static inline dns_adbzoneinfo_t *
|
2000-05-08 14:38:29 +00:00
|
|
|
new_adbzoneinfo(dns_adb_t *adb, dns_name_t *zone) {
|
1999-09-23 00:43:10 +00:00
|
|
|
dns_adbzoneinfo_t *zi;
|
|
|
|
|
|
|
|
zi = isc_mempool_get(adb->zimp);
|
|
|
|
if (zi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
1999-10-08 23:12:21 +00:00
|
|
|
dns_name_init(&zi->zone, NULL);
|
1999-10-19 21:10:29 +00:00
|
|
|
if (dns_name_dup(zone, adb->mctx, &zi->zone) != ISC_R_SUCCESS) {
|
|
|
|
isc_mempool_put(adb->zimp, zi);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
zi->magic = DNS_ADBZONEINFO_MAGIC;
|
1999-09-23 00:43:10 +00:00
|
|
|
zi->lame_timer = 0;
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LINK_INIT(zi, plink);
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
return (zi);
|
|
|
|
}
|
|
|
|
|
1999-10-08 23:12:21 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
free_adbzoneinfo(dns_adb_t *adb, dns_adbzoneinfo_t **zoneinfo) {
|
1999-10-08 23:12:21 +00:00
|
|
|
dns_adbzoneinfo_t *zi;
|
|
|
|
|
1999-10-14 00:50:00 +00:00
|
|
|
INSIST(zoneinfo != NULL && DNS_ADBZONEINFO_VALID(*zoneinfo));
|
1999-10-08 23:12:21 +00:00
|
|
|
zi = *zoneinfo;
|
|
|
|
*zoneinfo = NULL;
|
|
|
|
|
1999-10-29 01:53:20 +00:00
|
|
|
INSIST(!ISC_LINK_LINKED(zi, plink));
|
1999-10-08 23:12:21 +00:00
|
|
|
|
|
|
|
dns_name_free(&zi->zone, adb->mctx);
|
|
|
|
|
|
|
|
zi->magic = 0;
|
|
|
|
|
|
|
|
isc_mempool_put(adb->zimp, zi);
|
|
|
|
}
|
|
|
|
|
1999-10-05 23:50:43 +00:00
|
|
|
static inline dns_adbentry_t *
|
2000-05-08 14:38:29 +00:00
|
|
|
new_adbentry(dns_adb_t *adb) {
|
1999-09-23 00:43:10 +00:00
|
|
|
dns_adbentry_t *e;
|
1999-10-20 23:26:06 +00:00
|
|
|
isc_uint32_t r;
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
e = isc_mempool_get(adb->emp);
|
|
|
|
if (e == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
e->magic = DNS_ADBENTRY_MAGIC;
|
1999-10-02 01:59:09 +00:00
|
|
|
e->lock_bucket = DNS_ADB_INVALIDBUCKET;
|
1999-10-08 23:12:21 +00:00
|
|
|
e->refcnt = 0;
|
1999-09-23 00:43:10 +00:00
|
|
|
e->flags = 0;
|
2000-01-22 00:26:57 +00:00
|
|
|
e->edns_level = -1;
|
1999-09-23 00:43:10 +00:00
|
|
|
e->goodness = 0;
|
1999-10-20 23:26:06 +00:00
|
|
|
isc_random_get(&adb->rand, &r);
|
|
|
|
e->srtt = (r & 0x1f) + 1;
|
2000-01-12 03:00:33 +00:00
|
|
|
e->expires = 0;
|
2000-02-16 00:16:36 +00:00
|
|
|
e->avoid_bitstring = 0;
|
1999-09-23 00:43:10 +00:00
|
|
|
ISC_LIST_INIT(e->zoneinfo);
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LINK_INIT(e, plink);
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
return (e);
|
|
|
|
}
|
|
|
|
|
1999-10-05 23:50:43 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) {
|
1999-10-02 01:59:09 +00:00
|
|
|
dns_adbentry_t *e;
|
1999-10-19 21:42:56 +00:00
|
|
|
dns_adbzoneinfo_t *zi;
|
1999-10-14 00:50:00 +00:00
|
|
|
|
1999-10-02 01:59:09 +00:00
|
|
|
INSIST(entry != NULL && DNS_ADBENTRY_VALID(*entry));
|
|
|
|
e = *entry;
|
|
|
|
*entry = NULL;
|
|
|
|
|
|
|
|
INSIST(e->lock_bucket == DNS_ADB_INVALIDBUCKET);
|
1999-10-08 23:12:21 +00:00
|
|
|
INSIST(e->refcnt == 0);
|
1999-10-29 01:53:20 +00:00
|
|
|
INSIST(!ISC_LINK_LINKED(e, plink));
|
1999-10-02 01:59:09 +00:00
|
|
|
|
|
|
|
e->magic = 0;
|
1999-10-19 21:42:56 +00:00
|
|
|
|
|
|
|
zi = ISC_LIST_HEAD(e->zoneinfo);
|
|
|
|
while (zi != NULL) {
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LIST_UNLINK(e->zoneinfo, zi, plink);
|
1999-10-19 21:42:56 +00:00
|
|
|
free_adbzoneinfo(adb, &zi);
|
|
|
|
zi = ISC_LIST_HEAD(e->zoneinfo);
|
|
|
|
}
|
|
|
|
|
1999-10-02 01:59:09 +00:00
|
|
|
isc_mempool_put(adb->emp, e);
|
|
|
|
}
|
|
|
|
|
1999-10-29 18:07:32 +00:00
|
|
|
static inline dns_adbfind_t *
|
2000-05-08 14:38:29 +00:00
|
|
|
new_adbfind(dns_adb_t *adb) {
|
1999-10-29 18:07:32 +00:00
|
|
|
dns_adbfind_t *h;
|
1999-09-25 01:44:41 +00:00
|
|
|
isc_result_t result;
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
h = isc_mempool_get(adb->ahmp);
|
|
|
|
if (h == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
1999-09-25 01:44:41 +00:00
|
|
|
/*
|
2000-05-08 14:38:29 +00:00
|
|
|
* Public members.
|
1999-09-25 01:44:41 +00:00
|
|
|
*/
|
|
|
|
h->magic = 0;
|
1999-10-22 05:19:42 +00:00
|
|
|
h->adb = adb;
|
1999-10-28 21:50:27 +00:00
|
|
|
h->partial_result = 0;
|
1999-10-29 01:26:45 +00:00
|
|
|
h->options = 0;
|
1999-11-01 20:16:35 +00:00
|
|
|
h->flags = 0;
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LINK_INIT(h, publink);
|
1999-10-28 20:09:51 +00:00
|
|
|
ISC_LINK_INIT(h, plink);
|
1999-09-25 01:44:41 +00:00
|
|
|
ISC_LIST_INIT(h->list);
|
1999-10-14 00:50:00 +00:00
|
|
|
h->adbname = NULL;
|
1999-10-29 18:00:31 +00:00
|
|
|
h->name_bucket = DNS_ADB_INVALIDBUCKET;
|
1999-09-25 01:44:41 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* private members
|
|
|
|
*/
|
|
|
|
result = isc_mutex_init(&h->lock);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
1999-10-29 18:30:48 +00:00
|
|
|
"isc_mutex_init failed in new_adbfind()");
|
1999-09-25 01:44:41 +00:00
|
|
|
isc_mempool_put(adb->ahmp, h);
|
|
|
|
return (NULL);
|
|
|
|
}
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
ISC_EVENT_INIT(&h->event, sizeof (isc_event_t), 0, 0, 0, NULL, NULL,
|
|
|
|
NULL, NULL, h);
|
|
|
|
|
1999-10-29 18:07:32 +00:00
|
|
|
h->magic = DNS_ADBFIND_MAGIC;
|
1999-09-23 00:43:10 +00:00
|
|
|
return (h);
|
|
|
|
}
|
|
|
|
|
1999-10-25 21:02:54 +00:00
|
|
|
static inline dns_adbfetch_t *
|
2000-05-08 14:38:29 +00:00
|
|
|
new_adbfetch(dns_adb_t *adb) {
|
1999-10-25 21:02:54 +00:00
|
|
|
dns_adbfetch_t *f;
|
|
|
|
|
|
|
|
f = isc_mempool_get(adb->afmp);
|
|
|
|
if (f == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
f->magic = 0;
|
|
|
|
f->namehook = NULL;
|
|
|
|
f->entry = NULL;
|
|
|
|
f->fetch = NULL;
|
|
|
|
|
|
|
|
f->namehook = new_adbnamehook(adb, NULL);
|
|
|
|
if (f->namehook == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
f->entry = new_adbentry(adb);
|
|
|
|
if (f->entry == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
dns_rdataset_init(&f->rdataset);
|
|
|
|
|
|
|
|
f->magic = DNS_ADBFETCH_MAGIC;
|
|
|
|
|
|
|
|
return (f);
|
|
|
|
|
|
|
|
err:
|
|
|
|
if (f->namehook != NULL)
|
|
|
|
free_adbnamehook(adb, &f->namehook);
|
|
|
|
if (f->entry != NULL)
|
|
|
|
free_adbentry(adb, &f->entry);
|
|
|
|
isc_mempool_put(adb->afmp, f);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
free_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch) {
|
1999-10-25 21:02:54 +00:00
|
|
|
dns_adbfetch_t *f;
|
|
|
|
|
|
|
|
INSIST(fetch != NULL && DNS_ADBFETCH_VALID(*fetch));
|
|
|
|
f = *fetch;
|
|
|
|
*fetch = NULL;
|
|
|
|
|
|
|
|
f->magic = 0;
|
|
|
|
|
|
|
|
if (f->namehook != NULL)
|
|
|
|
free_adbnamehook(adb, &f->namehook);
|
|
|
|
if (f->entry != NULL)
|
|
|
|
free_adbentry(adb, &f->entry);
|
|
|
|
|
1999-10-28 00:37:31 +00:00
|
|
|
if (dns_rdataset_isassociated(&f->rdataset))
|
|
|
|
dns_rdataset_disassociate(&f->rdataset);
|
1999-10-25 21:02:54 +00:00
|
|
|
|
|
|
|
isc_mempool_put(adb->afmp, f);
|
|
|
|
}
|
|
|
|
|
1999-10-30 01:22:16 +00:00
|
|
|
/*
|
|
|
|
* Caller must be holding the name lock.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
1999-11-22 19:57:58 +00:00
|
|
|
a6find(void *arg, dns_name_t *a6name, dns_rdatatype_t type, isc_stdtime_t now,
|
|
|
|
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
|
|
|
|
{
|
1999-10-30 01:22:16 +00:00
|
|
|
dns_adbname_t *name;
|
|
|
|
dns_adb_t *adb;
|
|
|
|
|
|
|
|
name = arg;
|
|
|
|
INSIST(DNS_ADBNAME_VALID(name));
|
|
|
|
adb = name->adb;
|
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-01-15 00:45:49 +00:00
|
|
|
return (dns_view_simplefind(adb->view, a6name, type, now,
|
|
|
|
DNS_DBFIND_GLUEOK, ISC_FALSE,
|
|
|
|
rdataset, sigrdataset));
|
1999-10-30 01:22:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Caller must be holding the name lock.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
a6missing(dns_a6context_t *a6ctx, dns_name_t *a6name) {
|
|
|
|
dns_adbname_t *name;
|
|
|
|
dns_adb_t *adb;
|
|
|
|
dns_adbfetch6_t *fetch;
|
|
|
|
isc_result_t result;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-10-30 01:22:16 +00:00
|
|
|
name = a6ctx->arg;
|
|
|
|
INSIST(DNS_ADBNAME_VALID(name));
|
|
|
|
adb = name->adb;
|
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
|
|
|
|
1999-10-30 02:26:03 +00:00
|
|
|
fetch = new_adbfetch6(adb, name, a6ctx);
|
1999-10-30 01:22:16 +00:00
|
|
|
if (fetch == NULL) {
|
|
|
|
name->partial_result |= DNS_ADBFIND_INET6;
|
|
|
|
return;
|
|
|
|
}
|
1999-11-22 19:57:58 +00:00
|
|
|
|
1999-10-30 01:22:16 +00:00
|
|
|
result = dns_resolver_createfetch(adb->view->resolver, a6name,
|
2000-01-19 01:43:58 +00:00
|
|
|
dns_rdatatype_a6,
|
|
|
|
NULL, NULL, NULL, 0,
|
1999-10-30 01:35:51 +00:00
|
|
|
adb->task, fetch_callback_a6,
|
1999-10-30 01:22:16 +00:00
|
|
|
name, &fetch->rdataset, NULL,
|
|
|
|
&fetch->fetch);
|
1999-10-30 01:35:51 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
name->chains = a6ctx->chains;
|
|
|
|
ISC_LIST_APPEND(name->fetches_a6, fetch, plink);
|
|
|
|
|
|
|
|
cleanup:
|
1999-10-30 01:22:16 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
free_adbfetch6(adb, &fetch);
|
|
|
|
name->partial_result |= DNS_ADBFIND_INET6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline dns_adbfetch6_t *
|
2000-05-08 14:38:29 +00:00
|
|
|
new_adbfetch6(dns_adb_t *adb, dns_adbname_t *name, dns_a6context_t *a6ctx) {
|
1999-10-30 01:22:16 +00:00
|
|
|
dns_adbfetch6_t *f;
|
|
|
|
|
|
|
|
f = isc_mempool_get(adb->af6mp);
|
|
|
|
if (f == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
f->magic = 0;
|
|
|
|
f->namehook = NULL;
|
|
|
|
f->entry = NULL;
|
|
|
|
f->fetch = NULL;
|
1999-11-02 00:29:45 +00:00
|
|
|
f->flags = 0;
|
1999-10-30 01:22:16 +00:00
|
|
|
|
|
|
|
f->namehook = new_adbnamehook(adb, NULL);
|
|
|
|
if (f->namehook == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
f->entry = new_adbentry(adb);
|
|
|
|
if (f->entry == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
dns_rdataset_init(&f->rdataset);
|
|
|
|
|
1999-10-30 03:41:34 +00:00
|
|
|
dns_a6_init(&f->a6ctx, a6find, NULL, import_a6,
|
|
|
|
a6missing, name);
|
1999-10-30 01:22:16 +00:00
|
|
|
if (a6ctx != NULL)
|
|
|
|
dns_a6_copy(a6ctx, &f->a6ctx);
|
|
|
|
|
|
|
|
f->magic = DNS_ADBFETCH6_MAGIC;
|
|
|
|
|
|
|
|
return (f);
|
|
|
|
|
|
|
|
err:
|
|
|
|
if (f->namehook != NULL)
|
|
|
|
free_adbnamehook(adb, &f->namehook);
|
|
|
|
if (f->entry != NULL)
|
|
|
|
free_adbentry(adb, &f->entry);
|
|
|
|
isc_mempool_put(adb->af6mp, f);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
free_adbfetch6(dns_adb_t *adb, dns_adbfetch6_t **fetch) {
|
1999-10-30 01:22:16 +00:00
|
|
|
dns_adbfetch6_t *f;
|
|
|
|
|
|
|
|
INSIST(fetch != NULL && DNS_ADBFETCH6_VALID(*fetch));
|
|
|
|
f = *fetch;
|
|
|
|
*fetch = NULL;
|
|
|
|
|
|
|
|
f->magic = 0;
|
|
|
|
|
|
|
|
if (f->namehook != NULL)
|
|
|
|
free_adbnamehook(adb, &f->namehook);
|
|
|
|
if (f->entry != NULL)
|
|
|
|
free_adbentry(adb, &f->entry);
|
|
|
|
|
|
|
|
if (dns_rdataset_isassociated(&f->rdataset))
|
|
|
|
dns_rdataset_disassociate(&f->rdataset);
|
|
|
|
|
|
|
|
isc_mempool_put(adb->af6mp, f);
|
|
|
|
}
|
|
|
|
|
1999-10-08 23:12:21 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
free_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) {
|
1999-10-29 18:30:48 +00:00
|
|
|
dns_adbfind_t *find;
|
1999-10-08 23:12:21 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
INSIST(findp != NULL && DNS_ADBFIND_VALID(*findp));
|
|
|
|
find = *findp;
|
|
|
|
*findp = NULL;
|
1999-10-08 23:12:21 +00:00
|
|
|
|
1999-11-04 08:48:47 +00:00
|
|
|
INSIST(!FIND_HAS_ADDRS(find));
|
1999-10-29 18:30:48 +00:00
|
|
|
INSIST(!ISC_LINK_LINKED(find, publink));
|
|
|
|
INSIST(!ISC_LINK_LINKED(find, plink));
|
|
|
|
INSIST(find->name_bucket == DNS_ADB_INVALIDBUCKET);
|
|
|
|
INSIST(find->adbname == NULL);
|
1999-10-14 00:50:00 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
find->magic = 0;
|
1999-10-08 23:12:21 +00:00
|
|
|
|
2000-08-26 01:37:00 +00:00
|
|
|
DESTROYLOCK(&find->lock);
|
1999-10-29 18:30:48 +00:00
|
|
|
isc_mempool_put(adb->ahmp, find);
|
1999-10-08 23:12:21 +00:00
|
|
|
}
|
|
|
|
|
1999-09-23 00:43:10 +00:00
|
|
|
/*
|
|
|
|
* Copy bits from the entry into the newly allocated addrinfo. The entry
|
|
|
|
* must be locked, and the reference count must be bumped up by one
|
|
|
|
* if this function returns a valid pointer.
|
1999-09-22 00:26:20 +00:00
|
|
|
*/
|
1999-10-05 23:50:43 +00:00
|
|
|
static inline dns_adbaddrinfo_t *
|
2000-06-01 00:30:58 +00:00
|
|
|
new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) {
|
1999-09-23 00:43:10 +00:00
|
|
|
dns_adbaddrinfo_t *ai;
|
|
|
|
|
|
|
|
ai = isc_mempool_get(adb->aimp);
|
|
|
|
if (ai == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
ai->magic = DNS_ADBADDRINFO_MAGIC;
|
2000-06-01 00:30:58 +00:00
|
|
|
ai->sockaddr = entry->sockaddr;
|
|
|
|
isc_sockaddr_setport(&ai->sockaddr, port);
|
1999-09-23 00:43:10 +00:00
|
|
|
ai->goodness = entry->goodness;
|
|
|
|
ai->srtt = entry->srtt;
|
|
|
|
ai->flags = entry->flags;
|
2000-02-16 00:16:36 +00:00
|
|
|
ai->avoid_bitstring = entry->avoid_bitstring;
|
1999-09-23 00:43:10 +00:00
|
|
|
ai->entry = entry;
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LINK_INIT(ai, publink);
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
return (ai);
|
|
|
|
}
|
|
|
|
|
1999-10-14 00:50:00 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
free_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) {
|
1999-10-14 00:50:00 +00:00
|
|
|
dns_adbaddrinfo_t *ai;
|
|
|
|
|
|
|
|
INSIST(ainfo != NULL && DNS_ADBADDRINFO_VALID(*ainfo));
|
|
|
|
ai = *ainfo;
|
|
|
|
*ainfo = NULL;
|
|
|
|
|
|
|
|
INSIST(ai->entry == NULL);
|
1999-10-29 01:53:20 +00:00
|
|
|
INSIST(!ISC_LINK_LINKED(ai, publink));
|
1999-10-14 00:50:00 +00:00
|
|
|
|
|
|
|
ai->magic = 0;
|
|
|
|
|
|
|
|
isc_mempool_put(adb->aimp, ai);
|
|
|
|
}
|
|
|
|
|
1999-09-23 00:43:10 +00:00
|
|
|
/*
|
|
|
|
* Search for the name. NOTE: The bucket is kept locked on both
|
|
|
|
* success and failure, so it must always be unlocked by the caller!
|
1999-10-02 01:59:09 +00:00
|
|
|
*
|
|
|
|
* On the first call to this function, *bucketp must be set to
|
|
|
|
* DNS_ADB_INVALIDBUCKET.
|
1999-09-23 00:43:10 +00:00
|
|
|
*/
|
1999-10-05 23:50:43 +00:00
|
|
|
static inline dns_adbname_t *
|
2000-02-02 23:24:04 +00:00
|
|
|
find_name_and_lock(dns_adb_t *adb, dns_name_t *name,
|
|
|
|
unsigned int options, int *bucketp)
|
1999-09-23 00:43:10 +00:00
|
|
|
{
|
|
|
|
dns_adbname_t *adbname;
|
1999-10-05 23:50:43 +00:00
|
|
|
int bucket;
|
1999-09-23 00:43:10 +00:00
|
|
|
|
1999-11-05 02:05:06 +00:00
|
|
|
bucket = dns_name_hash(name, ISC_FALSE) % NBUCKETS;
|
1999-09-23 00:43:10 +00:00
|
|
|
|
1999-10-05 23:50:43 +00:00
|
|
|
if (*bucketp == DNS_ADB_INVALIDBUCKET) {
|
|
|
|
LOCK(&adb->namelocks[bucket]);
|
|
|
|
*bucketp = bucket;
|
|
|
|
} else if (*bucketp != bucket) {
|
|
|
|
UNLOCK(&adb->namelocks[*bucketp]);
|
|
|
|
LOCK(&adb->namelocks[bucket]);
|
|
|
|
*bucketp = bucket;
|
|
|
|
}
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
adbname = ISC_LIST_HEAD(adb->names[bucket]);
|
|
|
|
while (adbname != NULL) {
|
1999-10-30 01:58:02 +00:00
|
|
|
if (!NAME_DEAD(adbname)) {
|
2000-02-02 23:24:04 +00:00
|
|
|
if (dns_name_equal(name, &adbname->name)
|
|
|
|
&& GLUEHINT_OK(adbname, options))
|
1999-10-26 23:44:36 +00:00
|
|
|
return (adbname);
|
|
|
|
}
|
1999-10-29 01:53:20 +00:00
|
|
|
adbname = ISC_LIST_NEXT(adbname, plink);
|
1999-09-23 00:43:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Search for the address. NOTE: The bucket is kept locked on both
|
1999-10-02 01:59:09 +00:00
|
|
|
* success and failure, so it must always be unlocked by the caller.
|
|
|
|
*
|
|
|
|
* On the first call to this function, *bucketp must be set to
|
|
|
|
* DNS_ADB_INVALIDBUCKET. This will cause a lock to occur. On
|
|
|
|
* later calls (within the same "lock path") it can be left alone, so
|
|
|
|
* if this function is called multiple times locking is only done if
|
|
|
|
* the bucket changes.
|
1999-09-23 00:43:10 +00:00
|
|
|
*/
|
1999-10-05 23:50:43 +00:00
|
|
|
static inline dns_adbentry_t *
|
2000-05-08 14:38:29 +00:00
|
|
|
find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp) {
|
1999-09-23 00:43:10 +00:00
|
|
|
dns_adbentry_t *entry;
|
1999-10-02 01:59:09 +00:00
|
|
|
int bucket;
|
1999-09-23 00:43:10 +00:00
|
|
|
|
1999-11-05 02:05:06 +00:00
|
|
|
bucket = isc_sockaddr_hash(addr, ISC_TRUE) % NBUCKETS;
|
1999-09-23 00:43:10 +00:00
|
|
|
|
1999-10-02 01:59:09 +00:00
|
|
|
if (*bucketp == DNS_ADB_INVALIDBUCKET) {
|
|
|
|
LOCK(&adb->entrylocks[bucket]);
|
|
|
|
*bucketp = bucket;
|
|
|
|
} else if (*bucketp != bucket) {
|
|
|
|
UNLOCK(&adb->entrylocks[*bucketp]);
|
|
|
|
LOCK(&adb->entrylocks[bucket]);
|
|
|
|
*bucketp = bucket;
|
|
|
|
}
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
entry = ISC_LIST_HEAD(adb->entries[bucket]);
|
|
|
|
while (entry != NULL) {
|
|
|
|
if (isc_sockaddr_equal(addr, &entry->sockaddr))
|
|
|
|
return (entry);
|
1999-10-29 01:53:20 +00:00
|
|
|
entry = ISC_LIST_NEXT(entry, plink);
|
1999-09-23 00:43:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (NULL);
|
|
|
|
}
|
1999-09-22 00:26:20 +00:00
|
|
|
|
1999-10-19 20:55:04 +00:00
|
|
|
/*
|
|
|
|
* Entry bucket MUST be locked!
|
|
|
|
*/
|
|
|
|
static isc_boolean_t
|
1999-10-20 23:26:06 +00:00
|
|
|
entry_is_bad_for_zone(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *zone,
|
|
|
|
isc_stdtime_t now)
|
1999-10-19 20:55:04 +00:00
|
|
|
{
|
|
|
|
dns_adbzoneinfo_t *zi, *next_zi;
|
|
|
|
isc_boolean_t is_bad;
|
|
|
|
|
|
|
|
is_bad = ISC_FALSE;
|
|
|
|
|
|
|
|
zi = ISC_LIST_HEAD(entry->zoneinfo);
|
|
|
|
if (zi == NULL)
|
|
|
|
return (ISC_FALSE);
|
|
|
|
while (zi != NULL) {
|
1999-10-29 01:53:20 +00:00
|
|
|
next_zi = ISC_LIST_NEXT(zi, plink);
|
1999-10-19 20:55:04 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Has the entry expired?
|
|
|
|
*/
|
|
|
|
if (zi->lame_timer < now) {
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LIST_UNLINK(entry->zoneinfo, zi, plink);
|
1999-10-19 20:55:04 +00:00
|
|
|
free_adbzoneinfo(adb, &zi);
|
|
|
|
}
|
|
|
|
|
1999-10-20 23:26:06 +00:00
|
|
|
/*
|
|
|
|
* Order tests from least to most expensive.
|
|
|
|
*/
|
|
|
|
if (zi != NULL && !is_bad) {
|
1999-10-19 20:55:04 +00:00
|
|
|
if (dns_name_equal(zone, &zi->zone))
|
|
|
|
is_bad = ISC_TRUE;
|
1999-10-20 23:26:06 +00:00
|
|
|
}
|
1999-10-19 20:55:04 +00:00
|
|
|
|
|
|
|
zi = next_zi;
|
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-10-19 20:55:04 +00:00
|
|
|
return (is_bad);
|
|
|
|
}
|
|
|
|
|
1999-10-08 23:12:21 +00:00
|
|
|
static void
|
1999-11-02 00:29:45 +00:00
|
|
|
copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *zone,
|
|
|
|
dns_adbname_t *name, isc_stdtime_t now)
|
1999-10-08 23:12:21 +00:00
|
|
|
{
|
|
|
|
dns_adbnamehook_t *namehook;
|
|
|
|
dns_adbaddrinfo_t *addrinfo;
|
2000-02-16 00:16:36 +00:00
|
|
|
dns_adbentry_t *entry;
|
1999-10-19 20:55:04 +00:00
|
|
|
int bucket;
|
1999-10-08 23:12:21 +00:00
|
|
|
|
1999-10-19 20:55:04 +00:00
|
|
|
bucket = DNS_ADB_INVALIDBUCKET;
|
1999-10-08 23:12:21 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
if (find->options & DNS_ADBFIND_INET) {
|
1999-10-29 01:26:45 +00:00
|
|
|
namehook = ISC_LIST_HEAD(name->v4);
|
|
|
|
while (namehook != NULL) {
|
2000-02-16 00:16:36 +00:00
|
|
|
entry = namehook->entry;
|
|
|
|
bucket = entry->lock_bucket;
|
1999-10-29 01:26:45 +00:00
|
|
|
LOCK(&adb->entrylocks[bucket]);
|
2000-02-16 00:16:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for avoid bitstring timeout.
|
|
|
|
*/
|
|
|
|
if (entry->avoid_bitstring > 0
|
|
|
|
&& entry->avoid_bitstring < now)
|
|
|
|
entry->avoid_bitstring = 0;
|
|
|
|
|
2000-02-02 23:27:39 +00:00
|
|
|
if (!FIND_RETURNLAME(find)
|
2000-02-16 00:16:36 +00:00
|
|
|
&& entry_is_bad_for_zone(adb, entry, zone, now)) {
|
2000-02-02 23:24:04 +00:00
|
|
|
find->options |= DNS_ADBFIND_LAMEPRUNED;
|
1999-10-29 01:26:45 +00:00
|
|
|
goto nextv4;
|
2000-02-02 23:24:04 +00:00
|
|
|
}
|
2000-06-01 00:30:58 +00:00
|
|
|
addrinfo = new_adbaddrinfo(adb, entry, find->port);
|
1999-10-29 01:26:45 +00:00
|
|
|
if (addrinfo == NULL) {
|
1999-10-29 18:30:48 +00:00
|
|
|
find->partial_result |= DNS_ADBFIND_INET;
|
1999-10-29 01:26:45 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/*
|
1999-10-29 18:30:48 +00:00
|
|
|
* Found a valid entry. Add it to the find's list.
|
1999-10-29 01:26:45 +00:00
|
|
|
*/
|
2000-02-16 00:16:36 +00:00
|
|
|
inc_entry_refcnt(adb, entry, ISC_FALSE);
|
1999-10-29 18:30:48 +00:00
|
|
|
ISC_LIST_APPEND(find->list, addrinfo, publink);
|
1999-10-29 01:26:45 +00:00
|
|
|
addrinfo = NULL;
|
|
|
|
nextv4:
|
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
|
|
|
bucket = DNS_ADB_INVALIDBUCKET;
|
1999-10-29 01:53:20 +00:00
|
|
|
namehook = ISC_LIST_NEXT(namehook, plink);
|
1999-10-29 01:26:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-10-29 21:48:51 +00:00
|
|
|
if (find->options & DNS_ADBFIND_INET6) {
|
1999-10-29 01:26:45 +00:00
|
|
|
namehook = ISC_LIST_HEAD(name->v6);
|
|
|
|
while (namehook != NULL) {
|
2000-02-16 00:16:36 +00:00
|
|
|
entry = namehook->entry;
|
|
|
|
bucket = entry->lock_bucket;
|
1999-10-29 01:26:45 +00:00
|
|
|
LOCK(&adb->entrylocks[bucket]);
|
2000-02-16 00:16:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for avoid bitstring timeout.
|
|
|
|
*/
|
|
|
|
if (entry->avoid_bitstring > 0
|
|
|
|
&& entry->avoid_bitstring < now)
|
|
|
|
entry->avoid_bitstring = 0;
|
|
|
|
|
|
|
|
if (entry_is_bad_for_zone(adb, entry, zone, now))
|
1999-10-29 01:26:45 +00:00
|
|
|
goto nextv6;
|
2000-06-01 00:30:58 +00:00
|
|
|
addrinfo = new_adbaddrinfo(adb, entry, find->port);
|
1999-10-29 01:26:45 +00:00
|
|
|
if (addrinfo == NULL) {
|
1999-10-29 21:48:51 +00:00
|
|
|
find->partial_result |= DNS_ADBFIND_INET6;
|
1999-10-29 01:26:45 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/*
|
1999-10-29 18:30:48 +00:00
|
|
|
* Found a valid entry. Add it to the find's list.
|
1999-10-29 01:26:45 +00:00
|
|
|
*/
|
2000-02-16 00:16:36 +00:00
|
|
|
inc_entry_refcnt(adb, entry, ISC_FALSE);
|
1999-10-29 18:30:48 +00:00
|
|
|
ISC_LIST_APPEND(find->list, addrinfo, publink);
|
1999-10-29 01:26:45 +00:00
|
|
|
addrinfo = NULL;
|
|
|
|
nextv6:
|
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
|
|
|
bucket = DNS_ADB_INVALIDBUCKET;
|
1999-10-29 01:53:20 +00:00
|
|
|
namehook = ISC_LIST_NEXT(namehook, plink);
|
1999-10-08 23:12:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-10-19 20:55:04 +00:00
|
|
|
out:
|
|
|
|
if (bucket != DNS_ADB_INVALIDBUCKET)
|
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
1999-10-08 23:12:21 +00:00
|
|
|
}
|
|
|
|
|
1999-10-25 23:07:14 +00:00
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
shutdown_task(isc_task_t *task, isc_event_t *ev) {
|
1999-10-25 23:07:14 +00:00
|
|
|
dns_adb_t *adb;
|
1999-10-25 23:18:19 +00:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
UNUSED(task);
|
1999-10-25 23:07:14 +00:00
|
|
|
|
2000-04-17 19:22:44 +00:00
|
|
|
adb = ev->ev_arg;
|
1999-10-25 23:07:14 +00:00
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Kill the timer, and then the ADB itself. Note that this implies
|
|
|
|
* that this task was the one scheduled to get timer events. If
|
|
|
|
* this is not true (and it is unfortunate there is no way to INSIST()
|
1999-11-22 19:57:58 +00:00
|
|
|
* this) badness will occur.
|
1999-10-25 23:07:14 +00:00
|
|
|
*/
|
|
|
|
LOCK(&adb->lock);
|
|
|
|
isc_timer_detach(&adb->timer);
|
|
|
|
UNLOCK(&adb->lock);
|
|
|
|
isc_event_free(&ev);
|
1999-11-22 19:57:58 +00:00
|
|
|
destroy(adb);
|
1999-10-25 23:07:14 +00:00
|
|
|
}
|
|
|
|
|
1999-10-25 22:53:15 +00:00
|
|
|
/*
|
1999-10-29 23:53:12 +00:00
|
|
|
* name bucket must be locked; adb may be locked; no other locks held.
|
1999-10-25 22:53:15 +00:00
|
|
|
*/
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
check_expire_name(dns_adbname_t **namep, isc_stdtime_t now) {
|
1999-10-29 23:53:12 +00:00
|
|
|
dns_adbname_t *name;
|
|
|
|
|
|
|
|
INSIST(namep != NULL && DNS_ADBNAME_VALID(*namep));
|
|
|
|
name = *namep;
|
|
|
|
|
1999-11-04 08:48:47 +00:00
|
|
|
if (NAME_HAS_V4(name) || NAME_HAS_V6(name))
|
1999-10-29 23:53:12 +00:00
|
|
|
return;
|
1999-11-02 18:36:54 +00:00
|
|
|
if (NAME_FETCH(name))
|
1999-10-29 23:53:12 +00:00
|
|
|
return;
|
1999-11-04 06:46:05 +00:00
|
|
|
if (!EXPIRE_OK(name->expire_v4, now))
|
|
|
|
return;
|
|
|
|
if (!EXPIRE_OK(name->expire_v6, now))
|
|
|
|
return;
|
2000-01-19 01:43:58 +00:00
|
|
|
if (!EXPIRE_OK(name->expire_target, now))
|
|
|
|
return;
|
1999-10-29 23:53:12 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The name is empty. Delete it.
|
|
|
|
*/
|
|
|
|
kill_name(&name, DNS_EVENT_ADBEXPIRED);
|
2000-02-18 03:53:00 +00:00
|
|
|
*namep = NULL;
|
2000-01-13 20:42:43 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Our caller, or one of its callers, will be calling check_exit() at
|
|
|
|
* some point, so we don't need to do it here.
|
|
|
|
*/
|
1999-10-29 23:53:12 +00:00
|
|
|
}
|
|
|
|
|
2000-01-12 03:00:33 +00:00
|
|
|
/*
|
|
|
|
* entry bucket must be locked; adb may be locked; no other locks held.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
check_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now)
|
|
|
|
{
|
|
|
|
dns_adbentry_t *entry;
|
|
|
|
|
|
|
|
INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp));
|
|
|
|
entry = *entryp;
|
|
|
|
|
|
|
|
if (entry->refcnt != 0)
|
|
|
|
return;
|
|
|
|
if (entry->expires == 0 || entry->expires > now)
|
|
|
|
return;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-01-12 03:00:33 +00:00
|
|
|
/*
|
|
|
|
* The entry is not in use. Delete it.
|
|
|
|
*/
|
|
|
|
DP(DEF_LEVEL, "killing entry %p", entry);
|
|
|
|
INSIST(ISC_LINK_LINKED(entry, plink));
|
|
|
|
unlink_entry(adb, entry);
|
|
|
|
free_adbentry(adb, &entry);
|
2000-02-18 03:53:00 +00:00
|
|
|
*entryp = NULL;
|
2000-01-12 03:00:33 +00:00
|
|
|
}
|
|
|
|
|
1999-10-29 23:53:12 +00:00
|
|
|
/*
|
|
|
|
* ADB must be locked, and no other locks held.
|
|
|
|
*/
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
cleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
|
1999-10-29 23:53:12 +00:00
|
|
|
dns_adbname_t *name;
|
|
|
|
dns_adbname_t *next_name;
|
|
|
|
|
2000-01-12 03:00:33 +00:00
|
|
|
DP(CLEAN_LEVEL, "cleaning name bucket %d", bucket);
|
1999-11-24 19:23:27 +00:00
|
|
|
|
1999-10-29 23:53:12 +00:00
|
|
|
LOCK(&adb->namelocks[bucket]);
|
|
|
|
if (adb->name_sd[bucket]) {
|
|
|
|
UNLOCK(&adb->namelocks[bucket]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
name = ISC_LIST_HEAD(adb->names[bucket]);
|
|
|
|
while (name != NULL) {
|
|
|
|
next_name = ISC_LIST_NEXT(name, plink);
|
|
|
|
check_expire_namehooks(name, now);
|
1999-11-04 06:46:05 +00:00
|
|
|
check_expire_name(&name, now);
|
1999-10-29 23:53:12 +00:00
|
|
|
name = next_name;
|
|
|
|
}
|
|
|
|
UNLOCK(&adb->namelocks[bucket]);
|
1999-10-25 22:53:15 +00:00
|
|
|
}
|
|
|
|
|
2000-01-12 03:00:33 +00:00
|
|
|
/*
|
|
|
|
* ADB must be locked, and no other locks held.
|
|
|
|
*/
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
cleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
|
2000-01-12 03:00:33 +00:00
|
|
|
dns_adbentry_t *entry, *next_entry;
|
2000-02-18 03:53:00 +00:00
|
|
|
int freq;
|
2000-01-12 03:00:33 +00:00
|
|
|
|
|
|
|
DP(CLEAN_LEVEL, "cleaning entry bucket %d", bucket);
|
|
|
|
|
2000-02-18 03:53:00 +00:00
|
|
|
freq = NBUCKETS / CLEAN_SECONDS;
|
|
|
|
REQUIRE(freq > 0);
|
|
|
|
|
2000-01-12 03:00:33 +00:00
|
|
|
LOCK(&adb->entrylocks[bucket]);
|
|
|
|
entry = ISC_LIST_HEAD(adb->entries[bucket]);
|
|
|
|
while (entry != NULL) {
|
|
|
|
next_entry = ISC_LIST_NEXT(entry, plink);
|
|
|
|
check_expire_entry(adb, &entry, now);
|
2000-02-18 03:53:00 +00:00
|
|
|
if (entry != NULL && entry->goodness != 0) {
|
|
|
|
if (entry->goodness > 0
|
|
|
|
&& entry->goodness < freq)
|
|
|
|
entry->goodness = 0;
|
|
|
|
else if (entry->goodness < 0
|
|
|
|
&& entry->goodness > -freq)
|
|
|
|
entry->goodness = 0;
|
|
|
|
else if (entry->goodness > 0)
|
|
|
|
entry->goodness -= freq;
|
|
|
|
else if (entry->goodness < 0)
|
|
|
|
entry->goodness += freq;
|
|
|
|
}
|
2000-01-12 03:00:33 +00:00
|
|
|
entry = next_entry;
|
|
|
|
}
|
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
|
|
|
}
|
|
|
|
|
1999-10-25 22:53:15 +00:00
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
timer_cleanup(isc_task_t *task, isc_event_t *ev) {
|
1999-10-25 22:53:15 +00:00
|
|
|
dns_adb_t *adb;
|
1999-10-29 23:53:12 +00:00
|
|
|
isc_stdtime_t now;
|
2000-02-18 03:53:00 +00:00
|
|
|
unsigned int i;
|
1999-10-25 22:53:15 +00:00
|
|
|
|
2000-02-18 03:53:00 +00:00
|
|
|
UNUSED(task);
|
1999-10-25 23:18:19 +00:00
|
|
|
|
2000-04-17 19:22:44 +00:00
|
|
|
adb = ev->ev_arg;
|
1999-10-25 22:53:15 +00:00
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
|
|
|
|
|
|
|
LOCK(&adb->lock);
|
|
|
|
|
1999-12-16 23:29:07 +00:00
|
|
|
isc_stdtime_get(&now);
|
1999-10-29 23:53:12 +00:00
|
|
|
|
2000-02-18 03:53:00 +00:00
|
|
|
for (i = 0 ; i < CLEAN_BUCKETS ; i++) {
|
|
|
|
/*
|
|
|
|
* Call our cleanup routines.
|
|
|
|
*/
|
|
|
|
cleanup_names(adb, adb->next_cleanbucket, now);
|
|
|
|
cleanup_entries(adb, adb->next_cleanbucket, now);
|
1999-10-29 23:53:12 +00:00
|
|
|
|
2000-02-18 03:53:00 +00:00
|
|
|
/*
|
|
|
|
* Set the next bucket to be cleaned.
|
|
|
|
*/
|
|
|
|
adb->next_cleanbucket++;
|
|
|
|
if (adb->next_cleanbucket >= NBUCKETS) {
|
|
|
|
adb->next_cleanbucket = 0;
|
1999-11-24 19:23:27 +00:00
|
|
|
#ifdef DUMP_ADB_AFTER_CLEANING
|
2000-02-18 03:53:00 +00:00
|
|
|
dump_adb(adb, stdout);
|
1999-11-24 19:23:27 +00:00
|
|
|
#endif
|
2000-02-18 03:53:00 +00:00
|
|
|
}
|
1999-11-24 19:23:27 +00:00
|
|
|
}
|
1999-10-29 23:53:12 +00:00
|
|
|
|
1999-10-25 22:53:15 +00:00
|
|
|
/*
|
|
|
|
* Reset the timer.
|
Silence IRIX warnings:
"adb.c", line 2042: remark(1552): variable "result" was set but never used
isc_result_t result;
^
"adb.c", line 3082: warning(1185): enumerated type mixed with another type
NAME_GLUEOK(adbname), NAME_HINTOK(adbname),
^
"adb.c", line 3187: warning(1185): enumerated type mixed with another type
now, NAME_GLUEOK(adbname), NAME_HINTOK(adbname),
Note that the first is in timer_cleanup, a function returning void in a context
that can't do anything with something other than void (as an isc_taskaction_t).
It calls isc_timer_reset, which could conceivably return ISC_R_NOMEMORY or
ISC_R_UNEXPECTED. For now the call has been cast to void, but someone
who knows the code better should have a look and see whether something more
intelligent could be done with an error (and, if not, remove my XXX and
make sure the comment is clear as to why ignoring the return is the
best that can be done).
2000-05-13 20:15:16 +00:00
|
|
|
* XXXDCL isc_timer_reset might return ISC_R_UNEXPECTED or
|
|
|
|
* ISC_R_NOMEMORY, but it isn't clear what could be done here
|
|
|
|
* if either one of those things happened.
|
1999-10-25 22:53:15 +00:00
|
|
|
*/
|
Silence IRIX warnings:
"adb.c", line 2042: remark(1552): variable "result" was set but never used
isc_result_t result;
^
"adb.c", line 3082: warning(1185): enumerated type mixed with another type
NAME_GLUEOK(adbname), NAME_HINTOK(adbname),
^
"adb.c", line 3187: warning(1185): enumerated type mixed with another type
now, NAME_GLUEOK(adbname), NAME_HINTOK(adbname),
Note that the first is in timer_cleanup, a function returning void in a context
that can't do anything with something other than void (as an isc_taskaction_t).
It calls isc_timer_reset, which could conceivably return ISC_R_NOMEMORY or
ISC_R_UNEXPECTED. For now the call has been cast to void, but someone
who knows the code better should have a look and see whether something more
intelligent could be done with an error (and, if not, remove my XXX and
make sure the comment is clear as to why ignoring the return is the
best that can be done).
2000-05-13 20:15:16 +00:00
|
|
|
(void)isc_timer_reset(adb->timer, isc_timertype_once, NULL,
|
|
|
|
&adb->tick_interval, ISC_FALSE);
|
1999-10-25 22:53:15 +00:00
|
|
|
|
|
|
|
UNLOCK(&adb->lock);
|
|
|
|
|
|
|
|
isc_event_free(&ev);
|
|
|
|
}
|
|
|
|
|
1999-09-24 23:54:42 +00:00
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
destroy(dns_adb_t *adb) {
|
1999-09-24 23:54:42 +00:00
|
|
|
adb->magic = 0;
|
|
|
|
|
1999-10-25 23:07:14 +00:00
|
|
|
/*
|
|
|
|
* The timer is already dead, from the task's shutdown callback.
|
|
|
|
*/
|
1999-10-25 22:53:15 +00:00
|
|
|
isc_task_detach(&adb->task);
|
|
|
|
|
1999-09-24 23:54:42 +00:00
|
|
|
isc_mempool_destroy(&adb->nmp);
|
|
|
|
isc_mempool_destroy(&adb->nhmp);
|
|
|
|
isc_mempool_destroy(&adb->zimp);
|
|
|
|
isc_mempool_destroy(&adb->emp);
|
|
|
|
isc_mempool_destroy(&adb->ahmp);
|
|
|
|
isc_mempool_destroy(&adb->aimp);
|
1999-10-25 21:02:54 +00:00
|
|
|
isc_mempool_destroy(&adb->afmp);
|
1999-10-30 01:58:02 +00:00
|
|
|
isc_mempool_destroy(&adb->af6mp);
|
1999-09-24 23:54:42 +00:00
|
|
|
|
1999-11-05 02:05:06 +00:00
|
|
|
isc_mutexblock_destroy(adb->entrylocks, NBUCKETS);
|
|
|
|
isc_mutexblock_destroy(adb->namelocks, NBUCKETS);
|
1999-09-24 23:54:42 +00:00
|
|
|
|
2000-08-26 01:37:00 +00:00
|
|
|
DESTROYLOCK(&adb->ilock);
|
|
|
|
DESTROYLOCK(&adb->lock);
|
|
|
|
DESTROYLOCK(&adb->mplock);
|
1999-09-24 23:54:42 +00:00
|
|
|
|
1999-10-20 23:26:06 +00:00
|
|
|
isc_random_invalidate(&adb->rand);
|
|
|
|
|
1999-09-24 23:54:42 +00:00
|
|
|
isc_mem_put(adb->mctx, adb, sizeof (dns_adb_t));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-09-22 00:26:20 +00:00
|
|
|
/*
|
|
|
|
* Public functions.
|
|
|
|
*/
|
|
|
|
|
1999-09-21 22:46:42 +00:00
|
|
|
isc_result_t
|
1999-10-25 21:40:56 +00:00
|
|
|
dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
|
1999-10-25 21:39:08 +00:00
|
|
|
isc_taskmgr_t *taskmgr, dns_adb_t **newadb)
|
1999-09-21 22:46:42 +00:00
|
|
|
{
|
1999-09-23 00:43:10 +00:00
|
|
|
dns_adb_t *adb;
|
|
|
|
isc_result_t result;
|
|
|
|
int i;
|
|
|
|
|
1999-09-22 00:26:20 +00:00
|
|
|
REQUIRE(mem != NULL);
|
1999-10-25 22:53:15 +00:00
|
|
|
REQUIRE(view != NULL);
|
|
|
|
REQUIRE(timermgr != NULL);
|
|
|
|
REQUIRE(taskmgr != NULL);
|
1999-09-22 00:26:20 +00:00
|
|
|
REQUIRE(newadb != NULL && *newadb == NULL);
|
|
|
|
|
1999-09-23 00:43:10 +00:00
|
|
|
adb = isc_mem_get(mem, sizeof (dns_adb_t));
|
|
|
|
if (adb == NULL)
|
|
|
|
return (ISC_R_NOMEMORY);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize things here that cannot fail, and especially things
|
|
|
|
* that must be NULL for the error return to work properly.
|
|
|
|
*/
|
|
|
|
adb->magic = 0;
|
1999-10-19 01:37:22 +00:00
|
|
|
adb->erefcnt = 1;
|
|
|
|
adb->irefcnt = 0;
|
1999-09-23 00:43:10 +00:00
|
|
|
adb->nmp = NULL;
|
|
|
|
adb->nhmp = NULL;
|
|
|
|
adb->zimp = NULL;
|
|
|
|
adb->emp = NULL;
|
|
|
|
adb->ahmp = NULL;
|
|
|
|
adb->aimp = NULL;
|
1999-10-25 21:02:54 +00:00
|
|
|
adb->afmp = NULL;
|
1999-10-30 01:58:02 +00:00
|
|
|
adb->af6mp = NULL;
|
1999-10-25 22:53:15 +00:00
|
|
|
adb->task = NULL;
|
|
|
|
adb->timer = NULL;
|
|
|
|
adb->mctx = mem;
|
|
|
|
adb->view = view;
|
|
|
|
adb->timermgr = timermgr;
|
|
|
|
adb->taskmgr = taskmgr;
|
2000-01-12 03:00:33 +00:00
|
|
|
adb->next_cleanbucket = 0;
|
1999-11-22 19:57:58 +00:00
|
|
|
ISC_EVENT_INIT(&adb->cevent, sizeof adb->cevent, 0, NULL,
|
|
|
|
DNS_EVENT_ADBCONTROL, shutdown_task, adb,
|
|
|
|
adb, NULL, NULL);
|
|
|
|
adb->cevent_sent = ISC_FALSE;
|
|
|
|
adb->shutting_down = ISC_FALSE;
|
|
|
|
ISC_LIST_INIT(adb->whenshutdown);
|
1999-09-23 00:43:10 +00:00
|
|
|
|
1999-10-20 23:26:06 +00:00
|
|
|
result = isc_random_init(&adb->rand);
|
1999-09-23 00:43:10 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-10-05 23:50:43 +00:00
|
|
|
goto fail0a;
|
1999-10-20 23:26:06 +00:00
|
|
|
|
|
|
|
result = isc_mutex_init(&adb->lock);
|
1999-09-23 00:43:10 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-10-05 23:50:43 +00:00
|
|
|
goto fail0b;
|
1999-10-25 23:18:19 +00:00
|
|
|
|
1999-10-20 23:26:06 +00:00
|
|
|
result = isc_mutex_init(&adb->mplock);
|
1999-10-05 23:50:43 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto fail0c;
|
1999-09-23 00:43:10 +00:00
|
|
|
|
2000-01-13 20:42:43 +00:00
|
|
|
result = isc_mutex_init(&adb->ilock);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto fail0d;
|
|
|
|
|
1999-09-23 00:43:10 +00:00
|
|
|
/*
|
1999-09-24 23:54:42 +00:00
|
|
|
* Initialize the bucket locks for names and elements.
|
|
|
|
* May as well initialize the list heads, too.
|
1999-09-23 00:43:10 +00:00
|
|
|
*/
|
1999-11-05 02:05:06 +00:00
|
|
|
result = isc_mutexblock_init(adb->namelocks, NBUCKETS);
|
1999-09-24 23:54:42 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto fail1;
|
1999-11-05 02:05:06 +00:00
|
|
|
for (i = 0 ; i < NBUCKETS ; i++) {
|
1999-09-23 00:43:10 +00:00
|
|
|
ISC_LIST_INIT(adb->names[i]);
|
1999-10-19 01:37:22 +00:00
|
|
|
adb->name_sd[i] = ISC_FALSE;
|
|
|
|
adb->name_refcnt[i] = 0;
|
|
|
|
adb->irefcnt++;
|
|
|
|
}
|
2000-01-12 03:00:33 +00:00
|
|
|
for (i = 0 ; i < NBUCKETS ; i++) {
|
1999-09-23 00:43:10 +00:00
|
|
|
ISC_LIST_INIT(adb->entries[i]);
|
2000-01-12 03:00:33 +00:00
|
|
|
adb->entry_sd[i] = ISC_FALSE;
|
|
|
|
adb->entry_refcnt[i] = 0;
|
|
|
|
adb->irefcnt++;
|
|
|
|
}
|
1999-11-05 02:05:06 +00:00
|
|
|
result = isc_mutexblock_init(adb->entrylocks, NBUCKETS);
|
1999-09-24 23:54:42 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto fail2;
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Memory pools
|
|
|
|
*/
|
2000-05-08 18:47:02 +00:00
|
|
|
#define MPINIT(t, p, n) do { \
|
1999-09-23 00:43:10 +00:00
|
|
|
result = isc_mempool_create(mem, sizeof (t), &(p)); \
|
|
|
|
if (result != ISC_R_SUCCESS) \
|
|
|
|
goto fail3; \
|
|
|
|
isc_mempool_setfreemax((p), FREE_ITEMS); \
|
|
|
|
isc_mempool_setfillcount((p), FILL_COUNT); \
|
1999-10-19 01:37:22 +00:00
|
|
|
isc_mempool_setname((p), n); \
|
2000-05-08 18:47:02 +00:00
|
|
|
isc_mempool_associatelock((p), &adb->mplock); \
|
1999-09-23 00:43:10 +00:00
|
|
|
} while (0)
|
|
|
|
|
2000-05-08 18:47:02 +00:00
|
|
|
MPINIT(dns_adbname_t, adb->nmp, "adbname");
|
|
|
|
MPINIT(dns_adbnamehook_t, adb->nhmp, "adbnamehook");
|
|
|
|
MPINIT(dns_adbzoneinfo_t, adb->zimp, "adbzoneinfo");
|
|
|
|
MPINIT(dns_adbentry_t, adb->emp, "adbentry");
|
|
|
|
MPINIT(dns_adbfind_t, adb->ahmp, "adbfind");
|
|
|
|
MPINIT(dns_adbaddrinfo_t, adb->aimp, "adbaddrinfo");
|
|
|
|
MPINIT(dns_adbfetch_t, adb->afmp, "adbfetch");
|
|
|
|
MPINIT(dns_adbfetch6_t, adb->af6mp, "adbfetch6");
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
#undef MPINIT
|
|
|
|
|
1999-10-25 22:53:15 +00:00
|
|
|
/*
|
|
|
|
* Allocate a timer and a task for our periodic cleanup.
|
|
|
|
*/
|
2000-04-12 01:41:21 +00:00
|
|
|
result = isc_task_create(adb->taskmgr, 0, &adb->task);
|
1999-10-25 22:53:15 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto fail3;
|
2000-01-25 19:31:23 +00:00
|
|
|
isc_task_setname(adb->task, "ADB", adb);
|
1999-12-01 02:05:16 +00:00
|
|
|
/*
|
|
|
|
* XXXMLG When this is changed to be a config file option,
|
2000-08-01 01:33:37 +00:00
|
|
|
*/
|
1999-10-25 22:53:15 +00:00
|
|
|
isc_interval_set(&adb->tick_interval, CLEAN_SECONDS, 0);
|
|
|
|
result = isc_timer_create(adb->timermgr, isc_timertype_once,
|
|
|
|
NULL, &adb->tick_interval, adb->task,
|
|
|
|
timer_cleanup, adb, &adb->timer);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto fail3;
|
|
|
|
|
2000-02-18 03:53:00 +00:00
|
|
|
DP(5,
|
|
|
|
"Cleaning interval for adb: "
|
|
|
|
"%u buckets every %u seconds, %u buckets in system, %u cl.interval",
|
|
|
|
CLEAN_BUCKETS, CLEAN_SECONDS, NBUCKETS, CLEAN_PERIOD);
|
|
|
|
|
1999-09-23 00:43:10 +00:00
|
|
|
/*
|
|
|
|
* Normal return.
|
|
|
|
*/
|
|
|
|
adb->magic = DNS_ADB_MAGIC;
|
|
|
|
*newadb = adb;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
1999-10-25 22:53:15 +00:00
|
|
|
fail3:
|
|
|
|
if (adb->task != NULL)
|
|
|
|
isc_task_detach(&adb->task);
|
|
|
|
if (adb->timer != NULL)
|
|
|
|
isc_timer_detach(&adb->timer);
|
|
|
|
|
|
|
|
/* clean up entrylocks */
|
1999-11-05 02:05:06 +00:00
|
|
|
isc_mutexblock_destroy(adb->entrylocks, NBUCKETS);
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
fail2: /* clean up namelocks */
|
1999-11-05 02:05:06 +00:00
|
|
|
isc_mutexblock_destroy(adb->namelocks, NBUCKETS);
|
1999-09-23 00:43:10 +00:00
|
|
|
|
|
|
|
fail1: /* clean up only allocated memory */
|
|
|
|
if (adb->nmp != NULL)
|
|
|
|
isc_mempool_destroy(&adb->nmp);
|
|
|
|
if (adb->nhmp != NULL)
|
|
|
|
isc_mempool_destroy(&adb->nhmp);
|
|
|
|
if (adb->zimp != NULL)
|
|
|
|
isc_mempool_destroy(&adb->zimp);
|
|
|
|
if (adb->emp != NULL)
|
|
|
|
isc_mempool_destroy(&adb->emp);
|
|
|
|
if (adb->ahmp != NULL)
|
|
|
|
isc_mempool_destroy(&adb->ahmp);
|
|
|
|
if (adb->aimp != NULL)
|
|
|
|
isc_mempool_destroy(&adb->aimp);
|
1999-10-30 01:58:02 +00:00
|
|
|
if (adb->afmp != NULL)
|
1999-10-25 21:02:54 +00:00
|
|
|
isc_mempool_destroy(&adb->afmp);
|
1999-10-30 01:58:02 +00:00
|
|
|
if (adb->af6mp != NULL)
|
|
|
|
isc_mempool_destroy(&adb->af6mp);
|
1999-09-23 00:43:10 +00:00
|
|
|
|
2000-08-26 01:37:00 +00:00
|
|
|
DESTROYLOCK(&adb->ilock);
|
2000-01-13 20:42:43 +00:00
|
|
|
fail0d:
|
2000-08-26 01:37:00 +00:00
|
|
|
DESTROYLOCK(&adb->mplock);
|
1999-10-20 23:26:06 +00:00
|
|
|
fail0c:
|
2000-08-26 01:37:00 +00:00
|
|
|
DESTROYLOCK(&adb->lock);
|
1999-10-20 23:26:06 +00:00
|
|
|
fail0b:
|
|
|
|
isc_random_invalidate(&adb->rand);
|
1999-10-05 23:50:43 +00:00
|
|
|
fail0a:
|
1999-09-23 00:43:10 +00:00
|
|
|
isc_mem_put(mem, adb, sizeof (dns_adb_t));
|
|
|
|
|
|
|
|
return (result);
|
1999-09-21 22:46:42 +00:00
|
|
|
}
|
|
|
|
|
2000-04-18 08:18:52 +00:00
|
|
|
void
|
|
|
|
dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbx) {
|
|
|
|
|
|
|
|
REQUIRE(DNS_ADB_VALID(adb));
|
|
|
|
REQUIRE(adbx != NULL && *adbx == NULL);
|
|
|
|
|
|
|
|
inc_adb_erefcnt(adb, ISC_TRUE);
|
|
|
|
*adbx = adb;
|
|
|
|
}
|
|
|
|
|
1999-09-21 22:46:42 +00:00
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_adb_detach(dns_adb_t **adbx) {
|
1999-09-23 00:43:10 +00:00
|
|
|
dns_adb_t *adb;
|
|
|
|
|
|
|
|
REQUIRE(adbx != NULL && DNS_ADB_VALID(*adbx));
|
|
|
|
|
|
|
|
adb = *adbx;
|
|
|
|
*adbx = NULL;
|
|
|
|
|
1999-10-05 23:50:43 +00:00
|
|
|
LOCK(&adb->lock);
|
1999-10-19 01:37:22 +00:00
|
|
|
dec_adb_erefcnt(adb, ISC_FALSE);
|
1999-10-22 05:19:42 +00:00
|
|
|
if (adb->erefcnt == 0)
|
1999-11-22 19:57:58 +00:00
|
|
|
INSIST(adb->shutting_down);
|
|
|
|
UNLOCK(&adb->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) {
|
1999-11-22 19:57:58 +00:00
|
|
|
isc_task_t *clone;
|
|
|
|
isc_event_t *event;
|
2000-01-13 20:42:43 +00:00
|
|
|
isc_boolean_t zeroirefcnt = ISC_FALSE;
|
1999-11-22 19:57:58 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Send '*eventp' to 'task' when 'adb' has shutdown.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(DNS_ADB_VALID(adb));
|
|
|
|
REQUIRE(eventp != NULL);
|
|
|
|
|
|
|
|
event = *eventp;
|
|
|
|
*eventp = NULL;
|
|
|
|
|
|
|
|
LOCK(&adb->lock);
|
2000-01-13 20:42:43 +00:00
|
|
|
|
|
|
|
LOCK(&adb->ilock);
|
|
|
|
if (adb->irefcnt == 0)
|
|
|
|
zeroirefcnt = ISC_TRUE;
|
|
|
|
else
|
|
|
|
zeroirefcnt = ISC_FALSE;
|
|
|
|
UNLOCK(&adb->ilock);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-01-13 20:42:43 +00:00
|
|
|
if (adb->shutting_down && zeroirefcnt &&
|
1999-11-22 19:57:58 +00:00
|
|
|
isc_mempool_getallocated(adb->ahmp) == 0) {
|
|
|
|
/*
|
|
|
|
* We're already shutdown. Send the event.
|
|
|
|
*/
|
2000-04-17 19:22:44 +00:00
|
|
|
event->ev_sender = adb;
|
1999-11-22 19:57:58 +00:00
|
|
|
isc_task_send(task, &event);
|
|
|
|
} else {
|
|
|
|
clone = NULL;
|
|
|
|
isc_task_attach(task, &clone);
|
2000-04-17 19:22:44 +00:00
|
|
|
event->ev_sender = clone;
|
|
|
|
ISC_LIST_APPEND(adb->whenshutdown, event, ev_link);
|
1999-11-22 19:57:58 +00:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-11-22 19:57:58 +00:00
|
|
|
UNLOCK(&adb->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_adb_shutdown(dns_adb_t *adb) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Shutdown 'adb'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
LOCK(&adb->lock);
|
|
|
|
|
|
|
|
if (!adb->shutting_down) {
|
|
|
|
adb->shutting_down = ISC_TRUE;
|
1999-10-26 23:44:36 +00:00
|
|
|
shutdown_names(adb);
|
2000-01-12 03:00:33 +00:00
|
|
|
shutdown_entries(adb);
|
1999-11-22 19:57:58 +00:00
|
|
|
check_exit(adb);
|
|
|
|
}
|
|
|
|
|
1999-10-25 23:07:14 +00:00
|
|
|
UNLOCK(&adb->lock);
|
1999-09-21 22:46:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
1999-10-29 18:00:31 +00:00
|
|
|
dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
|
|
|
void *arg, dns_name_t *name, dns_name_t *zone,
|
2000-01-21 02:50:27 +00:00
|
|
|
unsigned int options, isc_stdtime_t now, dns_name_t *target,
|
2000-06-01 00:30:58 +00:00
|
|
|
in_port_t port, dns_adbfind_t **findp)
|
1999-09-21 22:46:42 +00:00
|
|
|
{
|
1999-10-29 18:30:48 +00:00
|
|
|
dns_adbfind_t *find;
|
1999-10-08 23:12:21 +00:00
|
|
|
dns_adbname_t *adbname;
|
|
|
|
int bucket;
|
2000-02-02 23:24:04 +00:00
|
|
|
isc_boolean_t want_event, start_at_root, alias;
|
1999-10-05 23:50:43 +00:00
|
|
|
isc_result_t result;
|
1999-10-29 01:26:45 +00:00
|
|
|
unsigned int wanted_addresses;
|
1999-12-14 00:10:06 +00:00
|
|
|
unsigned int wanted_fetches;
|
1999-11-02 18:36:54 +00:00
|
|
|
unsigned int query_pending;
|
1999-10-05 23:50:43 +00:00
|
|
|
|
1999-09-22 00:26:20 +00:00
|
|
|
REQUIRE(DNS_ADB_VALID(adb));
|
|
|
|
if (task != NULL) {
|
|
|
|
REQUIRE(action != NULL);
|
|
|
|
}
|
1999-10-08 23:12:21 +00:00
|
|
|
REQUIRE(name != NULL);
|
1999-09-22 00:26:20 +00:00
|
|
|
REQUIRE(zone != NULL);
|
1999-10-29 18:30:48 +00:00
|
|
|
REQUIRE(findp != NULL && *findp == NULL);
|
2000-01-21 02:50:27 +00:00
|
|
|
REQUIRE(target == NULL || dns_name_hasbuffer(target));
|
1999-10-05 23:50:43 +00:00
|
|
|
|
1999-11-01 02:29:03 +00:00
|
|
|
REQUIRE((options & DNS_ADBFIND_ADDRESSMASK) != 0);
|
1999-10-29 01:26:45 +00:00
|
|
|
|
1999-10-19 01:37:22 +00:00
|
|
|
result = ISC_R_UNEXPECTED;
|
1999-10-29 01:26:45 +00:00
|
|
|
wanted_addresses = (options & DNS_ADBFIND_ADDRESSMASK);
|
1999-12-14 00:10:06 +00:00
|
|
|
wanted_fetches = 0;
|
1999-11-02 18:36:54 +00:00
|
|
|
query_pending = 0;
|
|
|
|
want_event = ISC_FALSE;
|
2000-01-06 00:56:37 +00:00
|
|
|
start_at_root = ISC_FALSE;
|
2000-01-21 02:50:27 +00:00
|
|
|
alias = ISC_FALSE;
|
1999-09-22 00:26:20 +00:00
|
|
|
|
1999-12-16 23:29:07 +00:00
|
|
|
if (now == 0)
|
|
|
|
isc_stdtime_get(&now);
|
1999-10-20 23:26:06 +00:00
|
|
|
|
1999-09-25 02:44:40 +00:00
|
|
|
/*
|
1999-11-25 01:23:32 +00:00
|
|
|
* XXXMLG Move this comment somewhere else!
|
|
|
|
*
|
1999-10-08 23:12:21 +00:00
|
|
|
* Look up the name in our internal database.
|
1999-09-25 02:44:40 +00:00
|
|
|
*
|
|
|
|
* Possibilities: Note that these are not always exclusive.
|
|
|
|
*
|
1999-10-08 23:12:21 +00:00
|
|
|
* No name found. In this case, allocate a new name header and
|
|
|
|
* an initial namehook or two. If any of these allocations
|
|
|
|
* fail, clean up and return ISC_R_NOMEMORY.
|
1999-09-25 02:44:40 +00:00
|
|
|
*
|
|
|
|
* Name found, valid addresses present. Allocate one addrinfo
|
|
|
|
* structure for each found and append it to the linked list
|
|
|
|
* of addresses for this header.
|
|
|
|
*
|
|
|
|
* Name found, queries pending. In this case, if a task was
|
|
|
|
* passed in, allocate a job id, attach it to the name's job
|
|
|
|
* list and remember to tell the caller that there will be
|
|
|
|
* more info coming later.
|
|
|
|
*/
|
1999-11-25 01:23:32 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
find = new_adbfind(adb);
|
|
|
|
if (find == NULL)
|
1999-10-29 01:26:45 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
1999-10-08 23:12:21 +00:00
|
|
|
|
2000-06-01 00:30:58 +00:00
|
|
|
find->port = port;
|
|
|
|
|
1999-10-08 23:12:21 +00:00
|
|
|
/*
|
1999-10-29 01:26:45 +00:00
|
|
|
* Remember what types of addresses we are interested in.
|
|
|
|
*/
|
1999-10-29 18:30:48 +00:00
|
|
|
find->options = options;
|
1999-10-30 01:58:02 +00:00
|
|
|
find->flags |= wanted_addresses;
|
1999-11-04 08:48:47 +00:00
|
|
|
if (FIND_WANTEVENT(find)) {
|
|
|
|
REQUIRE(task != NULL);
|
|
|
|
}
|
1999-10-29 01:26:45 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Try to see if we know anything about this name at all.
|
1999-10-08 23:12:21 +00:00
|
|
|
*/
|
|
|
|
bucket = DNS_ADB_INVALIDBUCKET;
|
2000-02-02 23:24:04 +00:00
|
|
|
adbname = find_name_and_lock(adb, name, find->options, &bucket);
|
1999-10-19 01:37:22 +00:00
|
|
|
if (adb->name_sd[bucket]) {
|
1999-11-01 20:16:35 +00:00
|
|
|
DP(DEF_LEVEL,
|
1999-11-02 00:29:45 +00:00
|
|
|
"dns_adb_createfind: returning ISC_R_SHUTTINGDOWN");
|
1999-10-29 18:30:48 +00:00
|
|
|
free_adbfind(adb, &find);
|
1999-10-27 19:36:58 +00:00
|
|
|
result = ISC_R_SHUTTINGDOWN;
|
1999-10-29 01:26:45 +00:00
|
|
|
goto out;
|
1999-10-26 00:16:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-10-29 01:26:45 +00:00
|
|
|
* Nothing found. Allocate a new adbname structure for this name.
|
1999-10-26 00:16:36 +00:00
|
|
|
*/
|
1999-10-29 01:26:45 +00:00
|
|
|
if (adbname == NULL) {
|
|
|
|
adbname = new_adbname(adb, name);
|
|
|
|
if (adbname == NULL) {
|
1999-10-29 18:30:48 +00:00
|
|
|
free_adbfind(adb, &find);
|
1999-10-29 01:26:45 +00:00
|
|
|
result = ISC_R_NOMEMORY;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
link_name(adb, bucket, adbname);
|
2000-02-02 23:24:04 +00:00
|
|
|
if (FIND_HINTOK(find))
|
|
|
|
adbname->flags |= NAME_HINT_OK;
|
|
|
|
if (FIND_GLUEOK(find))
|
|
|
|
adbname->flags |= NAME_GLUE_OK;
|
1999-10-27 19:36:58 +00:00
|
|
|
}
|
1999-10-25 23:43:20 +00:00
|
|
|
|
|
|
|
/*
|
1999-10-29 01:26:45 +00:00
|
|
|
* Expire old entries, etc.
|
1999-10-25 23:43:20 +00:00
|
|
|
*/
|
1999-10-29 01:26:45 +00:00
|
|
|
check_expire_namehooks(adbname, now);
|
1999-10-25 23:43:20 +00:00
|
|
|
|
2000-01-21 02:50:27 +00:00
|
|
|
/*
|
|
|
|
* Do we know that the name is an alias?
|
|
|
|
*/
|
|
|
|
if (!EXPIRE_OK(adbname->expire_target, now)) {
|
|
|
|
/*
|
|
|
|
* Yes, it is.
|
|
|
|
*/
|
|
|
|
DP(DEF_LEVEL,
|
|
|
|
"dns_adb_createfind: name %p is an alias (cached)",
|
|
|
|
adbname);
|
|
|
|
alias = ISC_TRUE;
|
|
|
|
goto post_copy;
|
|
|
|
}
|
|
|
|
|
1999-10-25 23:43:20 +00:00
|
|
|
/*
|
|
|
|
* Try to populate the name from the database and/or
|
1999-10-29 01:26:45 +00:00
|
|
|
* start fetches.
|
1999-10-25 23:43:20 +00:00
|
|
|
*/
|
1999-11-04 08:48:47 +00:00
|
|
|
if (!NAME_HAS_V4(adbname) && !NAME_FETCH_V4(adbname)
|
1999-11-04 06:46:05 +00:00
|
|
|
&& EXPIRE_OK(adbname->expire_v4, now)
|
1999-10-29 01:26:45 +00:00
|
|
|
&& WANT_INET(wanted_addresses)) {
|
2000-02-02 23:24:04 +00:00
|
|
|
result = dbfind_name(adbname, now, dns_rdatatype_a);
|
1999-10-29 01:26:45 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
1999-11-01 20:16:35 +00:00
|
|
|
DP(DEF_LEVEL,
|
2000-06-16 15:51:58 +00:00
|
|
|
"dns_adb_createfind: found A for name %p in db",
|
1999-10-29 22:28:57 +00:00
|
|
|
adbname);
|
1999-10-29 01:26:45 +00:00
|
|
|
goto v6;
|
|
|
|
}
|
1999-10-25 23:43:20 +00:00
|
|
|
|
2000-01-21 02:50:27 +00:00
|
|
|
/*
|
|
|
|
* Did we get a CNAME or DNAME?
|
|
|
|
*/
|
2000-01-28 00:32:32 +00:00
|
|
|
if (result == DNS_R_ALIAS) {
|
2000-01-21 02:50:27 +00:00
|
|
|
DP(DEF_LEVEL,
|
|
|
|
"dns_adb_createfind: name %p is an alias",
|
|
|
|
adbname);
|
|
|
|
alias = ISC_TRUE;
|
|
|
|
goto post_copy;
|
|
|
|
}
|
|
|
|
|
1999-11-24 19:23:27 +00:00
|
|
|
/*
|
|
|
|
* Listen to negative cache hints, and don't start
|
|
|
|
* another query.
|
|
|
|
*/
|
2000-01-15 00:45:49 +00:00
|
|
|
if (NCACHE_RESULT(result) || AUTH_NX(result))
|
1999-11-24 19:23:27 +00:00
|
|
|
goto v6;
|
|
|
|
|
1999-12-14 00:10:06 +00:00
|
|
|
wanted_fetches |= DNS_ADBFIND_INET;
|
1999-10-26 01:12:20 +00:00
|
|
|
}
|
|
|
|
|
1999-10-29 01:26:45 +00:00
|
|
|
v6:
|
1999-11-04 08:48:47 +00:00
|
|
|
if (!NAME_HAS_V6(adbname) && !NAME_FETCH_V6(adbname)
|
1999-11-04 06:46:05 +00:00
|
|
|
&& EXPIRE_OK(adbname->expire_v6, now)
|
1999-10-30 02:26:03 +00:00
|
|
|
&& WANT_INET6(wanted_addresses)) {
|
2000-02-02 23:24:04 +00:00
|
|
|
result = dbfind_a6(adbname, now);
|
1999-10-29 19:20:36 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
1999-11-01 20:16:35 +00:00
|
|
|
DP(DEF_LEVEL,
|
2000-06-16 15:51:58 +00:00
|
|
|
"dns_adb_createfind: found A6 for name %p",
|
1999-11-01 02:29:03 +00:00
|
|
|
adbname);
|
1999-12-14 00:10:06 +00:00
|
|
|
goto fetch;
|
1999-10-29 19:20:36 +00:00
|
|
|
}
|
|
|
|
|
2000-01-21 02:50:27 +00:00
|
|
|
/*
|
|
|
|
* Did we get a CNAME or DNAME?
|
|
|
|
*/
|
2000-01-28 00:32:32 +00:00
|
|
|
if (result == DNS_R_ALIAS) {
|
2000-01-21 02:50:27 +00:00
|
|
|
DP(DEF_LEVEL,
|
|
|
|
"dns_adb_createfind: name %p is an alias",
|
|
|
|
adbname);
|
|
|
|
alias = ISC_TRUE;
|
|
|
|
goto post_copy;
|
|
|
|
}
|
|
|
|
|
1999-11-24 19:23:27 +00:00
|
|
|
/*
|
|
|
|
* Listen to negative cache hints, and don't start
|
|
|
|
* another query.
|
|
|
|
*/
|
2000-01-15 00:45:49 +00:00
|
|
|
if (NCACHE_RESULT(result) || AUTH_NX(result))
|
1999-12-14 00:10:06 +00:00
|
|
|
goto fetch;
|
|
|
|
|
|
|
|
wanted_fetches |= DNS_ADBFIND_INET6;
|
|
|
|
}
|
1999-11-24 19:23:27 +00:00
|
|
|
|
1999-12-14 00:10:06 +00:00
|
|
|
fetch:
|
|
|
|
if (wanted_fetches != 0 &&
|
|
|
|
(!FIND_AVOIDFETCHES(find) || wanted_addresses == wanted_fetches)) {
|
1999-10-29 19:20:36 +00:00
|
|
|
/*
|
1999-12-14 00:10:06 +00:00
|
|
|
* We're missing at least one address family. Either the
|
|
|
|
* caller hasn't instructed us to avoid fetches, or we don't
|
|
|
|
* know anything about any of the address families that would
|
|
|
|
* be acceptable so we have to launch fetches.
|
1999-10-29 19:20:36 +00:00
|
|
|
*/
|
1999-12-14 00:10:06 +00:00
|
|
|
|
2000-01-06 00:56:37 +00:00
|
|
|
if (FIND_STARTATROOT(find))
|
|
|
|
start_at_root = ISC_TRUE;
|
|
|
|
|
1999-12-14 00:10:06 +00:00
|
|
|
/*
|
|
|
|
* Start V4.
|
|
|
|
*/
|
|
|
|
if (WANT_INET(wanted_fetches) &&
|
2000-02-02 23:24:04 +00:00
|
|
|
fetch_name_v4(adbname, start_at_root) == ISC_R_SUCCESS) {
|
1999-12-14 00:10:06 +00:00
|
|
|
DP(DEF_LEVEL,
|
2000-06-16 15:51:58 +00:00
|
|
|
"dns_adb_createfind: started A fetch for name %p",
|
1999-12-14 00:10:06 +00:00
|
|
|
adbname);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Start V6.
|
|
|
|
*/
|
|
|
|
if (WANT_INET6(wanted_fetches) &&
|
2000-02-02 23:24:04 +00:00
|
|
|
fetch_name_a6(adbname, start_at_root) == ISC_R_SUCCESS) {
|
1999-11-01 20:16:35 +00:00
|
|
|
DP(DEF_LEVEL,
|
2000-06-16 15:51:58 +00:00
|
|
|
"dns_adb_createfind: started A6 fetch for name %p",
|
1999-10-29 22:28:57 +00:00
|
|
|
adbname);
|
1999-10-29 19:20:36 +00:00
|
|
|
}
|
1999-10-29 01:26:45 +00:00
|
|
|
}
|
1999-10-08 23:12:21 +00:00
|
|
|
|
|
|
|
/*
|
1999-10-29 01:26:45 +00:00
|
|
|
* Run through the name and copy out the bits we are
|
|
|
|
* interested in.
|
1999-10-08 23:12:21 +00:00
|
|
|
*/
|
1999-11-02 00:29:45 +00:00
|
|
|
copy_namehook_lists(adb, find, zone, adbname, now);
|
1999-10-21 01:37:57 +00:00
|
|
|
|
2000-01-27 02:14:53 +00:00
|
|
|
post_copy:
|
1999-11-02 18:36:54 +00:00
|
|
|
if (NAME_FETCH_V4(adbname))
|
|
|
|
query_pending |= DNS_ADBFIND_INET;
|
|
|
|
if (NAME_FETCH_V6(adbname))
|
|
|
|
query_pending |= DNS_ADBFIND_INET6;
|
|
|
|
|
1999-10-27 19:36:58 +00:00
|
|
|
/*
|
|
|
|
* Attach to the name's query list if there are queries
|
1999-10-29 01:26:45 +00:00
|
|
|
* already running, and we have been asked to.
|
1999-10-27 19:36:58 +00:00
|
|
|
*/
|
1999-11-02 18:36:54 +00:00
|
|
|
want_event = ISC_TRUE;
|
1999-11-04 08:48:47 +00:00
|
|
|
if (!FIND_WANTEVENT(find))
|
1999-11-02 18:36:54 +00:00
|
|
|
want_event = ISC_FALSE;
|
1999-11-04 08:48:47 +00:00
|
|
|
if (FIND_WANTEMPTYEVENT(find) && FIND_HAS_ADDRS(find))
|
1999-11-02 18:36:54 +00:00
|
|
|
want_event = ISC_FALSE;
|
|
|
|
if ((wanted_addresses & query_pending) == 0)
|
|
|
|
want_event = ISC_FALSE;
|
2000-01-21 02:50:27 +00:00
|
|
|
if (alias)
|
|
|
|
want_event = ISC_FALSE;
|
1999-11-02 18:36:54 +00:00
|
|
|
if (want_event) {
|
1999-10-29 18:30:48 +00:00
|
|
|
find->adbname = adbname;
|
|
|
|
find->name_bucket = bucket;
|
|
|
|
ISC_LIST_APPEND(adbname->finds, find, plink);
|
1999-11-02 18:36:54 +00:00
|
|
|
find->query_pending = (query_pending & wanted_addresses);
|
1999-11-01 20:16:35 +00:00
|
|
|
find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
|
|
|
|
find->flags |= (find->query_pending & DNS_ADBFIND_ADDRESSMASK);
|
1999-11-05 02:05:06 +00:00
|
|
|
DP(DEF_LEVEL, "createfind: attaching find %p to adbname %p",
|
1999-11-01 02:57:16 +00:00
|
|
|
find, adbname);
|
1999-10-29 01:26:45 +00:00
|
|
|
} else {
|
1999-10-29 18:00:31 +00:00
|
|
|
/*
|
|
|
|
* Remove the flag so the caller knows there will never
|
|
|
|
* be an event, and set internal flags to fake that
|
|
|
|
* the event was sent and freed, so dns_adb_destroyfind() will
|
|
|
|
* do the right thing.
|
|
|
|
*/
|
2000-01-27 02:14:53 +00:00
|
|
|
find->query_pending = (query_pending & wanted_addresses);
|
1999-10-29 18:30:48 +00:00
|
|
|
find->options &= ~DNS_ADBFIND_WANTEVENT;
|
|
|
|
find->flags |= (FIND_EVENT_SENT | FIND_EVENT_FREED);
|
1999-11-01 20:16:35 +00:00
|
|
|
find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
|
1999-10-08 23:12:21 +00:00
|
|
|
}
|
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
find->partial_result |= (adbname->partial_result & wanted_addresses);
|
2000-01-21 02:50:27 +00:00
|
|
|
if (alias) {
|
|
|
|
if (target != NULL) {
|
|
|
|
result = dns_name_concatenate(&adbname->target, NULL,
|
|
|
|
target, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
result = DNS_R_ALIAS;
|
|
|
|
} else
|
|
|
|
result = ISC_R_SUCCESS;
|
1999-10-19 20:55:04 +00:00
|
|
|
|
1999-10-29 01:26:45 +00:00
|
|
|
out:
|
1999-10-29 18:30:48 +00:00
|
|
|
if (find != NULL) {
|
|
|
|
*findp = find;
|
1999-10-08 23:12:21 +00:00
|
|
|
|
1999-11-02 18:36:54 +00:00
|
|
|
if (want_event) {
|
1999-10-16 00:38:21 +00:00
|
|
|
isc_task_t *taskp;
|
|
|
|
|
1999-11-01 20:16:35 +00:00
|
|
|
INSIST((find->flags & DNS_ADBFIND_ADDRESSMASK) != 0);
|
1999-10-16 00:38:21 +00:00
|
|
|
taskp = NULL;
|
|
|
|
isc_task_attach(task, &taskp);
|
2000-04-17 19:22:44 +00:00
|
|
|
find->event.ev_sender = taskp;
|
|
|
|
find->event.ev_action = action;
|
|
|
|
find->event.ev_arg = arg;
|
1999-10-16 00:38:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-10-08 23:12:21 +00:00
|
|
|
if (bucket != DNS_ADB_INVALIDBUCKET)
|
|
|
|
UNLOCK(&adb->namelocks[bucket]);
|
|
|
|
|
|
|
|
return (result);
|
1999-09-25 01:56:10 +00:00
|
|
|
}
|
|
|
|
|
1999-09-21 22:46:42 +00:00
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_adb_destroyfind(dns_adbfind_t **findp) {
|
1999-10-29 18:30:48 +00:00
|
|
|
dns_adbfind_t *find;
|
1999-10-14 00:50:00 +00:00
|
|
|
dns_adbentry_t *entry;
|
|
|
|
dns_adbaddrinfo_t *ai;
|
|
|
|
int bucket;
|
1999-10-22 05:19:42 +00:00
|
|
|
dns_adb_t *adb;
|
1999-09-22 00:26:20 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
REQUIRE(findp != NULL && DNS_ADBFIND_VALID(*findp));
|
|
|
|
find = *findp;
|
|
|
|
*findp = NULL;
|
1999-09-21 22:46:42 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
LOCK(&find->lock);
|
1999-10-22 05:19:42 +00:00
|
|
|
|
2000-01-13 18:58:01 +00:00
|
|
|
DP(DEF_LEVEL, "dns_adb_destroyfind on find %p", find);
|
1999-10-27 19:36:58 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
adb = find->adb;
|
1999-10-22 05:19:42 +00:00
|
|
|
REQUIRE(DNS_ADB_VALID(adb));
|
1999-10-14 00:50:00 +00:00
|
|
|
|
1999-11-04 08:48:47 +00:00
|
|
|
REQUIRE(FIND_EVENTFREED(find));
|
1999-10-19 20:55:04 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
bucket = find->name_bucket;
|
1999-10-29 18:00:31 +00:00
|
|
|
INSIST(bucket == DNS_ADB_INVALIDBUCKET);
|
1999-10-14 00:50:00 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
UNLOCK(&find->lock);
|
1999-09-22 00:26:20 +00:00
|
|
|
|
1999-10-14 00:50:00 +00:00
|
|
|
/*
|
1999-10-29 18:30:48 +00:00
|
|
|
* The find doesn't exist on any list, and nothing is locked.
|
|
|
|
* Return the find to the memory pool, and decrement the adb's
|
1999-10-14 00:50:00 +00:00
|
|
|
* reference count.
|
|
|
|
*/
|
1999-10-29 18:30:48 +00:00
|
|
|
ai = ISC_LIST_HEAD(find->list);
|
1999-10-14 00:50:00 +00:00
|
|
|
while (ai != NULL) {
|
1999-10-29 18:30:48 +00:00
|
|
|
ISC_LIST_UNLINK(find->list, ai, publink);
|
1999-10-14 00:50:00 +00:00
|
|
|
entry = ai->entry;
|
|
|
|
ai->entry = NULL;
|
|
|
|
INSIST(DNS_ADBENTRY_VALID(entry));
|
|
|
|
dec_entry_refcnt(adb, entry, ISC_TRUE);
|
|
|
|
free_adbaddrinfo(adb, &ai);
|
1999-10-29 18:30:48 +00:00
|
|
|
ai = ISC_LIST_HEAD(find->list);
|
1999-10-14 00:50:00 +00:00
|
|
|
}
|
1999-10-22 05:19:42 +00:00
|
|
|
|
1999-10-29 18:00:31 +00:00
|
|
|
/*
|
1999-10-29 18:30:48 +00:00
|
|
|
* WARNING: The find is freed with the adb locked. This is done
|
|
|
|
* to avoid a race condition where we free the find, some other
|
1999-10-29 18:00:31 +00:00
|
|
|
* thread tests to see if it should be destroyed, detects it should
|
|
|
|
* be, destroys it, and then we try to lock it for our check, but the
|
|
|
|
* lock is destroyed.
|
|
|
|
*/
|
1999-10-22 05:19:42 +00:00
|
|
|
LOCK(&adb->lock);
|
1999-10-29 18:30:48 +00:00
|
|
|
free_adbfind(adb, &find);
|
1999-10-26 23:44:36 +00:00
|
|
|
check_exit(adb);
|
1999-10-25 23:07:14 +00:00
|
|
|
UNLOCK(&adb->lock);
|
1999-09-21 22:46:42 +00:00
|
|
|
}
|
1999-10-02 01:59:09 +00:00
|
|
|
|
1999-10-29 18:00:31 +00:00
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_adb_cancelfind(dns_adbfind_t *find) {
|
1999-10-29 18:00:31 +00:00
|
|
|
isc_event_t *ev;
|
|
|
|
isc_task_t *task;
|
|
|
|
dns_adb_t *adb;
|
|
|
|
int bucket;
|
1999-12-10 23:22:13 +00:00
|
|
|
int unlock_bucket;
|
1999-10-29 18:00:31 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
LOCK(&find->lock);
|
1999-10-29 18:00:31 +00:00
|
|
|
|
1999-11-01 20:16:35 +00:00
|
|
|
DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
|
1999-10-29 18:00:31 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
adb = find->adb;
|
1999-10-29 18:00:31 +00:00
|
|
|
REQUIRE(DNS_ADB_VALID(adb));
|
|
|
|
|
1999-11-04 08:48:47 +00:00
|
|
|
REQUIRE(!FIND_EVENTFREED(find));
|
|
|
|
REQUIRE(FIND_WANTEVENT(find));
|
1999-10-29 18:00:31 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
bucket = find->name_bucket;
|
1999-10-29 18:00:31 +00:00
|
|
|
if (bucket == DNS_ADB_INVALIDBUCKET)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/*
|
1999-10-29 18:30:48 +00:00
|
|
|
* We need to get the adbname's lock to unlink the find.
|
1999-10-29 18:00:31 +00:00
|
|
|
*/
|
1999-12-10 23:22:13 +00:00
|
|
|
unlock_bucket = bucket;
|
|
|
|
violate_locking_hierarchy(&find->lock, &adb->namelocks[unlock_bucket]);
|
1999-10-29 18:30:48 +00:00
|
|
|
bucket = find->name_bucket;
|
1999-10-29 18:00:31 +00:00
|
|
|
if (bucket != DNS_ADB_INVALIDBUCKET) {
|
1999-10-29 18:30:48 +00:00
|
|
|
ISC_LIST_UNLINK(find->adbname->finds, find, plink);
|
|
|
|
find->adbname = NULL;
|
|
|
|
find->name_bucket = DNS_ADB_INVALIDBUCKET;
|
1999-10-29 18:00:31 +00:00
|
|
|
}
|
1999-12-10 23:22:13 +00:00
|
|
|
UNLOCK(&adb->namelocks[unlock_bucket]);
|
1999-10-29 18:00:31 +00:00
|
|
|
bucket = DNS_ADB_INVALIDBUCKET;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
|
1999-11-04 08:48:47 +00:00
|
|
|
if (!FIND_EVENTSENT(find)) {
|
1999-10-29 18:30:48 +00:00
|
|
|
ev = &find->event;
|
2000-04-17 19:22:44 +00:00
|
|
|
task = ev->ev_sender;
|
|
|
|
ev->ev_sender = find;
|
|
|
|
ev->ev_type = DNS_EVENT_ADBCANCELED;
|
|
|
|
ev->ev_destroy = event_free;
|
|
|
|
ev->ev_destroy_arg = find;
|
1999-10-29 18:00:31 +00:00
|
|
|
|
1999-11-01 20:16:35 +00:00
|
|
|
DP(DEF_LEVEL, "Sending event %p to task %p for find %p",
|
1999-10-29 22:28:57 +00:00
|
|
|
ev, task, find);
|
1999-10-29 18:00:31 +00:00
|
|
|
|
|
|
|
isc_task_sendanddetach(&task, &ev);
|
|
|
|
}
|
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
UNLOCK(&find->lock);
|
1999-10-29 18:00:31 +00:00
|
|
|
}
|
|
|
|
|
1999-10-02 01:59:09 +00:00
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_adb_dump(dns_adb_t *adb, FILE *f) {
|
1999-10-02 01:59:09 +00:00
|
|
|
REQUIRE(DNS_ADB_VALID(adb));
|
|
|
|
REQUIRE(f != NULL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lock the adb itself, lock all the name buckets, then lock all
|
|
|
|
* the entry buckets. This should put the adb into a state where
|
|
|
|
* nothing can change, so we can iterate through everything and
|
|
|
|
* print at our leasure.
|
|
|
|
*/
|
|
|
|
|
|
|
|
LOCK(&adb->lock);
|
1999-10-27 19:36:58 +00:00
|
|
|
dump_adb(adb, f);
|
|
|
|
UNLOCK(&adb->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
dump_adb(dns_adb_t *adb, FILE *f) {
|
1999-10-27 19:36:58 +00:00
|
|
|
int i;
|
|
|
|
isc_sockaddr_t *sa;
|
|
|
|
dns_adbname_t *name;
|
|
|
|
dns_adbentry_t *entry;
|
|
|
|
char tmp[512];
|
|
|
|
const char *tmpp;
|
1999-11-04 08:29:06 +00:00
|
|
|
isc_stdtime_t now;
|
|
|
|
|
1999-12-16 23:29:07 +00:00
|
|
|
isc_stdtime_get(&now);
|
1999-10-02 01:59:09 +00:00
|
|
|
|
1999-10-19 01:37:22 +00:00
|
|
|
fprintf(f, "ADB %p DUMP:\n", adb);
|
1999-10-29 18:30:48 +00:00
|
|
|
fprintf(f, "erefcnt %u, irefcnt %u, finds out %u\n",
|
1999-10-27 22:24:40 +00:00
|
|
|
adb->erefcnt, adb->irefcnt,
|
|
|
|
isc_mempool_getallocated(adb->nhmp));
|
1999-10-19 01:37:22 +00:00
|
|
|
|
1999-11-05 02:05:06 +00:00
|
|
|
for (i = 0 ; i < NBUCKETS ; i++)
|
1999-10-02 01:59:09 +00:00
|
|
|
LOCK(&adb->namelocks[i]);
|
1999-11-05 02:05:06 +00:00
|
|
|
for (i = 0 ; i < NBUCKETS ; i++)
|
1999-10-02 01:59:09 +00:00
|
|
|
LOCK(&adb->entrylocks[i]);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Dump the names
|
|
|
|
*/
|
|
|
|
fprintf(f, "Names:\n");
|
1999-11-05 02:05:06 +00:00
|
|
|
for (i = 0 ; i < NBUCKETS ; i++) {
|
1999-10-02 01:59:09 +00:00
|
|
|
name = ISC_LIST_HEAD(adb->names[i]);
|
|
|
|
if (name == NULL)
|
|
|
|
continue;
|
|
|
|
fprintf(f, "Name bucket %d:\n", i);
|
|
|
|
while (name != NULL) {
|
2000-02-02 23:24:04 +00:00
|
|
|
fprintf(f, "name %p (flags %08x)\n",
|
|
|
|
name, name->flags);
|
1999-10-02 01:59:09 +00:00
|
|
|
if (!DNS_ADBNAME_VALID(name))
|
|
|
|
fprintf(f, "\tMAGIC %08x\n", name->magic);
|
1999-11-04 08:29:06 +00:00
|
|
|
fprintf(f, "\texpiry [");
|
|
|
|
if (name->expire_v4 == INT_MAX)
|
|
|
|
fprintf(f, "inf ");
|
|
|
|
else
|
|
|
|
fprintf(f, "%d ", name->expire_v4 - now);
|
|
|
|
if (name->expire_v6 == INT_MAX)
|
2000-01-19 02:28:48 +00:00
|
|
|
fprintf(f, "inf ");
|
1999-11-04 08:29:06 +00:00
|
|
|
else
|
2000-01-19 01:43:58 +00:00
|
|
|
fprintf(f, "%d ", name->expire_v6 - now);
|
|
|
|
if (name->expire_target == INT_MAX)
|
|
|
|
fprintf(f, "inf] ");
|
|
|
|
else
|
|
|
|
fprintf(f, "%d] ", name->expire_target - now);
|
1999-10-02 01:59:09 +00:00
|
|
|
print_dns_name(f, &name->name);
|
2000-01-21 02:50:27 +00:00
|
|
|
if (dns_name_countlabels(&name->target) > 0) {
|
|
|
|
fprintf(f, "\t\t alias for ");
|
|
|
|
print_dns_name(f, &name->target);
|
|
|
|
}
|
1999-10-05 23:50:43 +00:00
|
|
|
fprintf(f, "\n");
|
1999-10-02 01:59:09 +00:00
|
|
|
print_namehook_list(f, name);
|
1999-10-27 19:36:58 +00:00
|
|
|
print_fetch_list(f, name);
|
1999-10-29 18:30:48 +00:00
|
|
|
print_find_list(f, name);
|
1999-10-16 00:38:21 +00:00
|
|
|
fprintf(f, "\n");
|
1999-10-02 01:59:09 +00:00
|
|
|
|
1999-10-29 01:53:20 +00:00
|
|
|
name = ISC_LIST_NEXT(name, plink);
|
1999-10-02 01:59:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Dump the entries
|
|
|
|
*/
|
|
|
|
fprintf(f, "Entries:\n");
|
1999-11-05 02:05:06 +00:00
|
|
|
for (i = 0 ; i < NBUCKETS ; i++) {
|
1999-10-02 01:59:09 +00:00
|
|
|
entry = ISC_LIST_HEAD(adb->entries[i]);
|
|
|
|
if (entry == NULL)
|
|
|
|
continue;
|
|
|
|
fprintf(f, "Entry bucket %d:\n", i);
|
|
|
|
while (entry != NULL) {
|
|
|
|
if (!DNS_ADBENTRY_VALID(entry))
|
|
|
|
fprintf(f, "\tMAGIC %08x\n", entry->magic);
|
|
|
|
if (entry->lock_bucket != i)
|
|
|
|
fprintf(f, "\tWRONG BUCKET! lock_bucket %d\n",
|
|
|
|
entry->lock_bucket);
|
|
|
|
|
|
|
|
sa = &entry->sockaddr;
|
1999-10-12 02:06:08 +00:00
|
|
|
switch (sa->type.sa.sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
tmpp = inet_ntop(AF_INET,
|
|
|
|
&sa->type.sin.sin_addr,
|
|
|
|
tmp, sizeof tmp);
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
tmpp = inet_ntop(AF_INET6,
|
|
|
|
&sa->type.sin6.sin6_addr,
|
|
|
|
tmp, sizeof tmp);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
tmpp = "UnkFamily";
|
|
|
|
}
|
|
|
|
|
1999-10-02 01:59:09 +00:00
|
|
|
if (tmpp == NULL)
|
2000-02-16 01:49:11 +00:00
|
|
|
tmpp = "BadAddress";
|
1999-10-02 01:59:09 +00:00
|
|
|
|
1999-10-22 05:19:42 +00:00
|
|
|
fprintf(f, "\t%p: refcnt %u flags %08x goodness %d"
|
2000-02-16 01:49:11 +00:00
|
|
|
" srtt %u addr %s, avoid_bitstring %u\n",
|
1999-10-22 05:19:42 +00:00
|
|
|
entry, entry->refcnt, entry->flags,
|
2000-02-16 01:49:11 +00:00
|
|
|
entry->goodness, entry->srtt, tmpp,
|
|
|
|
entry->avoid_bitstring);
|
1999-10-02 01:59:09 +00:00
|
|
|
|
1999-10-29 01:53:20 +00:00
|
|
|
entry = ISC_LIST_NEXT(entry, plink);
|
1999-10-02 01:59:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unlock everything
|
|
|
|
*/
|
1999-11-05 02:05:06 +00:00
|
|
|
for (i = 0 ; i < NBUCKETS ; i++)
|
1999-10-02 01:59:09 +00:00
|
|
|
UNLOCK(&adb->entrylocks[i]);
|
1999-11-05 02:05:06 +00:00
|
|
|
for (i = 0 ; i < NBUCKETS ; i++)
|
1999-10-02 01:59:09 +00:00
|
|
|
UNLOCK(&adb->namelocks[i]);
|
|
|
|
}
|
|
|
|
|
1999-10-16 00:38:21 +00:00
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_adb_dumpfind(dns_adbfind_t *find, FILE *f) {
|
1999-10-16 00:38:21 +00:00
|
|
|
char tmp[512];
|
|
|
|
const char *tmpp;
|
|
|
|
dns_adbaddrinfo_t *ai;
|
|
|
|
isc_sockaddr_t *sa;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Not used currently, in the API Just In Case we
|
|
|
|
* want to dump out the name and/or entries too.
|
|
|
|
*/
|
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
LOCK(&find->lock);
|
1999-10-16 00:38:21 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
fprintf(f, "Find %p\n", find);
|
1999-11-01 20:16:35 +00:00
|
|
|
fprintf(f, "\tqpending %08x partial %08x options %08x flags %08x\n",
|
1999-10-29 18:30:48 +00:00
|
|
|
find->query_pending, find->partial_result,
|
1999-11-01 20:16:35 +00:00
|
|
|
find->options, find->flags);
|
1999-10-16 00:38:21 +00:00
|
|
|
fprintf(f, "\tname_bucket %d, name %p, event sender %p\n",
|
2000-04-17 19:22:44 +00:00
|
|
|
find->name_bucket, find->adbname, find->event.ev_sender);
|
1999-10-16 00:38:21 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
ai = ISC_LIST_HEAD(find->list);
|
1999-10-16 00:38:21 +00:00
|
|
|
if (ai != NULL)
|
|
|
|
fprintf(f, "\tAddresses:\n");
|
|
|
|
while (ai != NULL) {
|
2000-06-01 00:30:58 +00:00
|
|
|
sa = &ai->sockaddr;
|
1999-10-16 00:38:21 +00:00
|
|
|
switch (sa->type.sa.sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
tmpp = inet_ntop(AF_INET, &sa->type.sin.sin_addr,
|
|
|
|
tmp, sizeof tmp);
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
tmpp = inet_ntop(AF_INET6, &sa->type.sin6.sin6_addr,
|
|
|
|
tmp, sizeof tmp);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
tmpp = "UnkFamily";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tmpp == NULL)
|
2000-02-16 01:49:11 +00:00
|
|
|
tmpp = "BadAddress";
|
1999-10-16 00:38:21 +00:00
|
|
|
|
|
|
|
fprintf(f, "\t\tentry %p, flags %08x goodness %d"
|
2000-02-16 01:49:11 +00:00
|
|
|
" srtt %u addr %s avoid_bitstring %u\n",
|
|
|
|
ai->entry, ai->flags, ai->goodness, ai->srtt, tmpp,
|
|
|
|
ai->avoid_bitstring);
|
1999-10-16 00:38:21 +00:00
|
|
|
|
1999-10-29 01:53:20 +00:00
|
|
|
ai = ISC_LIST_NEXT(ai, publink);
|
1999-10-16 00:38:21 +00:00
|
|
|
}
|
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
UNLOCK(&find->lock);
|
1999-10-16 00:38:21 +00:00
|
|
|
}
|
|
|
|
|
1999-10-02 01:59:09 +00:00
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
print_dns_name(FILE *f, dns_name_t *name) {
|
2000-08-09 00:09:36 +00:00
|
|
|
char buf[DNS_NAME_FORMATSIZE];
|
1999-10-02 01:59:09 +00:00
|
|
|
|
|
|
|
INSIST(f != NULL);
|
|
|
|
|
2000-05-26 16:12:30 +00:00
|
|
|
dns_name_format(name, buf, sizeof(buf));
|
|
|
|
fprintf(f, "%s", buf);
|
1999-10-02 01:59:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
print_namehook_list(FILE *f, dns_adbname_t *n) {
|
1999-10-02 01:59:09 +00:00
|
|
|
dns_adbnamehook_t *nh;
|
|
|
|
|
1999-10-29 01:26:45 +00:00
|
|
|
nh = ISC_LIST_HEAD(n->v4);
|
1999-10-02 01:59:09 +00:00
|
|
|
while (nh != NULL) {
|
1999-10-29 22:28:57 +00:00
|
|
|
fprintf(f, "\t\tHook(V4) %p -> entry %p\n", nh, nh->entry);
|
|
|
|
nh = ISC_LIST_NEXT(nh, plink);
|
|
|
|
}
|
|
|
|
nh = ISC_LIST_HEAD(n->v6);
|
|
|
|
while (nh != NULL) {
|
|
|
|
fprintf(f, "\t\tHook(V6) %p -> entry %p\n", nh, nh->entry);
|
1999-10-29 01:53:20 +00:00
|
|
|
nh = ISC_LIST_NEXT(nh, plink);
|
1999-10-02 01:59:09 +00:00
|
|
|
}
|
|
|
|
}
|
1999-10-16 00:38:21 +00:00
|
|
|
|
1999-11-02 18:36:54 +00:00
|
|
|
static inline void
|
2000-06-01 18:26:56 +00:00
|
|
|
print_fetch(FILE *f, dns_adbfetch_t *ft, const char *type) {
|
1999-11-02 18:36:54 +00:00
|
|
|
fprintf(f, "\t\tFetch(%s): %p -> { nh %p, entry %p, fetch %p }\n",
|
|
|
|
type, ft, ft->namehook, ft->entry, ft->fetch);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
print_fetch6(FILE *f, dns_adbfetch6_t *ft) {
|
1999-11-02 18:36:54 +00:00
|
|
|
fprintf(f, "\t\tFetch(A6): %p -> { nh %p, entry %p, fetch %p }\n",
|
1999-10-29 21:48:51 +00:00
|
|
|
ft, ft->namehook, ft->entry, ft->fetch);
|
|
|
|
}
|
1999-10-27 19:36:58 +00:00
|
|
|
|
1999-10-29 21:48:51 +00:00
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
print_fetch_list(FILE *f, dns_adbname_t *n) {
|
1999-11-02 18:36:54 +00:00
|
|
|
dns_adbfetch6_t *fetch6;
|
|
|
|
|
|
|
|
if (NAME_FETCH_A(n))
|
|
|
|
print_fetch(f, n->fetch_a, "A");
|
|
|
|
if (NAME_FETCH_AAAA(n))
|
|
|
|
print_fetch(f, n->fetch_aaaa, "AAAA");
|
|
|
|
|
|
|
|
fetch6 = ISC_LIST_HEAD(n->fetches_a6);
|
|
|
|
while (fetch6 != NULL) {
|
|
|
|
print_fetch6(f, fetch6);
|
|
|
|
fetch6 = ISC_LIST_NEXT(fetch6, plink);
|
|
|
|
}
|
1999-10-27 19:36:58 +00:00
|
|
|
}
|
|
|
|
|
1999-10-16 00:38:21 +00:00
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
print_find_list(FILE *f, dns_adbname_t *name) {
|
1999-10-29 18:30:48 +00:00
|
|
|
dns_adbfind_t *find;
|
1999-10-16 00:38:21 +00:00
|
|
|
|
1999-10-29 18:30:48 +00:00
|
|
|
find = ISC_LIST_HEAD(name->finds);
|
|
|
|
while (find != NULL) {
|
1999-11-01 02:57:16 +00:00
|
|
|
dns_adb_dumpfind(find, f);
|
1999-10-29 18:30:48 +00:00
|
|
|
find = ISC_LIST_NEXT(find, plink);
|
1999-10-16 00:38:21 +00:00
|
|
|
}
|
|
|
|
}
|
1999-10-19 20:55:04 +00:00
|
|
|
|
|
|
|
static isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype)
|
1999-10-19 20:55:04 +00:00
|
|
|
{
|
|
|
|
isc_result_t result;
|
1999-10-21 01:18:06 +00:00
|
|
|
dns_rdataset_t rdataset;
|
1999-10-29 01:26:45 +00:00
|
|
|
dns_adb_t *adb;
|
2000-01-21 02:50:27 +00:00
|
|
|
dns_fixedname_t foundname;
|
|
|
|
dns_name_t *fname;
|
1999-10-19 20:55:04 +00:00
|
|
|
|
|
|
|
INSIST(DNS_ADBNAME_VALID(adbname));
|
1999-10-29 01:26:45 +00:00
|
|
|
adb = adbname->adb;
|
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
1999-10-29 21:48:51 +00:00
|
|
|
INSIST(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa);
|
1999-10-19 20:55:04 +00:00
|
|
|
|
2000-01-21 02:50:27 +00:00
|
|
|
dns_fixedname_init(&foundname);
|
|
|
|
fname = dns_fixedname_name(&foundname);
|
1999-10-21 01:18:06 +00:00
|
|
|
dns_rdataset_init(&rdataset);
|
|
|
|
|
2000-01-21 02:50:27 +00:00
|
|
|
result = dns_view_find(adb->view, &adbname->name, rdtype, now,
|
Silence IRIX warnings:
"adb.c", line 2042: remark(1552): variable "result" was set but never used
isc_result_t result;
^
"adb.c", line 3082: warning(1185): enumerated type mixed with another type
NAME_GLUEOK(adbname), NAME_HINTOK(adbname),
^
"adb.c", line 3187: warning(1185): enumerated type mixed with another type
now, NAME_GLUEOK(adbname), NAME_HINTOK(adbname),
Note that the first is in timer_cleanup, a function returning void in a context
that can't do anything with something other than void (as an isc_taskaction_t).
It calls isc_timer_reset, which could conceivably return ISC_R_NOMEMORY or
ISC_R_UNEXPECTED. For now the call has been cast to void, but someone
who knows the code better should have a look and see whether something more
intelligent could be done with an error (and, if not, remove my XXX and
make sure the comment is clear as to why ignoring the return is the
best that can be done).
2000-05-13 20:15:16 +00:00
|
|
|
NAME_GLUEOK(adbname),
|
|
|
|
ISC_TF(NAME_HINTOK(adbname)),
|
2000-02-02 23:24:04 +00:00
|
|
|
fname, &rdataset, NULL);
|
|
|
|
|
1999-10-29 19:20:36 +00:00
|
|
|
switch (result) {
|
|
|
|
case DNS_R_GLUE:
|
|
|
|
case DNS_R_HINT:
|
2000-04-06 22:03:35 +00:00
|
|
|
case ISC_R_SUCCESS:
|
1999-10-29 19:20:36 +00:00
|
|
|
/*
|
|
|
|
* Found in the database. Even if we can't copy out
|
|
|
|
* any information, return success, or else a fetch
|
|
|
|
* will be made, which will only make things worse.
|
|
|
|
*/
|
1999-11-02 00:29:45 +00:00
|
|
|
result = import_rdataset(adbname, &rdataset, now);
|
1999-10-29 19:20:36 +00:00
|
|
|
break;
|
2000-01-15 00:45:49 +00:00
|
|
|
case DNS_R_NXDOMAIN:
|
|
|
|
case DNS_R_NXRRSET:
|
|
|
|
/*
|
|
|
|
* We're authoritative and the data doesn't exist.
|
|
|
|
* Make up a negative cache entry so we don't ask again
|
|
|
|
* for a while.
|
|
|
|
*
|
|
|
|
* XXXRTH What time should we use? I'm putting in 30 seconds
|
|
|
|
* for now.
|
|
|
|
*/
|
|
|
|
if (rdtype == dns_rdatatype_a) {
|
|
|
|
adbname->expire_v4 = now + 30;
|
|
|
|
DP(NCACHE_LEVEL,
|
|
|
|
"adb name %p: Caching auth negative entry for A",
|
|
|
|
adbname);
|
|
|
|
} else {
|
|
|
|
DP(NCACHE_LEVEL,
|
|
|
|
"adb name %p: Caching auth negative entry for AAAA",
|
|
|
|
adbname);
|
|
|
|
adbname->expire_v6 = now + 30;
|
|
|
|
}
|
2000-01-19 01:43:58 +00:00
|
|
|
break;
|
1999-11-04 06:46:05 +00:00
|
|
|
case DNS_R_NCACHENXDOMAIN:
|
|
|
|
case DNS_R_NCACHENXRRSET:
|
|
|
|
/*
|
|
|
|
* We found a negative cache entry. Pull the TTL from it
|
|
|
|
* so we won't ask again for a while.
|
|
|
|
*/
|
2000-06-07 20:15:48 +00:00
|
|
|
rdataset.ttl = ttlclamp(rdataset.ttl);
|
1999-11-04 06:46:05 +00:00
|
|
|
if (rdtype == dns_rdatatype_a) {
|
|
|
|
adbname->expire_v4 = rdataset.ttl + now;
|
2000-01-19 01:43:58 +00:00
|
|
|
DP(NCACHE_LEVEL,
|
|
|
|
"adb name %p: Caching negative entry for A (ttl %u)",
|
1999-11-05 02:05:06 +00:00
|
|
|
adbname, rdataset.ttl);
|
1999-11-04 06:46:05 +00:00
|
|
|
} else {
|
2000-01-19 01:43:58 +00:00
|
|
|
DP(NCACHE_LEVEL,
|
|
|
|
"adb name %p: Caching negative entry for AAAA (ttl %u)",
|
1999-11-05 02:05:06 +00:00
|
|
|
adbname, rdataset.ttl);
|
1999-11-04 06:46:05 +00:00
|
|
|
adbname->expire_v6 = rdataset.ttl + now;
|
|
|
|
}
|
2000-01-19 01:43:58 +00:00
|
|
|
break;
|
2000-01-21 02:50:27 +00:00
|
|
|
case DNS_R_CNAME:
|
|
|
|
case DNS_R_DNAME:
|
2000-02-02 23:24:04 +00:00
|
|
|
/*
|
|
|
|
* Clear the hint and glue flags, so this will match
|
|
|
|
* more often.
|
|
|
|
*/
|
|
|
|
adbname->flags &= ~(DNS_ADBFIND_GLUEOK | DNS_ADBFIND_HINTOK);
|
|
|
|
|
2000-06-07 20:15:48 +00:00
|
|
|
rdataset.ttl = ttlclamp(rdataset.ttl);
|
2000-01-21 02:50:27 +00:00
|
|
|
clean_target(adb, &adbname->target);
|
|
|
|
adbname->expire_target = INT_MAX;
|
|
|
|
result = set_target(adb, &adbname->name, fname, &rdataset,
|
|
|
|
&adbname->target);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
2000-01-28 00:32:32 +00:00
|
|
|
result = DNS_R_ALIAS;
|
2000-01-21 02:50:27 +00:00
|
|
|
DP(NCACHE_LEVEL,
|
|
|
|
"adb name %p: caching alias target",
|
|
|
|
adbname);
|
|
|
|
adbname->expire_target = rdataset.ttl + now;
|
|
|
|
}
|
|
|
|
break;
|
1999-10-29 19:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dns_rdataset_isassociated(&rdataset))
|
|
|
|
dns_rdataset_disassociate(&rdataset);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-10-30 02:26:03 +00:00
|
|
|
static isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dbfind_a6(dns_adbname_t *adbname, isc_stdtime_t now) {
|
1999-10-30 02:26:03 +00:00
|
|
|
isc_result_t result;
|
|
|
|
dns_rdataset_t rdataset;
|
|
|
|
dns_adb_t *adb;
|
|
|
|
dns_a6context_t a6ctx;
|
2000-01-21 02:50:27 +00:00
|
|
|
dns_fixedname_t foundname;
|
|
|
|
dns_name_t *fname;
|
1999-10-30 02:26:03 +00:00
|
|
|
|
|
|
|
INSIST(DNS_ADBNAME_VALID(adbname));
|
|
|
|
adb = adbname->adb;
|
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
1999-11-02 18:36:54 +00:00
|
|
|
INSIST(!NAME_FETCH_V6(adbname));
|
1999-10-30 02:26:03 +00:00
|
|
|
|
|
|
|
result = ISC_R_UNEXPECTED;
|
|
|
|
|
2000-01-21 02:50:27 +00:00
|
|
|
dns_fixedname_init(&foundname);
|
|
|
|
fname = dns_fixedname_name(&foundname);
|
1999-10-30 02:26:03 +00:00
|
|
|
dns_rdataset_init(&rdataset);
|
|
|
|
|
2000-01-21 02:50:27 +00:00
|
|
|
result = dns_view_find(adb->view, &adbname->name, dns_rdatatype_a6,
|
Silence IRIX warnings:
"adb.c", line 2042: remark(1552): variable "result" was set but never used
isc_result_t result;
^
"adb.c", line 3082: warning(1185): enumerated type mixed with another type
NAME_GLUEOK(adbname), NAME_HINTOK(adbname),
^
"adb.c", line 3187: warning(1185): enumerated type mixed with another type
now, NAME_GLUEOK(adbname), NAME_HINTOK(adbname),
Note that the first is in timer_cleanup, a function returning void in a context
that can't do anything with something other than void (as an isc_taskaction_t).
It calls isc_timer_reset, which could conceivably return ISC_R_NOMEMORY or
ISC_R_UNEXPECTED. For now the call has been cast to void, but someone
who knows the code better should have a look and see whether something more
intelligent could be done with an error (and, if not, remove my XXX and
make sure the comment is clear as to why ignoring the return is the
best that can be done).
2000-05-13 20:15:16 +00:00
|
|
|
now, NAME_GLUEOK(adbname),
|
|
|
|
ISC_TF(NAME_HINTOK(adbname)),
|
2000-02-02 23:24:04 +00:00
|
|
|
fname, &rdataset, NULL);
|
|
|
|
|
1999-10-30 02:26:03 +00:00
|
|
|
switch (result) {
|
|
|
|
case DNS_R_GLUE:
|
|
|
|
case DNS_R_HINT:
|
2000-04-06 22:03:35 +00:00
|
|
|
case ISC_R_SUCCESS:
|
1999-10-30 02:26:03 +00:00
|
|
|
/*
|
|
|
|
* Start a6 chain follower. There is no need to poke people
|
|
|
|
* who might be waiting, since this is call requires there
|
|
|
|
* are none.
|
|
|
|
*/
|
|
|
|
dns_a6_init(&a6ctx, a6find, NULL, import_a6,
|
|
|
|
a6missing, adbname);
|
1999-11-22 19:57:58 +00:00
|
|
|
(void)dns_a6_foreach(&a6ctx, &rdataset, now);
|
1999-10-30 02:26:03 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
break;
|
2000-01-19 01:43:58 +00:00
|
|
|
case DNS_R_NXDOMAIN:
|
|
|
|
case DNS_R_NXRRSET:
|
|
|
|
/*
|
|
|
|
* We're authoritative and the data doesn't exist.
|
|
|
|
* Make up a negative cache entry so we don't ask again
|
|
|
|
* for a while.
|
|
|
|
*
|
|
|
|
* XXXRTH What time should we use? I'm putting in 30 seconds
|
|
|
|
* for now.
|
|
|
|
*/
|
|
|
|
DP(NCACHE_LEVEL,
|
|
|
|
"adb name %p: Caching auth negative entry for AAAA",
|
|
|
|
adbname);
|
|
|
|
adbname->expire_v6 = now + 30;
|
|
|
|
break;
|
1999-11-04 06:46:05 +00:00
|
|
|
case DNS_R_NCACHENXDOMAIN:
|
|
|
|
case DNS_R_NCACHENXRRSET:
|
|
|
|
/*
|
|
|
|
* We found a negative cache entry. Pull the TTL from it
|
|
|
|
* so we won't ask again for a while.
|
|
|
|
*/
|
2000-01-19 01:43:58 +00:00
|
|
|
DP(NCACHE_LEVEL,
|
|
|
|
"adb name %p: Caching negative entry for A6 (ttl %u)",
|
1999-11-24 19:23:27 +00:00
|
|
|
adbname, rdataset.ttl);
|
|
|
|
adbname->expire_v6 = ISC_MIN(rdataset.ttl + now,
|
|
|
|
adbname->expire_v6);
|
2000-01-21 02:50:27 +00:00
|
|
|
break;
|
|
|
|
case DNS_R_CNAME:
|
|
|
|
case DNS_R_DNAME:
|
2000-06-07 20:15:48 +00:00
|
|
|
rdataset.ttl = ttlclamp(rdataset.ttl);
|
2000-01-21 02:50:27 +00:00
|
|
|
clean_target(adb, &adbname->target);
|
|
|
|
adbname->expire_target = INT_MAX;
|
|
|
|
result = set_target(adb, &adbname->name, fname, &rdataset,
|
|
|
|
&adbname->target);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
2000-01-28 00:32:32 +00:00
|
|
|
result = DNS_R_ALIAS;
|
2000-01-21 02:50:27 +00:00
|
|
|
DP(NCACHE_LEVEL,
|
|
|
|
"adb name %p: caching alias target",
|
|
|
|
adbname);
|
|
|
|
adbname->expire_target = rdataset.ttl + now;
|
|
|
|
}
|
|
|
|
break;
|
1999-10-30 02:26:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dns_rdataset_isassociated(&rdataset))
|
|
|
|
dns_rdataset_disassociate(&rdataset);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-10-27 19:36:58 +00:00
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
fetch_callback(isc_task_t *task, isc_event_t *ev) {
|
1999-10-27 19:36:58 +00:00
|
|
|
dns_fetchevent_t *dev;
|
|
|
|
dns_adbname_t *name;
|
|
|
|
dns_adb_t *adb;
|
|
|
|
dns_adbfetch_t *fetch;
|
|
|
|
int bucket;
|
|
|
|
isc_eventtype_t ev_status;
|
1999-10-27 22:24:40 +00:00
|
|
|
isc_stdtime_t now;
|
|
|
|
isc_result_t result;
|
1999-11-04 06:46:05 +00:00
|
|
|
unsigned int address_type;
|
2000-01-13 20:42:43 +00:00
|
|
|
isc_boolean_t want_check_exit = ISC_FALSE;
|
1999-10-27 19:36:58 +00:00
|
|
|
|
2000-08-11 16:47:33 +00:00
|
|
|
UNUSED(task);
|
1999-10-27 19:36:58 +00:00
|
|
|
|
2000-04-17 19:22:44 +00:00
|
|
|
INSIST(ev->ev_type == DNS_EVENT_FETCHDONE);
|
1999-10-27 19:36:58 +00:00
|
|
|
dev = (dns_fetchevent_t *)ev;
|
2000-04-17 19:22:44 +00:00
|
|
|
name = ev->ev_arg;
|
1999-10-27 19:36:58 +00:00
|
|
|
INSIST(DNS_ADBNAME_VALID(name));
|
|
|
|
adb = name->adb;
|
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
|
|
|
|
|
|
|
bucket = name->lock_bucket;
|
|
|
|
LOCK(&adb->namelocks[bucket]);
|
|
|
|
|
1999-11-04 09:04:29 +00:00
|
|
|
INSIST(NAME_FETCH_A(name) || NAME_FETCH_AAAA(name));
|
1999-11-04 06:46:05 +00:00
|
|
|
address_type = 0;
|
1999-11-04 09:04:29 +00:00
|
|
|
if (NAME_FETCH_A(name) && (name->fetch_a->fetch == dev->fetch)) {
|
|
|
|
address_type = DNS_ADBFIND_INET;
|
|
|
|
fetch = name->fetch_a;
|
|
|
|
name->fetch_a = NULL;
|
|
|
|
} else if (NAME_FETCH_AAAA(name)
|
|
|
|
&& (name->fetch_aaaa->fetch == dev->fetch)) {
|
|
|
|
address_type = DNS_ADBFIND_INET6;
|
|
|
|
fetch = name->fetch_aaaa;
|
|
|
|
name->fetch_aaaa = NULL;
|
|
|
|
}
|
1999-11-04 06:46:05 +00:00
|
|
|
INSIST(address_type != 0);
|
1999-10-29 21:48:51 +00:00
|
|
|
|
2000-01-21 02:50:27 +00:00
|
|
|
dns_resolver_destroyfetch(&fetch->fetch);
|
1999-10-29 19:20:36 +00:00
|
|
|
dev->fetch = NULL;
|
|
|
|
|
1999-10-29 23:53:12 +00:00
|
|
|
ev_status = DNS_EVENT_ADBNOMOREADDRESSES;
|
|
|
|
|
1999-10-29 19:20:36 +00:00
|
|
|
/*
|
|
|
|
* Cleanup things we don't care about.
|
|
|
|
*/
|
|
|
|
if (dev->node != NULL)
|
|
|
|
dns_db_detachnode(dev->db, &dev->node);
|
|
|
|
if (dev->db != NULL)
|
|
|
|
dns_db_detach(&dev->db);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this name is marked as dead, clean up, throwing away
|
|
|
|
* potentially good data.
|
|
|
|
*/
|
1999-10-30 01:58:02 +00:00
|
|
|
if (NAME_DEAD(name)) {
|
1999-10-29 19:20:36 +00:00
|
|
|
free_adbfetch(adb, &fetch);
|
|
|
|
isc_event_free(&ev);
|
|
|
|
|
|
|
|
kill_name(&name, DNS_EVENT_ADBCANCELED);
|
|
|
|
|
2000-01-13 20:42:43 +00:00
|
|
|
/*
|
|
|
|
* If we're shutting down and this bucket is empty, we need
|
|
|
|
* to call check_exit() to see if we're done.
|
|
|
|
*/
|
|
|
|
if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0)
|
|
|
|
want_check_exit = ISC_TRUE;
|
1999-10-29 19:20:36 +00:00
|
|
|
|
|
|
|
UNLOCK(&adb->namelocks[bucket]);
|
|
|
|
|
2000-01-13 20:42:43 +00:00
|
|
|
if (want_check_exit) {
|
|
|
|
LOCK(&adb->lock);
|
|
|
|
check_exit(adb);
|
|
|
|
UNLOCK(&adb->lock);
|
|
|
|
}
|
1999-10-29 19:20:36 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2000-01-21 02:50:27 +00:00
|
|
|
isc_stdtime_get(&now);
|
|
|
|
|
1999-11-24 19:23:27 +00:00
|
|
|
/*
|
|
|
|
* If we got a negative cache response, remember it.
|
|
|
|
*/
|
|
|
|
if (NCACHE_RESULT(dev->result)) {
|
2000-06-07 20:15:48 +00:00
|
|
|
dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
|
1999-11-24 19:23:27 +00:00
|
|
|
if (address_type == DNS_ADBFIND_INET) {
|
1999-12-01 02:05:16 +00:00
|
|
|
DP(NCACHE_LEVEL, "adb fetch name %p: "
|
1999-11-24 19:23:27 +00:00
|
|
|
"Caching negative entry for A (ttl %u)",
|
|
|
|
name, dev->rdataset->ttl);
|
|
|
|
name->expire_v4 = ISC_MIN(name->expire_v4,
|
|
|
|
dev->rdataset->ttl + now);
|
|
|
|
} else {
|
1999-12-01 02:05:16 +00:00
|
|
|
DP(NCACHE_LEVEL, "adb fetch name %p: "
|
1999-11-24 19:23:27 +00:00
|
|
|
"Caching negative entry for AAAA (ttl %u)",
|
|
|
|
name, dev->rdataset->ttl);
|
|
|
|
name->expire_v6 = ISC_MIN(name->expire_v6,
|
|
|
|
dev->rdataset->ttl + now);
|
|
|
|
}
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
1999-11-25 01:23:32 +00:00
|
|
|
/*
|
2000-01-21 02:50:27 +00:00
|
|
|
* Handle CNAME/DNAME.
|
1999-11-25 01:23:32 +00:00
|
|
|
*/
|
2000-01-21 02:50:27 +00:00
|
|
|
if (dev->result == DNS_R_CNAME || dev->result == DNS_R_DNAME) {
|
2000-06-07 20:15:48 +00:00
|
|
|
dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
|
2000-01-21 02:50:27 +00:00
|
|
|
clean_target(adb, &name->target);
|
|
|
|
name->expire_target = INT_MAX;
|
|
|
|
result = set_target(adb, &name->name,
|
|
|
|
dns_fixedname_name(&dev->foundname),
|
|
|
|
dev->rdataset,
|
|
|
|
&name->target);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
DP(NCACHE_LEVEL,
|
|
|
|
"adb fetch name %p: caching alias target",
|
|
|
|
name);
|
|
|
|
name->expire_target = dev->rdataset->ttl + now;
|
|
|
|
}
|
|
|
|
goto check_result;
|
|
|
|
}
|
1999-11-25 01:23:32 +00:00
|
|
|
|
1999-10-29 19:20:36 +00:00
|
|
|
/*
|
|
|
|
* Did we get back junk? If so, and there are no more fetches
|
|
|
|
* sitting out there, tell all the finds about it.
|
|
|
|
*/
|
1999-11-04 09:42:46 +00:00
|
|
|
if (dev->result != ISC_R_SUCCESS) {
|
|
|
|
/* XXXMLG Don't pound on bad servers. */
|
|
|
|
if (address_type == DNS_ADBFIND_INET)
|
|
|
|
name->expire_v4 = ISC_MIN(name->expire_v4, now + 300);
|
|
|
|
else
|
|
|
|
name->expire_v6 = ISC_MIN(name->expire_v6, now + 300);
|
1999-11-24 19:23:27 +00:00
|
|
|
DP(1, "got junk in fetch for name %p (%s)",
|
|
|
|
name, isc_result_totext(dev->result));
|
1999-11-04 09:42:46 +00:00
|
|
|
|
1999-10-29 19:20:36 +00:00
|
|
|
goto out;
|
1999-11-04 09:42:46 +00:00
|
|
|
}
|
1999-10-29 19:20:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We got something potentially useful.
|
|
|
|
*/
|
1999-12-16 23:29:07 +00:00
|
|
|
result = import_rdataset(name, &fetch->rdataset, now);
|
2000-01-21 02:50:27 +00:00
|
|
|
|
|
|
|
check_result:
|
1999-10-29 19:20:36 +00:00
|
|
|
if (result == ISC_R_SUCCESS)
|
|
|
|
ev_status = DNS_EVENT_ADBMOREADDRESSES;
|
|
|
|
|
|
|
|
out:
|
|
|
|
free_adbfetch(adb, &fetch);
|
|
|
|
isc_event_free(&ev);
|
|
|
|
|
1999-11-04 06:46:05 +00:00
|
|
|
clean_finds_at_name(name, ev_status, address_type);
|
1999-10-27 19:36:58 +00:00
|
|
|
|
|
|
|
UNLOCK(&adb->namelocks[bucket]);
|
|
|
|
}
|
|
|
|
|
1999-10-30 01:22:16 +00:00
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
fetch_callback_a6(isc_task_t *task, isc_event_t *ev) {
|
1999-10-30 01:22:16 +00:00
|
|
|
dns_fetchevent_t *dev;
|
|
|
|
dns_adbname_t *name;
|
|
|
|
dns_adb_t *adb;
|
|
|
|
dns_adbfetch6_t *fetch;
|
|
|
|
int bucket;
|
1999-11-22 19:57:58 +00:00
|
|
|
isc_stdtime_t now;
|
|
|
|
isc_result_t result;
|
2000-01-13 20:42:43 +00:00
|
|
|
isc_boolean_t want_check_exit = ISC_FALSE;
|
1999-10-30 01:22:16 +00:00
|
|
|
|
2000-08-11 16:47:33 +00:00
|
|
|
UNUSED(task);
|
1999-10-30 01:22:16 +00:00
|
|
|
|
2000-04-17 19:22:44 +00:00
|
|
|
INSIST(ev->ev_type == DNS_EVENT_FETCHDONE);
|
1999-10-30 01:22:16 +00:00
|
|
|
dev = (dns_fetchevent_t *)ev;
|
2000-04-17 19:22:44 +00:00
|
|
|
name = ev->ev_arg;
|
1999-10-30 01:22:16 +00:00
|
|
|
INSIST(DNS_ADBNAME_VALID(name));
|
|
|
|
adb = name->adb;
|
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
|
|
|
|
|
|
|
bucket = name->lock_bucket;
|
|
|
|
LOCK(&adb->namelocks[bucket]);
|
|
|
|
|
1999-10-30 01:58:02 +00:00
|
|
|
INSIST(!NAME_NEEDSPOKE(name));
|
1999-10-30 02:40:59 +00:00
|
|
|
|
1999-10-30 01:22:16 +00:00
|
|
|
for (fetch = ISC_LIST_HEAD(name->fetches_a6);
|
|
|
|
fetch != NULL;
|
|
|
|
fetch = ISC_LIST_NEXT(fetch, plink))
|
|
|
|
if (fetch->fetch == dev->fetch)
|
|
|
|
break;
|
|
|
|
INSIST(fetch != NULL);
|
|
|
|
ISC_LIST_UNLINK(name->fetches_a6, fetch, plink);
|
|
|
|
|
1999-11-01 20:16:35 +00:00
|
|
|
DP(ENTER_LEVEL, "ENTER: fetch_callback_a6() name %p", name);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-01-21 02:50:27 +00:00
|
|
|
dns_resolver_destroyfetch(&fetch->fetch);
|
1999-10-30 01:22:16 +00:00
|
|
|
dev->fetch = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Cleanup things we don't care about.
|
|
|
|
*/
|
|
|
|
if (dev->node != NULL)
|
|
|
|
dns_db_detachnode(dev->db, &dev->node);
|
|
|
|
if (dev->db != NULL)
|
|
|
|
dns_db_detach(&dev->db);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this name is marked as dead, clean up, throwing away
|
|
|
|
* potentially good data.
|
|
|
|
*/
|
1999-10-30 01:58:02 +00:00
|
|
|
if (NAME_DEAD(name)) {
|
1999-10-30 01:22:16 +00:00
|
|
|
free_adbfetch6(adb, &fetch);
|
|
|
|
isc_event_free(&ev);
|
|
|
|
|
|
|
|
kill_name(&name, DNS_EVENT_ADBCANCELED);
|
|
|
|
|
2000-01-13 20:42:43 +00:00
|
|
|
/*
|
|
|
|
* If we're shutting down and this bucket is empty, we need
|
|
|
|
* to call check_exit() to see if we're done.
|
|
|
|
*/
|
|
|
|
if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0)
|
|
|
|
want_check_exit = ISC_TRUE;
|
1999-10-30 01:22:16 +00:00
|
|
|
|
|
|
|
UNLOCK(&adb->namelocks[bucket]);
|
|
|
|
|
2000-01-13 20:42:43 +00:00
|
|
|
if (want_check_exit) {
|
|
|
|
LOCK(&adb->lock);
|
|
|
|
check_exit(adb);
|
|
|
|
UNLOCK(&adb->lock);
|
|
|
|
}
|
1999-10-30 01:22:16 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-12-16 23:29:07 +00:00
|
|
|
isc_stdtime_get(&now);
|
1999-11-22 19:57:58 +00:00
|
|
|
|
1999-10-30 01:22:16 +00:00
|
|
|
/*
|
1999-11-02 00:29:45 +00:00
|
|
|
* If the A6 query didn't succeed, and this is the first query
|
|
|
|
* in the A6 chain, try AAAA records instead. For later failures,
|
|
|
|
* don't do this.
|
1999-10-30 01:22:16 +00:00
|
|
|
*/
|
1999-11-02 00:29:45 +00:00
|
|
|
if (dev->result != ISC_R_SUCCESS) {
|
2000-08-09 21:15:32 +00:00
|
|
|
DP(DEF_LEVEL, "name %p: A6 failed: %s",
|
|
|
|
name, isc_result_totext(dev->result));
|
1999-11-02 00:29:45 +00:00
|
|
|
|
1999-11-24 19:23:27 +00:00
|
|
|
/*
|
|
|
|
* If we got a negative cache response, remember it.
|
|
|
|
*/
|
|
|
|
if (NCACHE_RESULT(dev->result)) {
|
2000-06-07 20:15:48 +00:00
|
|
|
dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
|
1999-12-01 02:05:16 +00:00
|
|
|
DP(NCACHE_LEVEL, "adb fetch name %p: "
|
1999-11-24 19:23:27 +00:00
|
|
|
"Caching negative entry for A6 (ttl %u)",
|
|
|
|
name, dev->rdataset->ttl);
|
|
|
|
name->expire_v6 = ISC_MIN(name->expire_v6,
|
|
|
|
dev->rdataset->ttl + now);
|
|
|
|
}
|
|
|
|
|
2000-01-21 02:50:27 +00:00
|
|
|
/*
|
2000-01-22 00:19:55 +00:00
|
|
|
* Handle CNAME/DNAME.
|
2000-01-21 02:50:27 +00:00
|
|
|
*/
|
2000-01-22 00:19:55 +00:00
|
|
|
if (dev->result == DNS_R_CNAME || dev->result == DNS_R_DNAME) {
|
2000-06-07 20:15:48 +00:00
|
|
|
dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
|
2000-01-22 00:19:55 +00:00
|
|
|
clean_target(adb, &name->target);
|
|
|
|
name->expire_target = INT_MAX;
|
|
|
|
result = set_target(adb, &name->name,
|
|
|
|
dns_fixedname_name(&dev->foundname),
|
|
|
|
dev->rdataset,
|
|
|
|
&name->target);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
DP(NCACHE_LEVEL,
|
|
|
|
"adb A6 fetch name %p: caching alias target",
|
|
|
|
name);
|
|
|
|
name->expire_target = dev->rdataset->ttl + now;
|
|
|
|
if (FETCH_FIRSTA6(fetch)) {
|
|
|
|
/*
|
|
|
|
* Make this name 'pokeable', since
|
|
|
|
* we've learned that this name is an
|
|
|
|
* alias.
|
|
|
|
*/
|
|
|
|
name->flags |= NAME_NEEDS_POKE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
goto out;
|
|
|
|
}
|
2000-01-21 02:50:27 +00:00
|
|
|
|
1999-11-04 08:48:47 +00:00
|
|
|
if (FETCH_FIRSTA6(fetch) && !NAME_HAS_V6(name)) {
|
1999-11-02 00:29:45 +00:00
|
|
|
DP(DEF_LEVEL,
|
|
|
|
"name %p: A6 query failed, starting AAAA", name);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since this is the very first fetch, and it
|
|
|
|
* failed, we know there are no more running.
|
|
|
|
*/
|
2000-02-02 23:24:04 +00:00
|
|
|
result = dbfind_name(name, now, dns_rdatatype_aaaa);
|
1999-11-02 00:29:45 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
DP(DEF_LEVEL,
|
|
|
|
"name %p: callback_a6: Found AAAA for",
|
|
|
|
name);
|
|
|
|
name->flags |= NAME_NEEDS_POKE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
1999-11-24 19:23:27 +00:00
|
|
|
/*
|
|
|
|
* Listen to negative cache hints, and don't start
|
|
|
|
* another query.
|
|
|
|
*/
|
2000-01-15 00:45:49 +00:00
|
|
|
if (NCACHE_RESULT(result) || AUTH_NX(result))
|
1999-11-24 19:23:27 +00:00
|
|
|
goto out;
|
|
|
|
|
1999-11-02 00:29:45 +00:00
|
|
|
/*
|
|
|
|
* Try to start fetches for AAAA.
|
|
|
|
*/
|
2000-01-19 01:43:58 +00:00
|
|
|
result = fetch_name_aaaa(name);
|
1999-11-02 00:29:45 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
DP(DEF_LEVEL,
|
|
|
|
"name %p: callback_a6: Started AAAA fetch",
|
|
|
|
name);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-10-30 01:22:16 +00:00
|
|
|
goto out;
|
1999-11-02 00:29:45 +00:00
|
|
|
}
|
1999-10-30 01:22:16 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We got something potentially useful. Run the A6 chain
|
|
|
|
* follower on this A6 rdataset.
|
|
|
|
*/
|
|
|
|
|
|
|
|
fetch->a6ctx.chains = name->chains;
|
1999-11-22 19:57:58 +00:00
|
|
|
(void)dns_a6_foreach(&fetch->a6ctx, dev->rdataset, now);
|
1999-10-30 01:22:16 +00:00
|
|
|
|
|
|
|
out:
|
|
|
|
free_adbfetch6(adb, &fetch);
|
|
|
|
isc_event_free(&ev);
|
|
|
|
|
1999-10-30 01:58:02 +00:00
|
|
|
if (NAME_NEEDSPOKE(name))
|
1999-10-30 01:22:16 +00:00
|
|
|
clean_finds_at_name(name, DNS_EVENT_ADBMOREADDRESSES,
|
|
|
|
DNS_ADBFIND_INET6);
|
1999-11-02 18:36:54 +00:00
|
|
|
else if (!NAME_FETCH_V6(name))
|
1999-10-30 01:22:16 +00:00
|
|
|
clean_finds_at_name(name, DNS_EVENT_ADBNOMOREADDRESSES,
|
|
|
|
DNS_ADBFIND_INET6);
|
|
|
|
|
1999-10-30 01:58:02 +00:00
|
|
|
name->flags &= ~NAME_NEEDS_POKE;
|
1999-10-30 01:22:16 +00:00
|
|
|
|
|
|
|
UNLOCK(&adb->namelocks[bucket]);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-10-26 01:12:20 +00:00
|
|
|
static isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
fetch_name_v4(dns_adbname_t *adbname, isc_boolean_t start_at_root) {
|
1999-10-27 19:36:58 +00:00
|
|
|
isc_result_t result;
|
|
|
|
dns_adbfetch_t *fetch;
|
1999-10-29 01:26:45 +00:00
|
|
|
dns_adb_t *adb;
|
2000-01-06 00:56:37 +00:00
|
|
|
dns_name_t *name;
|
2000-02-12 02:19:53 +00:00
|
|
|
dns_rdataset_t rdataset;
|
|
|
|
dns_rdataset_t *nameservers;
|
1999-10-29 01:26:45 +00:00
|
|
|
|
|
|
|
INSIST(DNS_ADBNAME_VALID(adbname));
|
|
|
|
adb = adbname->adb;
|
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
1999-10-27 19:36:58 +00:00
|
|
|
|
1999-11-02 18:36:54 +00:00
|
|
|
INSIST(!NAME_FETCH_V4(adbname));
|
1999-10-29 21:48:51 +00:00
|
|
|
|
2000-02-12 02:19:53 +00:00
|
|
|
name = NULL;
|
|
|
|
nameservers = NULL;
|
|
|
|
dns_rdataset_init(&rdataset);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-01-06 00:56:37 +00:00
|
|
|
if (start_at_root) {
|
|
|
|
DP(50, "fetch_name_v4: starting at DNS root for name %p",
|
|
|
|
adbname);
|
|
|
|
name = dns_rootname;
|
2000-02-12 02:19:53 +00:00
|
|
|
result = dns_view_simplefind(adb->view, name, dns_rdatatype_ns,
|
|
|
|
0, 0, ISC_TRUE, &rdataset, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS && result != DNS_R_HINT)
|
|
|
|
goto cleanup;
|
|
|
|
nameservers = &rdataset;
|
|
|
|
}
|
1999-10-27 19:36:58 +00:00
|
|
|
|
|
|
|
fetch = new_adbfetch(adb);
|
|
|
|
if (fetch == NULL) {
|
|
|
|
result = ISC_R_NOMEMORY;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = dns_resolver_createfetch(adb->view->resolver, &adbname->name,
|
2000-01-19 01:43:58 +00:00
|
|
|
dns_rdatatype_a,
|
2000-02-12 02:19:53 +00:00
|
|
|
name, nameservers, NULL, 0,
|
1999-11-04 06:46:05 +00:00
|
|
|
adb->task, fetch_callback,
|
1999-10-29 01:26:45 +00:00
|
|
|
adbname, &fetch->rdataset, NULL,
|
1999-10-27 19:36:58 +00:00
|
|
|
&fetch->fetch);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
|
1999-10-29 21:48:51 +00:00
|
|
|
adbname->fetch_a = fetch;
|
1999-10-27 19:36:58 +00:00
|
|
|
fetch = NULL; /* keep us from cleaning this up below */
|
1999-10-29 19:20:36 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (fetch != NULL)
|
|
|
|
free_adbfetch(adb, &fetch);
|
2000-02-12 02:19:53 +00:00
|
|
|
if (dns_rdataset_isassociated(&rdataset))
|
|
|
|
dns_rdataset_disassociate(&rdataset);
|
1999-10-29 19:20:36 +00:00
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
fetch_name_aaaa(dns_adbname_t *adbname) {
|
1999-10-29 19:20:36 +00:00
|
|
|
isc_result_t result;
|
|
|
|
dns_adbfetch_t *fetch;
|
|
|
|
dns_adb_t *adb;
|
|
|
|
|
|
|
|
INSIST(DNS_ADBNAME_VALID(adbname));
|
|
|
|
adb = adbname->adb;
|
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
|
|
|
|
1999-11-02 18:36:54 +00:00
|
|
|
INSIST(!NAME_FETCH_AAAA(adbname));
|
1999-10-29 21:48:51 +00:00
|
|
|
|
1999-10-29 19:20:36 +00:00
|
|
|
fetch = new_adbfetch(adb);
|
|
|
|
if (fetch == NULL) {
|
|
|
|
result = ISC_R_NOMEMORY;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = dns_resolver_createfetch(adb->view->resolver, &adbname->name,
|
2000-01-19 01:43:58 +00:00
|
|
|
dns_rdatatype_aaaa,
|
|
|
|
NULL, NULL, NULL, 0,
|
1999-11-04 06:46:05 +00:00
|
|
|
adb->task, fetch_callback,
|
1999-10-29 19:20:36 +00:00
|
|
|
adbname, &fetch->rdataset, NULL,
|
|
|
|
&fetch->fetch);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
|
1999-10-29 21:48:51 +00:00
|
|
|
adbname->fetch_aaaa = fetch;
|
1999-10-29 19:20:36 +00:00
|
|
|
fetch = NULL; /* keep us from cleaning this up below */
|
1999-10-27 19:36:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (fetch != NULL)
|
|
|
|
free_adbfetch(adb, &fetch);
|
|
|
|
|
|
|
|
return (result);
|
1999-10-26 01:12:20 +00:00
|
|
|
}
|
|
|
|
|
1999-10-30 02:26:03 +00:00
|
|
|
static isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
fetch_name_a6(dns_adbname_t *adbname, isc_boolean_t start_at_root) {
|
1999-10-30 02:26:03 +00:00
|
|
|
isc_result_t result;
|
|
|
|
dns_adbfetch6_t *fetch;
|
|
|
|
dns_adb_t *adb;
|
2000-01-06 00:56:37 +00:00
|
|
|
dns_name_t *name;
|
2000-02-12 02:19:53 +00:00
|
|
|
dns_rdataset_t rdataset;
|
|
|
|
dns_rdataset_t *nameservers;
|
1999-10-30 02:26:03 +00:00
|
|
|
|
|
|
|
INSIST(DNS_ADBNAME_VALID(adbname));
|
|
|
|
adb = adbname->adb;
|
|
|
|
INSIST(DNS_ADB_VALID(adb));
|
|
|
|
|
1999-11-02 18:36:54 +00:00
|
|
|
INSIST(!NAME_FETCH_V6(adbname));
|
1999-10-30 02:26:03 +00:00
|
|
|
|
2000-02-12 02:19:53 +00:00
|
|
|
name = NULL;
|
|
|
|
nameservers = NULL;
|
|
|
|
dns_rdataset_init(&rdataset);
|
|
|
|
|
2000-01-06 00:56:37 +00:00
|
|
|
if (start_at_root) {
|
|
|
|
DP(50, "fetch_name_a6: starting at DNS root for name %p",
|
|
|
|
adbname);
|
|
|
|
name = dns_rootname;
|
2000-02-12 02:19:53 +00:00
|
|
|
result = dns_view_simplefind(adb->view, name, dns_rdatatype_ns,
|
|
|
|
0, 0, ISC_TRUE, &rdataset, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS && result != DNS_R_HINT)
|
|
|
|
goto cleanup;
|
|
|
|
nameservers = &rdataset;
|
|
|
|
}
|
1999-10-30 02:26:03 +00:00
|
|
|
|
|
|
|
fetch = new_adbfetch6(adb, adbname, NULL);
|
|
|
|
if (fetch == NULL) {
|
|
|
|
result = ISC_R_NOMEMORY;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-11-04 08:48:47 +00:00
|
|
|
fetch->flags |= FETCH_FIRST_A6;
|
1999-10-30 02:26:03 +00:00
|
|
|
|
|
|
|
result = dns_resolver_createfetch(adb->view->resolver, &adbname->name,
|
2000-01-19 01:43:58 +00:00
|
|
|
dns_rdatatype_a6,
|
2000-02-12 02:19:53 +00:00
|
|
|
name, nameservers, NULL, 0,
|
1999-10-30 02:26:03 +00:00
|
|
|
adb->task, fetch_callback_a6,
|
|
|
|
adbname, &fetch->rdataset, NULL,
|
|
|
|
&fetch->fetch);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ISC_LIST_APPEND(adbname->fetches_a6, fetch, plink);
|
|
|
|
fetch = NULL; /* keep us from cleaning this up below */
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (fetch != NULL)
|
|
|
|
free_adbfetch6(adb, &fetch);
|
2000-02-12 02:19:53 +00:00
|
|
|
if (dns_rdataset_isassociated(&rdataset))
|
|
|
|
dns_rdataset_disassociate(&rdataset);
|
1999-10-30 02:26:03 +00:00
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-11-02 00:29:45 +00:00
|
|
|
/* XXXMLG
|
|
|
|
* Needs to take a find argument and an address info, no zone or adb, since
|
|
|
|
* these can be extracted from the find itself.
|
|
|
|
*/
|
1999-10-19 21:10:29 +00:00
|
|
|
isc_result_t
|
1999-10-19 21:28:09 +00:00
|
|
|
dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *zone,
|
|
|
|
isc_stdtime_t expire_time)
|
1999-10-19 21:10:29 +00:00
|
|
|
{
|
|
|
|
dns_adbzoneinfo_t *zi;
|
1999-10-19 21:28:09 +00:00
|
|
|
int bucket;
|
1999-10-19 21:10:29 +00:00
|
|
|
|
|
|
|
REQUIRE(DNS_ADB_VALID(adb));
|
|
|
|
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
|
|
|
|
zi = new_adbzoneinfo(adb, zone);
|
|
|
|
if (zi == NULL)
|
|
|
|
return (ISC_R_NOMEMORY);
|
|
|
|
|
1999-10-19 21:28:09 +00:00
|
|
|
zi->lame_timer = expire_time;
|
|
|
|
|
|
|
|
bucket = addr->entry->lock_bucket;
|
|
|
|
LOCK(&adb->entrylocks[bucket]);
|
1999-10-29 01:53:20 +00:00
|
|
|
ISC_LIST_PREPEND(addr->entry->zoneinfo, zi, plink);
|
1999-10-19 21:28:09 +00:00
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
|
|
|
|
1999-10-19 21:10:29 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
1999-10-19 22:06:08 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
dns_adb_adjustgoodness(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
|
|
|
|
int goodness_adjustment)
|
|
|
|
{
|
|
|
|
int bucket;
|
|
|
|
int old_goodness, new_goodness;
|
|
|
|
|
1999-10-19 22:21:27 +00:00
|
|
|
REQUIRE(DNS_ADB_VALID(adb));
|
1999-10-19 22:06:08 +00:00
|
|
|
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
|
|
|
|
|
|
|
if (goodness_adjustment == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bucket = addr->entry->lock_bucket;
|
|
|
|
LOCK(&adb->entrylocks[bucket]);
|
|
|
|
|
|
|
|
old_goodness = addr->entry->goodness;
|
|
|
|
|
|
|
|
if (goodness_adjustment > 0) {
|
|
|
|
if (old_goodness > INT_MAX - goodness_adjustment)
|
|
|
|
new_goodness = INT_MAX;
|
|
|
|
else
|
|
|
|
new_goodness = old_goodness + goodness_adjustment;
|
|
|
|
} else {
|
|
|
|
if (old_goodness < INT_MIN - goodness_adjustment)
|
2000-02-11 02:58:44 +00:00
|
|
|
new_goodness = INT_MIN;
|
1999-10-19 22:06:08 +00:00
|
|
|
else
|
|
|
|
new_goodness = old_goodness + goodness_adjustment;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr->entry->goodness = new_goodness;
|
1999-10-19 22:21:27 +00:00
|
|
|
addr->goodness = new_goodness;
|
1999-10-19 22:06:08 +00:00
|
|
|
|
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
|
|
|
}
|
|
|
|
|
1999-10-19 22:21:27 +00:00
|
|
|
void
|
|
|
|
dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
|
|
|
|
unsigned int rtt, unsigned int factor)
|
|
|
|
{
|
|
|
|
int bucket;
|
|
|
|
unsigned int new_srtt;
|
|
|
|
|
|
|
|
REQUIRE(DNS_ADB_VALID(adb));
|
|
|
|
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
1999-11-19 00:30:13 +00:00
|
|
|
REQUIRE(factor <= 10);
|
1999-10-19 22:21:27 +00:00
|
|
|
|
|
|
|
bucket = addr->entry->lock_bucket;
|
|
|
|
LOCK(&adb->entrylocks[bucket]);
|
|
|
|
|
1999-11-19 00:30:13 +00:00
|
|
|
new_srtt = (addr->entry->srtt / 10 * factor)
|
|
|
|
+ (rtt / 10 * (10 - factor));
|
|
|
|
|
1999-10-19 22:21:27 +00:00
|
|
|
addr->entry->srtt = new_srtt;
|
|
|
|
addr->srtt = new_srtt;
|
|
|
|
|
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
|
|
|
}
|
1999-11-16 06:53:29 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
|
|
|
|
unsigned int bits, unsigned int mask)
|
|
|
|
{
|
|
|
|
int bucket;
|
|
|
|
|
|
|
|
REQUIRE(DNS_ADB_VALID(adb));
|
|
|
|
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
|
|
|
|
|
|
|
bucket = addr->entry->lock_bucket;
|
|
|
|
LOCK(&adb->entrylocks[bucket]);
|
|
|
|
|
1999-11-16 21:04:18 +00:00
|
|
|
addr->entry->flags = (addr->entry->flags & ~mask) | (bits & mask);
|
|
|
|
/*
|
|
|
|
* Note that we do not update the other bits in addr->flags with
|
|
|
|
* the most recent values from addr->entry->flags.
|
|
|
|
*/
|
|
|
|
addr->flags = (addr->flags & ~mask) | (bits & mask);
|
1999-11-16 06:53:29 +00:00
|
|
|
|
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
|
|
|
}
|
2000-01-12 03:00:33 +00:00
|
|
|
|
2000-02-16 00:16:36 +00:00
|
|
|
void
|
|
|
|
dns_adb_setavoidbitstring(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
|
|
|
|
isc_stdtime_t when)
|
|
|
|
{
|
|
|
|
int bucket;
|
|
|
|
|
|
|
|
REQUIRE(DNS_ADB_VALID(adb));
|
|
|
|
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
|
|
|
|
|
|
|
bucket = addr->entry->lock_bucket;
|
|
|
|
LOCK(&adb->entrylocks[bucket]);
|
|
|
|
|
|
|
|
addr->entry->avoid_bitstring = when;
|
|
|
|
addr->avoid_bitstring = when;
|
|
|
|
|
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
|
|
|
}
|
|
|
|
|
2000-01-12 03:00:33 +00:00
|
|
|
isc_result_t
|
|
|
|
dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa,
|
2000-02-16 00:16:36 +00:00
|
|
|
dns_adbaddrinfo_t **addrp, isc_stdtime_t now)
|
2000-01-12 03:00:33 +00:00
|
|
|
{
|
|
|
|
int bucket;
|
|
|
|
dns_adbentry_t *entry;
|
|
|
|
dns_adbaddrinfo_t *addr;
|
|
|
|
isc_result_t result;
|
2000-06-01 00:30:58 +00:00
|
|
|
in_port_t port;
|
2000-01-12 03:00:33 +00:00
|
|
|
|
|
|
|
REQUIRE(DNS_ADB_VALID(adb));
|
|
|
|
REQUIRE(addrp != NULL && *addrp == NULL);
|
|
|
|
|
2000-02-16 00:16:36 +00:00
|
|
|
if (now == 0)
|
|
|
|
isc_stdtime_get(&now);
|
|
|
|
|
2000-01-12 03:00:33 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
bucket = DNS_ADB_INVALIDBUCKET;
|
|
|
|
entry = find_entry_and_lock(adb, sa, &bucket);
|
|
|
|
if (adb->entry_sd[bucket]) {
|
|
|
|
result = ISC_R_SHUTTINGDOWN;
|
|
|
|
goto unlock;
|
|
|
|
}
|
|
|
|
if (entry == NULL) {
|
|
|
|
/*
|
|
|
|
* We don't know anything about this address.
|
|
|
|
*/
|
|
|
|
entry = new_adbentry(adb);
|
|
|
|
if (entry == NULL) {
|
|
|
|
result = ISC_R_NOMEMORY;
|
|
|
|
goto unlock;
|
|
|
|
}
|
|
|
|
entry->sockaddr = *sa;
|
|
|
|
link_entry(adb, bucket, entry);
|
|
|
|
DP(50, "findaddrinfo: new entry %p", entry);
|
|
|
|
} else
|
|
|
|
DP(50, "findaddrinfo: found entry %p", entry);
|
|
|
|
|
2000-02-16 00:16:36 +00:00
|
|
|
/*
|
|
|
|
* Check for avoid bitstring timeout.
|
|
|
|
*/
|
|
|
|
if (entry->avoid_bitstring > 0 && entry->avoid_bitstring < now)
|
|
|
|
entry->avoid_bitstring = 0;
|
|
|
|
|
2000-06-01 00:30:58 +00:00
|
|
|
port = isc_sockaddr_getport(sa);
|
|
|
|
addr = new_adbaddrinfo(adb, entry, port);
|
2000-01-12 03:00:33 +00:00
|
|
|
if (addr != NULL) {
|
|
|
|
inc_entry_refcnt(adb, entry, ISC_FALSE);
|
|
|
|
*addrp = addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
unlock:
|
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp) {
|
2000-01-12 03:00:33 +00:00
|
|
|
dns_adbaddrinfo_t *addr;
|
|
|
|
dns_adbentry_t *entry;
|
|
|
|
int bucket;
|
|
|
|
isc_stdtime_t now;
|
2000-01-13 20:42:43 +00:00
|
|
|
isc_boolean_t want_check_exit = ISC_FALSE;
|
2000-01-12 03:00:33 +00:00
|
|
|
|
|
|
|
REQUIRE(DNS_ADB_VALID(adb));
|
|
|
|
REQUIRE(addrp != NULL);
|
|
|
|
addr = *addrp;
|
|
|
|
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
|
|
|
entry = addr->entry;
|
|
|
|
REQUIRE(DNS_ADBENTRY_VALID(entry));
|
|
|
|
|
|
|
|
isc_stdtime_get(&now);
|
|
|
|
|
|
|
|
*addrp = NULL;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-01-12 03:00:33 +00:00
|
|
|
bucket = addr->entry->lock_bucket;
|
|
|
|
LOCK(&adb->entrylocks[bucket]);
|
|
|
|
|
|
|
|
entry->expires = now + 1800; /* XXXRTH */
|
|
|
|
|
|
|
|
dec_entry_refcnt(adb, entry, ISC_FALSE);
|
|
|
|
if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0)
|
2000-01-13 20:42:43 +00:00
|
|
|
want_check_exit = ISC_TRUE;
|
2000-01-12 03:00:33 +00:00
|
|
|
|
|
|
|
UNLOCK(&adb->entrylocks[bucket]);
|
|
|
|
|
|
|
|
addr->entry = NULL;
|
|
|
|
free_adbaddrinfo(adb, &addr);
|
2000-01-13 20:42:43 +00:00
|
|
|
|
|
|
|
if (want_check_exit) {
|
|
|
|
LOCK(&adb->lock);
|
|
|
|
check_exit(adb);
|
|
|
|
UNLOCK(&adb->lock);
|
|
|
|
}
|
2000-01-12 03:00:33 +00:00
|
|
|
}
|