#include <inttypes.h>
#include <stdbool.h>
+#include <isc/atomic.h>
#include <isc/counter.h>
#include <isc/log.h>
#include <isc/platform.h>
/*% Locked by task event serialization. */
dns_name_t domain;
dns_rdataset_t nameservers;
- unsigned int attributes;
+ atomic_uint_fast32_t attributes;
isc_timer_t * timer;
isc_time_t expires;
isc_interval_t interval;
#define FCTX_ATTR_TRIEDFIND 0x0080
#define FCTX_ATTR_TRIEDALT 0x0100
-#define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
- 0)
-#define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
- 0)
-#define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
- 0)
-#define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
- != 0)
-#define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
-#define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
-#define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
-#define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
-#define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
+#define HAVE_ANSWER(f) \
+ ((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_HAVEANSWER) != 0)
+#define GLUING(f) \
+ ((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_GLUING) != 0)
+#define ADDRWAIT(f) \
+ ((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_ADDRWAIT) != 0)
+#define SHUTTINGDOWN(f) \
+ ((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_SHUTTINGDOWN) != 0)
+#define WANTCACHE(f) \
+ ((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_WANTCACHE) != 0)
+#define WANTNCACHE(f) \
+ ((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_WANTNCACHE) != 0)
+#define NEEDEDNS0(f) \
+ ((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_NEEDEDNS0) != 0)
+#define TRIEDFIND(f) \
+ ((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_TRIEDFIND) != 0)
+#define TRIEDALT(f) \
+ ((atomic_load_acquire(&(f)->attributes) & FCTX_ATTR_TRIEDALT) != 0)
+
+#define FCTX_ATTR_SET(f, a) atomic_fetch_or_release(&(f)->attributes, (a))
+#define FCTX_ATTR_CLR(f, a) atomic_fetch_and_release(&(f)->attributes, ~(a))
typedef struct {
dns_adbaddrinfo_t * addrinfo;
count++;
}
- if ((fctx->attributes & FCTX_ATTR_HAVEANSWER) != 0 &&
- fctx->spilled &&
+ if (HAVE_ANSWER(fctx) && fctx->spilled &&
(count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
LOCK(&fctx->res->lock);
if (count == fctx->res->spillat &&
LOCK(&res->buckets[fctx->bucketnum].lock);
fctx->state = fetchstate_done;
- fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+ FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
fctx_sendevents(fctx, result, line);
UNLOCK(&res->buckets[fctx->bucketnum].lock);
* Behave as if the idle timer has expired. For TCP
* this may not actually reflect the latest timer.
*/
- fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+ FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
result = fctx_stopidletimer(fctx);
if (result != ISC_R_SUCCESS)
fctx_done(fctx, result, __LINE__);
* Behave as if the idle timer has expired. For TCP
* connections this may not actually reflect the latest timer.
*/
- fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+ FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
result = fctx_stopidletimer(fctx);
if (result != ISC_R_SUCCESS)
fctx_done(fctx, result, __LINE__);
*/
INSIST(!SHUTTINGDOWN(fctx));
if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) {
- fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+ FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
want_try = true;
} else {
fctx->findfail++;
* know the answer. There's nothing to do but
* fail the fctx.
*/
- fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+ FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
want_done = true;
}
}
* No forwarders. Move to the next find.
*/
fctx->forwarding = false;
- fctx->attributes |= FCTX_ATTR_TRIEDFIND;
+ FCTX_ATTR_SET(fctx, FCTX_ATTR_TRIEDFIND);
find = fctx->find;
if (find == NULL) {
* No nameservers left. Try alternates.
*/
- fctx->attributes |= FCTX_ATTR_TRIEDALT;
+ FCTX_ATTR_SET(fctx, FCTX_ATTR_TRIEDALT);
find = fctx->altfind;
if (find == NULL) {
* Sleep waiting for addresses.
*/
FCTXTRACE("addrwait");
- fctx->attributes |= FCTX_ATTR_ADDRWAIT;
+ FCTX_ATTR_SET(fctx, FCTX_ATTR_ADDRWAIT);
return;
} else if (result != ISC_R_SUCCESS) {
/*
dns_resolver_destroyfetch(&fctx->qminfetch);
+ LOCK(&res->buckets[bucketnum].lock);
if (SHUTTINGDOWN(fctx)) {
- maybe_destroy(fctx, false);
+ maybe_destroy(fctx, true);
+ UNLOCK(&res->buckets[bucketnum].lock);
goto cleanup;
}
+ UNLOCK(&res->buckets[bucketnum].lock);
/*
* Note: fevent->rdataset must be disassociated and
FCTXTRACE("query timed out; no response");
fctx_cancelquery(&query, NULL, NULL, true, false);
}
- fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+ FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
/*
* Our timer has triggered. Reestablish the fctx lifetime
/*
* An fctx that is shutting down is no longer in ADDRWAIT mode.
*/
- fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+ FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
/*
* Cancel all pending validators. Note that this must be done
LOCK(&res->buckets[bucketnum].lock);
- fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
+ FCTX_ATTR_SET(fctx, FCTX_ATTR_SHUTTINGDOWN);
INSIST(fctx->state == fetchstate_active ||
fctx->state == fetchstate_done);
* We haven't started this fctx yet, and we've been requested
* to shut it down.
*/
- fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
+ FCTX_ATTR_SET(fctx, FCTX_ATTR_SHUTTINGDOWN);
fctx->state = fetchstate_done;
fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
/*
fctx->vresult = ISC_R_SUCCESS;
fctx->exitline = -1; /* sentinel */
fctx->logged = false;
- fctx->attributes = 0;
+ atomic_store(&fctx->attributes, 0);
fctx->spilled = false;
fctx->nqueries = 0;
fctx->reason = NULL;
* as opposed to an error. 'node' must be non-NULL.
*/
- fctx->attributes |= FCTX_ATTR_HAVEANSWER;
+ FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
if (hevent != NULL) {
/*
}
if (result == ISC_R_SUCCESS && have_answer) {
- fctx->attributes |= FCTX_ATTR_HAVEANSWER;
+ FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
if (event != NULL) {
/*
* Negative results must be indicated in event->result.
FCTXTRACE("cache_message");
- fctx->attributes &= ~FCTX_ATTR_WANTCACHE;
+ FCTX_ATTR_CLR(fctx, FCTX_ATTR_WANTCACHE);
LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
FCTXTRACE("ncache_message");
- fctx->attributes &= ~FCTX_ATTR_WANTNCACHE;
+ FCTX_ATTR_CLR(fctx, FCTX_ATTR_WANTNCACHE);
res = fctx->res;
need_validation = false;
goto unlock;
if (!HAVE_ANSWER(fctx)) {
- fctx->attributes |= FCTX_ATTR_HAVEANSWER;
+ FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
if (event != NULL) {
event->result = eresult;
if (adbp != NULL && *adbp != NULL) {
/*
* Clear cache bits.
*/
- fctx->attributes &= ~(FCTX_ATTR_WANTNCACHE | FCTX_ATTR_WANTCACHE);
+ FCTX_ATTR_CLR(fctx, (FCTX_ATTR_WANTNCACHE | FCTX_ATTR_WANTCACHE));
/*
* Did we get any answers?
/*
* This response is now potentially cacheable.
*/
- fctx->attributes |= FCTX_ATTR_WANTCACHE;
+ FCTX_ATTR_SET(fctx, FCTX_ATTR_WANTCACHE);
/*
* Did chaining end before we got the final answer?
}
if (rctx->negative) {
- fctx->attributes |= FCTX_ATTR_WANTNCACHE;
+ FCTX_ATTR_SET(fctx, FCTX_ATTR_WANTNCACHE);
}
return (ISC_R_SUCCESS);
* query domain.
*/
INSIST(rctx->ns_rdataset != NULL);
- fctx->attributes |= FCTX_ATTR_GLUING;
+ FCTX_ATTR_SET(fctx, FCTX_ATTR_GLUING);
(void)dns_rdataset_additionaldata(rctx->ns_rdataset,
check_related, fctx);
#if CHECK_FOR_GLUE_IN_ANSWER
check_answer, fctx);
}
#endif
- fctx->attributes &= ~FCTX_ATTR_GLUING;
+ FCTX_ATTR_CLR(fctx, FCTX_ATTR_GLUING);
/*
* NS rdatasets with 0 TTL cause problems.
return (ISC_R_COMPLETE);
}
- fctx->attributes |= FCTX_ATTR_WANTCACHE;
+ FCTX_ATTR_SET(fctx, FCTX_ATTR_WANTCACHE);
fctx->ns_ttl_ok = false;
log_ns_ttl(fctx, "DELEGATION");
rctx->result = DNS_R_DELEGATION;