mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-28 21:17:54 +00:00
a6 checkpoint
This commit is contained in:
parent
5862cce82b
commit
fe14eafefa
253
lib/dns/adb.c
253
lib/dns/adb.c
@ -40,6 +40,7 @@
|
||||
#include <isc/random.h>
|
||||
#include <isc/timer.h>
|
||||
|
||||
#include <dns/a6.h>
|
||||
#include <dns/adb.h>
|
||||
#include <dns/db.h>
|
||||
#include <dns/events.h>
|
||||
@ -66,6 +67,8 @@
|
||||
#define DNS_ADBENTRY_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
|
||||
#define DNS_ADBFETCH_MAGIC 0x61644634 /* adF4. */
|
||||
#define DNS_ADBFETCH_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
|
||||
#define DNS_ADBFETCH6_MAGIC 0x61644636 /* adF6. */
|
||||
#define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
|
||||
|
||||
/*
|
||||
* Lengths of lists needs to be small primes.
|
||||
@ -87,6 +90,7 @@ typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
|
||||
typedef struct dns_adbzoneinfo dns_adbzoneinfo_t;
|
||||
typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
|
||||
typedef struct dns_adbfetch dns_adbfetch_t;
|
||||
typedef struct dns_adbfetch6 dns_adbfetch6_t;
|
||||
|
||||
struct dns_adb {
|
||||
unsigned int magic;
|
||||
@ -114,6 +118,7 @@ struct dns_adb {
|
||||
isc_mempool_t *ahmp; /* dns_adbfind_t */
|
||||
isc_mempool_t *aimp; /* dns_adbaddrinfo_t */
|
||||
isc_mempool_t *afmp; /* dns_adbfetch_t */
|
||||
isc_mempool_t *af6mp; /* dns_adbfetch6_t */
|
||||
|
||||
isc_random_t rand;
|
||||
|
||||
@ -149,11 +154,12 @@ struct dns_adbname {
|
||||
int lock_bucket;
|
||||
isc_stdtime_t expire_v4;
|
||||
isc_stdtime_t expire_v6;
|
||||
unsigned int chains;
|
||||
dns_adbnamehooklist_t v4;
|
||||
dns_adbnamehooklist_t v6;
|
||||
dns_adbfetch_t *fetch_a;
|
||||
dns_adbfetch_t *fetch_aaaa;
|
||||
ISC_LIST(dns_adbfetch_t) fetches_a6;
|
||||
ISC_LIST(dns_adbfetch6_t) fetches_a6;
|
||||
ISC_LIST(dns_adbfind_t) finds;
|
||||
ISC_LINK(dns_adbname_t) plink;
|
||||
};
|
||||
@ -166,6 +172,16 @@ struct dns_adbfetch {
|
||||
dns_rdataset_t rdataset;
|
||||
};
|
||||
|
||||
struct dns_adbfetch6 {
|
||||
unsigned int magic;
|
||||
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;
|
||||
};
|
||||
|
||||
/*
|
||||
* dns_adbnamehook_t
|
||||
*
|
||||
@ -234,6 +250,8 @@ static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *,
|
||||
|
||||
static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *);
|
||||
static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
|
||||
static inline dns_adbfetch6_t *new_adbfetch6(dns_adb_t *, dns_a6context_t *);
|
||||
static inline void free_adbfetch6(dns_adb_t *, dns_adbfetch6_t **);
|
||||
static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
|
||||
int *);
|
||||
static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
|
||||
@ -268,6 +286,7 @@ static void shutdown_names(dns_adb_t *);
|
||||
static inline void link_name(dns_adb_t *, int, dns_adbname_t *);
|
||||
static inline void unlink_name(dns_adb_t *, dns_adbname_t *);
|
||||
static void kill_name(dns_adbname_t **, isc_eventtype_t ev);
|
||||
static void fetch_callback_a6(isc_task_t *task, isc_event_t *ev);
|
||||
|
||||
#define FIND_EVENT_SENT 0x00000001
|
||||
#define FIND_EVENT_FREED 0x00000002
|
||||
@ -829,6 +848,7 @@ new_adbname(dns_adb_t *adb, dns_name_t *dnsname)
|
||||
name->dead = ISC_FALSE;
|
||||
name->expire_v4 = INT_MAX;
|
||||
name->expire_v6 = INT_MAX;
|
||||
name->chains = 0;
|
||||
name->lock_bucket = DNS_ADB_INVALIDBUCKET;
|
||||
ISC_LIST_INIT(name->v4);
|
||||
ISC_LIST_INIT(name->v6);
|
||||
@ -1087,6 +1107,129 @@ free_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch)
|
||||
isc_mempool_put(adb->afmp, f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Caller must be holding the name lock.
|
||||
*/
|
||||
static isc_result_t
|
||||
a6find(void *arg, dns_name_t *a6name, dns_rdatatype_t type,
|
||||
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
|
||||
dns_adbname_t *name;
|
||||
dns_adb_t *adb;
|
||||
|
||||
name = arg;
|
||||
INSIST(DNS_ADBNAME_VALID(name));
|
||||
adb = name->adb;
|
||||
INSIST(DNS_ADB_VALID(adb));
|
||||
|
||||
/*
|
||||
* XXXRTH Cache 'now' in the name so we don't have to call
|
||||
* isc_stdtime_get() on every dns_view_find().
|
||||
*/
|
||||
|
||||
return (dns_view_find(adb->view, a6name, type, 0, 0, ISC_FALSE,
|
||||
rdataset, sigrdataset));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
name = a6ctx->arg;
|
||||
INSIST(DNS_ADBNAME_VALID(name));
|
||||
adb = name->adb;
|
||||
INSIST(DNS_ADB_VALID(adb));
|
||||
|
||||
fetch = new_adbfetch6(adb, a6ctx);
|
||||
if (fetch == NULL) {
|
||||
name->partial_result |= DNS_ADBFIND_INET6;
|
||||
return;
|
||||
}
|
||||
result = dns_resolver_createfetch(adb->view->resolver, a6name,
|
||||
dns_rdatatype_a6, NULL, NULL, NULL,
|
||||
0, adb->task, fetch_callback_a6,
|
||||
name, &fetch->rdataset, NULL,
|
||||
&fetch->fetch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
free_adbfetch6(adb, &fetch);
|
||||
name->partial_result |= DNS_ADBFIND_INET6;
|
||||
return;
|
||||
}
|
||||
|
||||
name->chains = a6ctx->chains;
|
||||
ISC_LIST_APPEND(name->fetches_a6, fetch, plink);
|
||||
}
|
||||
|
||||
static inline dns_adbfetch6_t *
|
||||
new_adbfetch6(dns_adb_t *adb, dns_a6context_t *a6ctx)
|
||||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
if (a6ctx != NULL)
|
||||
dns_a6_copy(a6ctx, &f->a6ctx);
|
||||
else
|
||||
dns_a6_init(&f->a6ctx, a6find, NULL, /* import */ NULL,
|
||||
a6missing, f);
|
||||
|
||||
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
|
||||
free_adbfetch6(dns_adb_t *adb, dns_adbfetch6_t **fetch)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static inline void
|
||||
free_adbfind(dns_adb_t *adb, dns_adbfind_t **findp)
|
||||
{
|
||||
@ -1586,6 +1729,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
|
||||
MPINIT(dns_adbfind_t, adb->ahmp, ISC_TRUE, "adbfind");
|
||||
MPINIT(dns_adbaddrinfo_t, adb->aimp, ISC_TRUE, "adbaddrinfo");
|
||||
MPINIT(dns_adbfetch_t, adb->afmp, ISC_TRUE, "adbfetch");
|
||||
MPINIT(dns_adbfetch6_t, adb->af6mp, ISC_TRUE, "adbfetch6");
|
||||
|
||||
#undef MPINIT
|
||||
|
||||
@ -2529,6 +2673,7 @@ fetch_callback_v4(isc_task_t *task, isc_event_t *ev)
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_callback_aaaa(isc_task_t *task, isc_event_t *ev)
|
||||
{
|
||||
@ -2624,6 +2769,112 @@ fetch_callback_aaaa(isc_task_t *task, isc_event_t *ev)
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_callback_a6(isc_task_t *task, isc_event_t *ev)
|
||||
{
|
||||
dns_fetchevent_t *dev;
|
||||
dns_adbname_t *name;
|
||||
dns_adb_t *adb;
|
||||
dns_adbfetch6_t *fetch;
|
||||
int bucket;
|
||||
isc_eventtype_t ev_status;
|
||||
isc_stdtime_t now;
|
||||
isc_result_t result;
|
||||
|
||||
(void)task;
|
||||
|
||||
INSIST(ev->type == DNS_EVENT_FETCHDONE);
|
||||
dev = (dns_fetchevent_t *)ev;
|
||||
name = ev->arg;
|
||||
INSIST(DNS_ADBNAME_VALID(name));
|
||||
adb = name->adb;
|
||||
INSIST(DNS_ADB_VALID(adb));
|
||||
|
||||
bucket = name->lock_bucket;
|
||||
LOCK(&adb->namelocks[bucket]);
|
||||
|
||||
/* XXX INSIST(needs_poke == 0) */
|
||||
|
||||
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);
|
||||
|
||||
dns_resolver_destroyfetch(adb->view->resolver, &fetch->fetch);
|
||||
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.
|
||||
*/
|
||||
if (name->dead) {
|
||||
isc_boolean_t decr_adbrefcnt;
|
||||
|
||||
free_adbfetch6(adb, &fetch);
|
||||
isc_event_free(&ev);
|
||||
|
||||
kill_name(&name, DNS_EVENT_ADBCANCELED);
|
||||
|
||||
decr_adbrefcnt = ISC_FALSE;
|
||||
if (adb->name_sd[bucket] && (adb->name_refcnt[bucket] == 0))
|
||||
decr_adbrefcnt = ISC_TRUE;
|
||||
|
||||
UNLOCK(&adb->namelocks[bucket]);
|
||||
|
||||
if (decr_adbrefcnt)
|
||||
dec_adb_irefcnt(adb, ISC_TRUE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Did we get back junk? If so, and there are no more fetches
|
||||
* sitting out there, tell all the finds about it.
|
||||
*/
|
||||
if (dev->result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* We got something potentially useful. Run the A6 chain
|
||||
* follower on this A6 rdataset.
|
||||
*/
|
||||
|
||||
fetch->a6ctx.chains = name->chains;
|
||||
(void)dns_a6_foreach(&fetch->a6ctx, dev->rdataset);
|
||||
|
||||
out:
|
||||
free_adbfetch6(adb, &fetch);
|
||||
isc_event_free(&ev);
|
||||
|
||||
#ifdef notyet
|
||||
if (needs_poke)
|
||||
clean_finds_at_name(name, DNS_EVENT_ADBMOREADDRESSES,
|
||||
DNS_ADBFIND_INET6);
|
||||
else if (ISC_LIST_EMPTY(name->fetches_a6)) {
|
||||
clean_finds_at_name(name, DNS_EVENT_ADBNOMOREADDRESSES,
|
||||
DNS_ADBFIND_INET6);
|
||||
name->query_pending &= ~DNS_ADBFIND_INET6;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* XXX clear needs poke */
|
||||
|
||||
UNLOCK(&adb->namelocks[bucket]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
fetch_name_v4(dns_adbname_t *adbname, isc_stdtime_t now)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user