]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- authzone work, probe timer setup.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 19 Oct 2017 09:03:36 +0000 (09:03 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 19 Oct 2017 09:03:36 +0000 (09:03 +0000)
git-svn-id: file:///svn/unbound/trunk@4378 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/worker.c
doc/Changelog
libunbound/libworker.c
services/authzone.c
services/authzone.h
smallapp/unbound-checkconf.c
util/module.h

index ac7053abddf30c98f9d57353ee23f951e151a1d1..cffaecc43ca8c3c8481bcc50f0f667887444d9bc 100644 (file)
@@ -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;
index 5f57f656e6bbe98fcdc4db7c362c232fe34dadf2..73e7ce27a4eace61a35ec0ec9883884cace518bf 100644 (file)
@@ -1,3 +1,6 @@
+19 October 2017: Wouter 
+       - authzone work, probe timer setup.
+
 18 October 2017: Wouter 
        - lint for recent authzone commit.
 
index 4067ef4d2853234a1e4671f0708228509ddb6f70..301a3e8565ecb18bb12f48063b86c9ea924eb4b3 100644 (file)
@@ -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);
        }
index 21a8ee704cd60672e5fdbd022cef5ac770cffb3a..26541a28aaafb20e667c82e6c58391c59bcbed44 100644 (file)
@@ -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);
+       }
+
+       /* 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);
 }
 
-/** determine next timeout for auth_xfer. Also (re)sets timer. */
+/** initial pick up of worker timeouts, ties events to worker event loop */
 void
-xfr_set_timeout(struct auth_xfer* xfr)
+auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env)
 {
-       (void)xfr;
-       /* TODO */
+       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.
index b22810329120e8fb4cf8ecd1997f8ea45315ee1c..69cfd78efaa819fd3c67cb91d18092156abddd10 100644 (file)
@@ -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 */
index 2b6f7faef2ef016bf95a75a9462e275f03030687..2b84aad12aba34837d6fa6da9792587506f1709a 100644 (file)
@@ -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);
index 415865c3d8b68064065d3c676a48874380411efb..90894d5ec2d6716e76c55e717402314f9de715ff 100644 (file)
@@ -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;