mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
- authzone work, probe timer setup.
git-svn-id: file:///svn/unbound/trunk@4378 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
7bf7524d22
commit
bdb6a5501a
7 changed files with 202 additions and 74 deletions
|
|
@ -1672,6 +1672,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
|||
if(worker->thread_num == 0)
|
||||
log_set_time(worker->env.now);
|
||||
worker->env.worker = worker;
|
||||
worker->env.worker_base = worker->base;
|
||||
worker->env.send_query = &worker_send_query;
|
||||
worker->env.alloc = &worker->alloc;
|
||||
worker->env.rnd = worker->rndstate;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
19 October 2017: Wouter
|
||||
- authzone work, probe timer setup.
|
||||
|
||||
18 October 2017: Wouter
|
||||
- lint for recent authzone commit.
|
||||
|
||||
|
|
|
|||
|
|
@ -214,6 +214,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
|||
libworker_delete(w);
|
||||
return NULL;
|
||||
}
|
||||
w->env->worker_base = w->base;
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,6 +250,7 @@ msg_add_rrset_ar(struct auth_zone* z, struct regional* region,
|
|||
|
||||
struct auth_zones* auth_zones_create(void)
|
||||
{
|
||||
/* TODO: create and put in env in worker and libworker */
|
||||
struct auth_zones* az = (struct auth_zones*)calloc(1, sizeof(*az));
|
||||
if(!az) {
|
||||
log_err("out of memory");
|
||||
|
|
@ -1245,8 +1246,62 @@ auth_zones_read_zones(struct auth_zones* az)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** setup all auth zones */
|
||||
int
|
||||
/** Find auth_zone SOA and populate the values in xfr(soa values). */
|
||||
static int
|
||||
xfr_find_soa(struct auth_zone* z, struct auth_xfer* xfr)
|
||||
{
|
||||
struct auth_data* apex;
|
||||
struct auth_rrset* soa;
|
||||
struct packed_rrset_data* d;
|
||||
apex = az_find_name(z, z->name, z->namelen);
|
||||
if(!apex) return 0;
|
||||
soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA);
|
||||
if(!soa || soa->data->count==0)
|
||||
return 0; /* no RRset or no RRs in rrset */
|
||||
if(soa->data->rr_len[0] < 2+4*5) return 0; /* SOA too short */
|
||||
/* SOA record ends with serial, refresh, retry, expiry, minimum,
|
||||
* as 4 byte fields */
|
||||
d = soa->data;
|
||||
xfr->have_zone = 1;
|
||||
xfr->serial = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-20));
|
||||
xfr->retry = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-16));
|
||||
xfr->refresh = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-12));
|
||||
xfr->expiry = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-8));
|
||||
/* soa minimum at d->rr_len[0]-4 */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup auth_xfer zone
|
||||
* This populates the have_zone, soa values, next_probe and so on times.
|
||||
* Doesn't do network traffic yet, sets the timeout.
|
||||
* @param z: locked by caller, and modified for setup
|
||||
* @param x: locked by caller, and modified, timers and timeouts.
|
||||
* @param env: module env with time.
|
||||
* @return false on failure.
|
||||
*/
|
||||
static int
|
||||
auth_xfer_setup(struct auth_zone* z, struct auth_xfer* x, struct module_env* env)
|
||||
{
|
||||
if(!z || !x) return 1;
|
||||
if(!xfr_find_soa(z, x)) {
|
||||
return 1;
|
||||
}
|
||||
/* nextprobe setup */
|
||||
x->task_nextprobe->next_probe = 0;
|
||||
if(x->have_zone)
|
||||
x->task_nextprobe->lease_time = *env->now;
|
||||
/* nothing for probe and transfer tasks */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup all zones
|
||||
* @param az: auth zones structure
|
||||
* @param env: module env with time.
|
||||
* @return false on failure.
|
||||
*/
|
||||
static int
|
||||
auth_zones_setup_zones(struct auth_zones* az, struct module_env* env)
|
||||
{
|
||||
struct auth_zone* z;
|
||||
|
|
@ -1334,7 +1389,8 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg)
|
||||
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
|
||||
int setup, struct module_env* env)
|
||||
{
|
||||
struct config_auth* p;
|
||||
for(p = cfg->auths; p; p = p->next) {
|
||||
|
|
@ -1349,6 +1405,10 @@ int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg)
|
|||
}
|
||||
if(!auth_zones_read_zones(az))
|
||||
return 0;
|
||||
if(setup) {
|
||||
if(!auth_zones_setup_zones(az, env))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -2635,6 +2695,34 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** set a zone expired */
|
||||
static void
|
||||
auth_xfer_set_expired(struct auth_xfer* xfr, struct module_env* env,
|
||||
int expired)
|
||||
{
|
||||
struct auth_zone* z;
|
||||
|
||||
/* expire xfr */
|
||||
lock_basic_lock(&xfr->lock);
|
||||
xfr->zone_expired = expired;
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
|
||||
/* find auth_zone */
|
||||
lock_rw_rdlock(&env->auth_zones->lock);
|
||||
z = auth_zone_find(env->auth_zones, xfr->name, xfr->namelen,
|
||||
xfr->dclass);
|
||||
if(!z) {
|
||||
lock_rw_unlock(&env->auth_zones->lock);
|
||||
return;
|
||||
}
|
||||
lock_rw_wrlock(&z->lock);
|
||||
lock_rw_unlock(&env->auth_zones->lock);
|
||||
|
||||
/* expire auth_zone */
|
||||
z->zone_expired = expired;
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
|
||||
/** the current transfer has finished, apply the results.
|
||||
* set timer for future probe. See if zone is expired now. */
|
||||
void
|
||||
|
|
@ -2663,37 +2751,99 @@ xfr_master_start(struct auth_xfer* xfr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** Find auth_zone SOA and populate the values in xfr(soa values). */
|
||||
static int
|
||||
xfr_find_soa(struct auth_zone* z, struct auth_xfer* xfr)
|
||||
/** xfer nextprobe timeout callback */
|
||||
void auth_xfer_timer(void* arg)
|
||||
{
|
||||
struct auth_data* apex;
|
||||
struct auth_rrset* soa;
|
||||
struct packed_rrset_data* d;
|
||||
apex = az_find_name(z, z->name, z->namelen);
|
||||
if(!apex) return 0;
|
||||
soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA);
|
||||
if(!soa || soa->data->count==0)
|
||||
return 0; /* no RRset or no RRs in rrset */
|
||||
if(soa->data->rr_len[0] < 2+4*5) return 0; /* SOA too short */
|
||||
/* SOA record ends with serial, refresh, retry, expiry, minimum,
|
||||
* as 4 byte fields */
|
||||
d = soa->data;
|
||||
xfr->have_zone = 1;
|
||||
xfr->serial = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-20));
|
||||
xfr->retry = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-16));
|
||||
xfr->refresh = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-12));
|
||||
xfr->expiry = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-8));
|
||||
/* soa minimum at d->rr_len[0]-4 */
|
||||
return 1;
|
||||
struct auth_xfer* xfr = (struct auth_xfer*)arg;
|
||||
log_assert(xfr->task_nextprobe);
|
||||
|
||||
/* see if zone has expired, and if so, also set auth_zone expired */
|
||||
if(xfr->have_zone && !xfr->zone_expired &&
|
||||
*(xfr->task_nextprobe->env->now) >= xfr->task_nextprobe->lease_time
|
||||
+ xfr->expiry) {
|
||||
auth_xfer_set_expired(xfr, xfr->task_nextprobe->env, 1);
|
||||
}
|
||||
|
||||
/** determine next timeout for auth_xfer. Also (re)sets timer. */
|
||||
void
|
||||
xfr_set_timeout(struct auth_xfer* xfr)
|
||||
{
|
||||
(void)xfr;
|
||||
/* see if we need to start a probe (or maybe it is already in
|
||||
* progress (due to notify)) */
|
||||
/* TODO */
|
||||
|
||||
/* if we don't end up resetting the timer, delete it, because
|
||||
* the next worker to pick this up does not have the same
|
||||
* event base */
|
||||
comm_timer_delete(xfr->task_nextprobe->timer);
|
||||
xfr->task_nextprobe->timer = NULL;
|
||||
xfr->task_nextprobe->next_probe = 0;
|
||||
/* we don't own this item anymore */
|
||||
xfr->task_nextprobe->worker = NULL;
|
||||
xfr->task_nextprobe->env = NULL;
|
||||
}
|
||||
|
||||
/** for task_nextprobe.
|
||||
* determine next timeout for auth_xfer. Also (re)sets timer.
|
||||
* @param xfr: task structure
|
||||
* @param env: module environment, with worker and time.
|
||||
* @param failure: set true if timer should be set for failure retry.
|
||||
*/
|
||||
static void
|
||||
xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
|
||||
int failure)
|
||||
{
|
||||
struct timeval tv;
|
||||
log_assert(xfr->task_nextprobe != NULL);
|
||||
log_assert(xfr->task_nextprobe->worker == NULL ||
|
||||
xfr->task_nextprobe->worker == env->worker);
|
||||
/* normally, nextprobe = startoflease + refresh,
|
||||
* but if expiry is sooner, use that one.
|
||||
* after a failure, use the retry timer instead. */
|
||||
xfr->task_nextprobe->next_probe = *env->now;
|
||||
if(xfr->task_nextprobe->lease_time)
|
||||
xfr->task_nextprobe->next_probe =
|
||||
xfr->task_nextprobe->lease_time;
|
||||
if(xfr->have_zone) {
|
||||
time_t wait = xfr->refresh;
|
||||
if(failure) wait = xfr->retry;
|
||||
if(xfr->expiry < wait)
|
||||
xfr->task_nextprobe->next_probe += xfr->expiry;
|
||||
else xfr->task_nextprobe->next_probe += wait;
|
||||
}
|
||||
|
||||
if(!xfr->task_nextprobe->timer) {
|
||||
xfr->task_nextprobe->timer = comm_timer_create(
|
||||
env->worker_base, auth_xfer_timer, xfr);
|
||||
if(!xfr->task_nextprobe->timer) {
|
||||
/* failed to malloc memory. likely zone transfer
|
||||
* also fails for that. skip the timeout */
|
||||
char zname[255+1];
|
||||
dname_str(xfr->name, zname);
|
||||
log_err("cannot allocate timer, no refresh for %s",
|
||||
zname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
xfr->task_nextprobe->worker = env->worker;
|
||||
xfr->task_nextprobe->env = env;
|
||||
if(*(xfr->task_nextprobe->env->now) <= xfr->task_nextprobe->next_probe)
|
||||
tv.tv_sec = xfr->task_nextprobe->next_probe -
|
||||
*(xfr->task_nextprobe->env->now);
|
||||
else tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
comm_timer_set(xfr->task_nextprobe->timer, &tv);
|
||||
}
|
||||
|
||||
/** initial pick up of worker timeouts, ties events to worker event loop */
|
||||
void
|
||||
auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env)
|
||||
{
|
||||
struct auth_xfer* x;
|
||||
lock_rw_wrlock(&az->lock);
|
||||
RBTREE_FOR(x, struct auth_xfer*, &az->xtree) {
|
||||
lock_basic_lock(&x->lock);
|
||||
if(x->task_nextprobe && x->task_nextprobe->worker == NULL)
|
||||
xfr_set_timeout(x, env, 0);
|
||||
lock_basic_unlock(&x->lock);
|
||||
}
|
||||
lock_rw_unlock(&az->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2723,7 +2873,6 @@ auth_xfer_new(struct auth_zone* z)
|
|||
free(xfr);
|
||||
return NULL;
|
||||
}
|
||||
xfr->task_nextprobe->workernum = -1;
|
||||
xfr->task_probe = (struct auth_probe*)calloc(1,
|
||||
sizeof(struct auth_probe));
|
||||
if(!xfr->task_probe) {
|
||||
|
|
@ -2755,26 +2904,6 @@ auth_xfer_new(struct auth_zone* z)
|
|||
return xfr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup auth_xfer zone
|
||||
* This populates the have_zone, soa values, next_probe and so on times.
|
||||
* Doesn't do network traffic yet, sets the timeout.
|
||||
*/
|
||||
int
|
||||
auth_xfer_setup(struct auth_zone* z, struct auth_xfer* x, struct module_env* env)
|
||||
{
|
||||
if(!z || !x) return 1;
|
||||
if(!xfr_find_soa(z, x)) {
|
||||
return 1;
|
||||
}
|
||||
/* nextprobe setup */
|
||||
x->task_nextprobe->next_probe = 0;
|
||||
if(x->have_zone)
|
||||
x->task_nextprobe->lease_time = *env->now;
|
||||
/* nothing for probe and transfer tasks */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Create auth_xfer structure.
|
||||
* This populates the have_zone, soa values, next_probe and so on times.
|
||||
* and sets the timeout, if a zone transfer is needed a short timeout is set.
|
||||
|
|
|
|||
|
|
@ -247,10 +247,10 @@ struct auth_xfer {
|
|||
* if unowned.
|
||||
*/
|
||||
struct auth_nextprobe {
|
||||
/** worker num (or -1 unowned) that is performing this task */
|
||||
int workernum;
|
||||
/* Worker pointer. Used by the worker during callbacks. */
|
||||
/* Worker pointer. NULL means unowned. */
|
||||
struct worker* worker;
|
||||
/* module env for this task */
|
||||
struct module_env* env;
|
||||
|
||||
/** Timeout for next probe (for SOA) */
|
||||
time_t next_probe;
|
||||
|
|
@ -372,8 +372,14 @@ struct auth_zones* auth_zones_create(void);
|
|||
|
||||
/**
|
||||
* Apply configuration to auth zones. Reads zonefiles.
|
||||
* @param az: auth zones structure
|
||||
* @param cfg: config to apply.
|
||||
* @param setup: if true, also sets up values in the auth zones structure
|
||||
* @parm env: for setup, with current time.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg);
|
||||
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
|
||||
int setup, struct module_env* env);
|
||||
|
||||
/**
|
||||
* Delete auth zones structure
|
||||
|
|
@ -482,22 +488,4 @@ struct auth_xfer* auth_xfer_create(struct auth_zones* az, struct auth_zone* z);
|
|||
*/
|
||||
int xfer_set_masters(struct auth_master** list, struct config_auth* c);
|
||||
|
||||
/**
|
||||
* Setup auth_xfer zone. Populates timeouts.
|
||||
* @param z: locked by caller, and modified for setup
|
||||
* @param x: locked by caller, and modified, timers and timeouts.
|
||||
* @param env: module env with time.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int auth_xfer_setup(struct auth_zone* z, struct auth_xfer* xfr,
|
||||
struct module_env* env);
|
||||
|
||||
/**
|
||||
* Setup all zones
|
||||
* @param az: auth zones structure
|
||||
* @param env: module env with time.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int auth_zones_setup_zones(struct auth_zones* az, struct module_env* env);
|
||||
|
||||
#endif /* SERVICES_AUTHZONE_H */
|
||||
|
|
|
|||
|
|
@ -579,7 +579,7 @@ static void
|
|||
check_auth(struct config_file* cfg)
|
||||
{
|
||||
struct auth_zones* az = auth_zones_create();
|
||||
if(!az || !auth_zones_apply_cfg(az, cfg)) {
|
||||
if(!az || !auth_zones_apply_cfg(az, cfg, 0, NULL)) {
|
||||
fatal_exit("Could not setup authority zones");
|
||||
}
|
||||
auth_zones_delete(az);
|
||||
|
|
|
|||
|
|
@ -166,6 +166,8 @@ struct query_info;
|
|||
struct edns_data;
|
||||
struct regional;
|
||||
struct worker;
|
||||
struct comm_base;
|
||||
struct auth_zones;
|
||||
struct module_qstate;
|
||||
struct ub_randstate;
|
||||
struct mesh_area;
|
||||
|
|
@ -445,6 +447,8 @@ struct module_env {
|
|||
struct sldns_buffer* scratch_buffer;
|
||||
/** internal data for daemon - worker thread. */
|
||||
struct worker* worker;
|
||||
/** the worker event base */
|
||||
struct comm_base* worker_base;
|
||||
/** mesh area with query state dependencies */
|
||||
struct mesh_area* mesh;
|
||||
/** allocation service */
|
||||
|
|
@ -468,6 +472,8 @@ struct module_env {
|
|||
struct val_neg_cache* neg_cache;
|
||||
/** the 5011-probe timer (if any) */
|
||||
struct comm_timer* probe_timer;
|
||||
/** auth zones */
|
||||
struct auth_zones* auth_zones;
|
||||
/** Mapping of forwarding zones to targets.
|
||||
* iterator forwarder information. per-thread, created by worker */
|
||||
struct iter_forwards* fwds;
|
||||
|
|
|
|||
Loading…
Reference in a new issue