diff options
author | Grigorii Demidov <grigorii.demidov@nic.cz> | 2018-03-06 16:49:00 +0100 |
---|---|---|
committer | Petr Špaček <petr.spacek@nic.cz> | 2018-04-18 17:08:28 +0200 |
commit | 931b8be2537b70088e34587b1d6975544c51c24b (patch) | |
tree | d549988392d692ab27d814e2b0483d77f885eb99 /daemon/zimport.c | |
parent | lib/utils: merge kr_rrkey() and kr_rrkey2() functions (diff) | |
download | knot-resolver-931b8be2537b70088e34587b1d6975544c51c24b.tar.xz knot-resolver-931b8be2537b70088e34587b1d6975544c51c24b.zip |
daemon: cache prefill module
Diffstat (limited to 'daemon/zimport.c')
-rw-r--r-- | daemon/zimport.c | 415 |
1 files changed, 256 insertions, 159 deletions
diff --git a/daemon/zimport.c b/daemon/zimport.c index 1fed48cb..45de989a 100644 --- a/daemon/zimport.c +++ b/daemon/zimport.c @@ -14,6 +14,36 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ +/* Module is intended to import resource records from file into resolver's cache. + * File supposed to be a standard DNS zone file + * which contains text representations of resource records. + * For now only root zone import is supported. + * + * Import process consists of two stages. + * 1) Zone file parsing. + * 2) Import of parsed entries into the cache. + * + * These stages are implemented as two separate functions + * (zi_zone_import and zi_zone_process) which runs sequentially with the + * pause between them. This is done because resolver is a single-threaded + * application, so it can't process user's requests during the whole import + * process. Separation into two stages allows to reduce the + * continuous time interval when resolver can't serve user requests. + * Since root zone isn't large it is imported as single + * chunk. If it would be considered as necessary, import stage can be + * split into shorter stages. + * + * zi_zone_import() uses libzscanner to parse zone file. + * Parsed records are stored to internal storage from where they are imported to + * cache during the second stage. + * + * zi_zone_process() imports parsed resource records to cache. + * It imports rrset by creating request that will never be sent to upstream. + * After request creation resolver creates pseudo-answer which must contain + * all necessary data for validation. Then resolver process answer as if he had + * been received from network. + */ + #include <stdlib.h> #include <uv.h> #include <ucw/mempool.h> @@ -29,6 +59,8 @@ #define VERBOSE_MSG(qry, fmt...) QRVERBOSE(qry, "zimport", fmt) +/* Pause between parse and import stages, milliseconds. + * See comment in zi_zone_import() */ #define ZONE_IMPORT_PAUSE 100 typedef array_t(knot_rrset_t *) qr_rrsetlist_t; @@ -42,8 +74,8 @@ struct zone_import_ctx { uint64_t start_timestamp; size_t rrset_idx; uv_timer_t timer; - map_t rrset_sorted; - qr_rrsetlist_t rrset_list; + map_t rrset_indexed; + qr_rrsetlist_t rrset_sorted; knot_mm_t pool; zi_callback cb; void *cb_param; @@ -51,8 +83,6 @@ struct zone_import_ctx { typedef struct zone_import_ctx zone_import_ctx_t; -int worker_task_finalize(struct qr_task *task, int state); - static int RRSET_IS_ALREADY_IMPORTED = 1; /** @internal Allocate zone import context. @@ -74,7 +104,7 @@ static void zi_ctx_free(zone_import_ctx_t *z_import) * Flushes memory pool, but doesn't reallocate memory pool buffer. * Doesn't affect timer handle, pointers to callback and callback parameter. * @return 0 if success; -1 if failed. */ -static int zi_reset(struct zone_import_ctx *z_import, size_t rrset_list_size) +static int zi_reset(struct zone_import_ctx *z_import, size_t rrset_sorted_list_size) { mp_flush(z_import->pool.ctx); @@ -82,13 +112,13 @@ static int zi_reset(struct zone_import_ctx *z_import, size_t rrset_list_size) z_import->start_timestamp = 0; z_import->rrset_idx = 0; z_import->pool.alloc = (knot_mm_alloc_t) mp_alloc; - z_import->rrset_sorted = map_make(&z_import->pool); + z_import->rrset_indexed = map_make(&z_import->pool); - array_init(z_import->rrset_list); + array_init(z_import->rrset_sorted); int ret = 0; - if (rrset_list_size) { - ret = array_reserve_mm(z_import->rrset_list, rrset_list_size, + if (rrset_sorted_list_size) { + ret = array_reserve_mm(z_import->rrset_sorted, rrset_sorted_list_size, kr_memreserve, &z_import->pool); } @@ -127,7 +157,7 @@ zone_import_ctx_t *zi_allocate(struct worker_ctx *worker, if (ret < 0) { mp_delete(mp); zi_ctx_free(z_import); - z_import = NULL; + return NULL; } uv_timer_init(z_import->worker->loop, &z_import->timer); z_import->timer.data = z_import; @@ -164,52 +194,144 @@ static inline bool zi_rrset_is_marked_as_imported(knot_rrset_t *rr) return (rr->additional == &RRSET_IS_ALREADY_IMPORTED); } -/** @internal Try to find rrset with required properties amongst parsed rrsets - * and put it to given packet, If rrset found and successfully put, it marked as - * "already imported" to avoid repeated import. +/** @internal Try to find rrset with given requisites amongst parsed rrsets + * and put it to given packet. If there is RRSIG which covers that rrset, it + * will be added as well. If rrset found and successfully put, it marked as + * "already imported" to avoid repeated import. The same is true for RRSIG. * @return -1 if failed * 0 if required record been actually put into the packet * 1 if required record could not be found */ -static int zi_put_supplementary(struct zone_import_ctx *z_import, - knot_pkt_t *pkt, const knot_dname_t *owner, - uint16_t class, uint16_t supp_type) +static int zi_rrset_find_put(struct zone_import_ctx *z_import, + knot_pkt_t *pkt, const knot_dname_t *owner, + uint16_t class, uint16_t type, uint16_t additional) { - assert(supp_type != KNOT_RRTYPE_RRSIG); + if (type != KNOT_RRTYPE_RRSIG) { + /* If required rrset isn't rrsig, these must be the same values */ + additional = type; + } char key[KR_RRKEY_LEN]; - int err = kr_rrkey(key, class, owner, supp_type, supp_type); + int err = kr_rrkey(key, class, owner, type, additional); if (err <= 0) { return -1; } - knot_rrset_t *additional_rr = map_get(&z_import->rrset_sorted, key); - err = kr_rrkey(key, class, owner, KNOT_RRTYPE_RRSIG, supp_type); - if (err <= 0) { + knot_rrset_t *rr = map_get(&z_import->rrset_indexed, key); + if (!rr) { + return 1; + } + err = knot_pkt_put(pkt, 0, rr, 0); + if (err != KNOT_EOK) { return -1; } - knot_rrset_t *rrsig = map_get(&z_import->rrset_sorted, key); - if (additional_rr) { - err = knot_pkt_put(pkt, 0, additional_rr, 0); - if (err != KNOT_EOK) { - return -1; + zi_rrset_mark_as_imported(rr); + + if (type != KNOT_RRTYPE_RRSIG) { + /* Try to find corresponding rrsig */ + err = zi_rrset_find_put(z_import, pkt, owner, + class, KNOT_RRTYPE_RRSIG, type); + if (err < 0) { + return err; } - zi_rrset_mark_as_imported(additional_rr); } - if (rrsig) { - err = knot_pkt_put(pkt, 0, rrsig, 0); - if (err != KNOT_EOK) { - return -1; + + return 0; +} + +/** @internal Try to put given rrset to the given packet. + * If there is RRSIG which covers that rrset, it will be added as well. + * If rrset successfully put in the packet, it marked as + * "already imported" to avoid repeated import. + * The same is true for RRSIG. + * @return -1 if failed + * 0 if required record been actually put into the packet */ +static int zi_rrset_put(struct zone_import_ctx *z_import, knot_pkt_t *pkt, + knot_rrset_t *rr) +{ + assert(rr); + assert(rr->type != KNOT_RRTYPE_RRSIG); + int err = knot_pkt_put(pkt, 0, rr, 0); + if (err != KNOT_EOK) { + return -1; + } + zi_rrset_mark_as_imported(rr); + /* Try to find corresponding RRSIG */ + err = zi_rrset_find_put(z_import, pkt, rr->owner, rr->rclass, + KNOT_RRTYPE_RRSIG, rr->type); + return (err < 0) ? err : 0; +} + +/** @internal Try to put DS & NSEC* for rset->owner to given packet. + * @return -1 if failed; + * 0 if no errors occurred (it doesn't mean + * that records were actually added). */ +static int zi_put_delegation(zone_import_ctx_t *z_import, knot_pkt_t *pkt, + knot_rrset_t *rr) +{ + int err = zi_rrset_find_put(z_import, pkt, rr->owner, + rr->rclass, KNOT_RRTYPE_DS, 0); + if (err == 1) { + /* DS not found, maybe there are NSEC* */ + err = zi_rrset_find_put(z_import, pkt, rr->owner, + rr->rclass, KNOT_RRTYPE_NSEC, 0); + if (err >= 0) { + err = zi_rrset_find_put(z_import, pkt, rr->owner, + rr->rclass, KNOT_RRTYPE_NSEC3, 0); + } + } + return err < 0 ? err : 0; +} + +/** @internal Try to put A & AAAA records for rset->owner to given packet. + * @return -1 if failed; + * 0 if no errors occurred (it doesn't mean + * that records were actually added). */ +static int zi_put_glue(zone_import_ctx_t *z_import, knot_pkt_t *pkt, + knot_rrset_t *rr) +{ + int err = 0; + for (uint16_t i = 0; i < rr->rrs.rr_count; ++i) { + const knot_dname_t *ns_name = knot_ns_name(&rr->rrs, i); + err = zi_rrset_find_put(z_import, pkt, ns_name, + rr->rclass, KNOT_RRTYPE_A, 0); + if (err < 0) { + break; + } + + err = zi_rrset_find_put(z_import, pkt, ns_name, + rr->rclass, KNOT_RRTYPE_AAAA, 0); + if (err < 0) { + break; } - zi_rrset_mark_as_imported(rrsig); } - return additional_rr == NULL ? 1 : 0; + return err < 0 ? err : 0; +} + +/** @internal Create query. */ +static knot_pkt_t *zi_query_create(zone_import_ctx_t *z_import, knot_rrset_t *rr) +{ + knot_mm_t *pool = &z_import->pool; + + uint32_t msgid = kr_rand_uint(0); + + knot_pkt_t *query = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, pool); + if (!query) { + return NULL; + } + + knot_pkt_put_question(query, rr->owner, rr->rclass, rr->type); + knot_pkt_begin(query, KNOT_ANSWER); + knot_wire_set_rd(query->wire); + knot_wire_set_id(query->wire, msgid); + int err = knot_pkt_parse(query, 0); + if (err != KNOT_EOK) { + knot_pkt_free(&query); + return NULL; + } + + return query; } /** @internal Import given rrset to cache. - * The main goal of import procedure is to store parsed records to the cache. - * Resolver imports rrset by creating request that will never be sent to upstream. - * After request creation resolver creates pseudo-answer which must contain - * all necessary data for validation. Then resolver process answer as if he had - * been received from network. * @return -1 if failed; 0 if success */ static int zi_rrset_import(zone_import_ctx_t *z_import, knot_rrset_t *rr) { @@ -217,34 +339,33 @@ static int zi_rrset_import(zone_import_ctx_t *z_import, knot_rrset_t *rr) assert(worker); - knot_mm_t *pool = &z_import->pool; + /* Create "pseudo query" which asks for given rrset. */ + knot_pkt_t *query = zi_query_create(z_import, rr); + if (!query) { + return -1; + } + knot_mm_t *pool = &z_import->pool; uint8_t *dname = rr->owner; uint16_t rrtype = rr->type; uint16_t rrclass = rr->rclass; - struct kr_qflags options; - memset(&options, 0, sizeof(options)); - options.DNSSEC_WANT = true; - options.NO_MINIMIZE = true; - uint32_t msgid = kr_rand_uint(0); - - /* Create query */ - knot_pkt_t *query = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, pool); - if (!query) { - return -1; - } + /* Create "pseudo answer". */ knot_pkt_t *answer = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, pool); if (!answer) { knot_pkt_free(&query); return -1; } + knot_pkt_put_question(answer, dname, rrclass, rrtype); + knot_pkt_begin(answer, KNOT_ANSWER); - knot_pkt_put_question(query, dname, rrclass, rrtype); - knot_pkt_begin(query, KNOT_ANSWER); - knot_wire_set_rd(query->wire); - knot_wire_set_id(query->wire, msgid); + struct kr_qflags options; + memset(&options, 0, sizeof(options)); + options.DNSSEC_WANT = true; + options.NO_MINIMIZE = true; + /* This call creates internal structures which necessary for + * resolving - qr_task & request_ctx. */ struct qr_task *task = worker_resolve_start(worker, query, options); if (!task) { knot_pkt_free(&query); @@ -252,16 +373,20 @@ static int zi_rrset_import(zone_import_ctx_t *z_import, knot_rrset_t *rr) return -1; } + /* Push query to the request resolve plan. + * Actually query will never been sent to upstream. */ struct kr_request *request = worker_task_request(task); struct kr_rplan *rplan = &request->rplan; struct kr_query *qry = kr_rplan_push(rplan, NULL, dname, rrclass, rrtype); - char key[KR_RRKEY_LEN]; - int err = 0; int state = KR_STATE_FAIL; bool origin_is_owner = knot_dname_is_equal(rr->owner, z_import->origin); bool is_referral = (rrtype == KNOT_RRTYPE_NS && !origin_is_owner); + uint32_t msgid = knot_wire_get_id(query->wire); qry->id = msgid; + + /* Prepare zonecut. It must have all the necessary requisites for + * successful validation - matched zone name & keys & trust-anchors. */ kr_zonecut_init(&qry->zone_cut, z_import->origin, pool); qry->zone_cut.key = z_import->key; qry->zone_cut.trust_anchor = z_import->ta; @@ -270,53 +395,26 @@ static int zi_rrset_import(zone_import_ctx_t *z_import, knot_rrset_t *rr) goto cleanup; } - knot_pkt_put_question(answer, dname, rrclass, rrtype); - knot_pkt_begin(answer, KNOT_ANSWER); - + /* Since "pseudo" query asks for NS for subzone, + * "pseudo" answer must simulate referral. */ if (is_referral) { knot_pkt_begin(answer, KNOT_AUTHORITY); } - err = knot_pkt_put(answer, 0, rr, 0); + /* Put target rrset to ANSWER\AUTHORIRY as well as corresponding RRSIG */ + int err = zi_rrset_put(z_import, answer, rr); if (err != 0) { goto cleanup; } - zi_rrset_mark_as_imported(rr); - - err = kr_rrkey(key, rr->rclass, rr->owner, KNOT_RRTYPE_RRSIG, rr->type); - if (err <= 0) { - goto cleanup; - } - knot_rrset_t *rrsig = map_get(&z_import->rrset_sorted, key); - if (rrsig) { - err = knot_pkt_put(answer, 0, rrsig, 0); - if (err != 0) { - goto cleanup; - } - zi_rrset_mark_as_imported(rrsig); - } if (!is_referral) { knot_wire_set_aa(answer->wire); } else { /* Type is KNOT_RRTYPE_NS and owner is not equal to origin. - * It will be "referral" answer, so try to add DS or NSEC* to it. */ - err = zi_put_supplementary(z_import, answer, rr->owner, - rr->rclass, KNOT_RRTYPE_DS); + * It will be "referral" answer and must contain delegation. */ + err = zi_put_delegation(z_import, answer, rr); if (err < 0) { goto cleanup; - } else if (err == 1) { - /* DS not found */ - err = zi_put_supplementary(z_import, answer, rr->owner, - rr->rclass, KNOT_RRTYPE_NSEC); - if (err < 0) { - goto cleanup; - } - err = zi_put_supplementary(z_import, answer, rr->owner, - rr->rclass, KNOT_RRTYPE_NSEC3); - if (err < 0) { - goto cleanup; - } } } @@ -324,24 +422,18 @@ static int zi_rrset_import(zone_import_ctx_t *z_import, knot_rrset_t *rr) if (rrtype == KNOT_RRTYPE_NS) { /* Try to find glue addresses. */ - for (uint16_t i = 0; i < rr->rrs.rr_count; ++i) { - const knot_dname_t *ns_name = knot_ns_name(&rr->rrs, i); - err = zi_put_supplementary(z_import, answer, ns_name, - rr->rclass, KNOT_RRTYPE_A); - if (err < 0) { - goto cleanup; - } - - err = zi_put_supplementary(z_import, answer, ns_name, - rr->rclass, KNOT_RRTYPE_AAAA); - if (err < 0) { - goto cleanup; - } + err = zi_put_glue(z_import, answer, rr); + if (err < 0) { + goto cleanup; } } knot_wire_set_id(answer->wire, msgid); answer->parsed = answer->size; + err = knot_pkt_parse(answer, 0); + if (err != KNOT_EOK) { + goto cleanup; + } /* Importing doesn't imply communication with upstream at all. * "answer" contains pseudo-answer from upstream and must be successfully @@ -362,7 +454,7 @@ static int zi_mapwalk_preprocess(const char *k, void *v, void *baton) { zone_import_ctx_t *z_import = (zone_import_ctx_t *)baton; - int ret = array_push_mm(z_import->rrset_list, v, kr_memreserve, &z_import->pool); + int ret = array_push_mm(z_import->rrset_sorted, v, kr_memreserve, &z_import->pool); return (ret < 0); } @@ -390,26 +482,11 @@ static void zi_zone_process(uv_timer_t* handle) goto finish; } - if (z_import->rrset_list.len <= 0) { + if (z_import->rrset_sorted.len <= 0) { VERBOSE_MSG(NULL, "zone is empty\n"); goto finish; } - /* z_import.rrset_list now contains sorted rrset list. - * Records are sorted by the key returned by kr_rrkey() function. - * Find out if zone is secured. - * Try to find TA for worker->z_import.origin. */ - map_t *trust_anchors = &z_import->worker->engine->resolver.trust_anchors; - knot_rrset_t *rr = kr_ta_get(trust_anchors, z_import->origin); - if (!rr) { - /* For now - fail. - * TODO - query DS and continue after answer had been obtained. */ - kr_log_error("[zimport] TA not found for `%s`, fail\n", zone_name_str); - failed = 1; - goto finish; - } - z_import->ta = rr; - /* TA have been found, zone is secured. * DNSKEY must be somewhere amongst the imported records. Find it. * TODO - For those zones that provenly do not have TA this step must be skipped. */ @@ -421,7 +498,7 @@ static void zi_zone_process(uv_timer_t* handle) goto finish; } - rr = map_get(&z_import->rrset_sorted, key); + knot_rrset_t *rr = map_get(&z_import->rrset_indexed, key); if (!rr) { /* DNSKEY MUST be here. If not found - fail. */ kr_log_error("[zimport] DNSKEY not found for `%s`, fail\n", zone_name_str); @@ -451,8 +528,8 @@ static void zi_zone_process(uv_timer_t* handle) } /* Import all NS records */ - for (size_t i = 0; i < z_import->rrset_list.len; ++i) { - knot_rrset_t *rr = z_import->rrset_list.at[i]; + for (size_t i = 0; i < z_import->rrset_sorted.len; ++i) { + knot_rrset_t *rr = z_import->rrset_sorted.at[i]; if (rr->type != KNOT_RRTYPE_NS) { continue; @@ -470,14 +547,14 @@ static void zi_zone_process(uv_timer_t* handle) qname_str, type_str); ++failed; } - z_import->rrset_list.at[i] = NULL; + z_import->rrset_sorted.at[i] = NULL; } /* NS records have been imported as well as relative DS, NSEC* and glue. * Now import what's left. */ - for (size_t i = 0; i < z_import->rrset_list.len; ++i) { + for (size_t i = 0; i < z_import->rrset_sorted.len; ++i) { - knot_rrset_t *rr = z_import->rrset_list.at[i]; + knot_rrset_t *rr = z_import->rrset_sorted.at[i]; if (rr == NULL) { continue; } @@ -556,31 +633,34 @@ static int zi_record_store(zs_scanner_t *s) kr_log_error("[zscanner] line %lu: error creating rrset\n", s->line_counter); return -1; } - int ret = knot_rrset_add_rdata(new_rr, s->r_data, s->r_data_length, + int res = knot_rrset_add_rdata(new_rr, s->r_data, s->r_data_length, s->r_ttl, &z_import->pool); - if (ret != KNOT_EOK) { + if (res != KNOT_EOK) { kr_log_error("[zscanner] line %lu: error adding rdata to rrset\n", s->line_counter); return -1; } + /* Records in zone file may not be grouped by name and RR type. + * Use map to create search key and + * avoid ineffective searches across all the imported records. */ char key[KR_RRKEY_LEN]; uint16_t additional_key_field = kr_rrset_type_maysig(new_rr); - ret = kr_rrkey(key, new_rr->rclass, new_rr->owner, new_rr->type, + res = kr_rrkey(key, new_rr->rclass, new_rr->owner, new_rr->type, additional_key_field); - if (ret <= 0) { + if (res <= 0) { kr_log_error("[zscanner] line %lu: error constructing rrkey\n", s->line_counter); return -1; } - knot_rrset_t *saved_rr = map_get(&z_import->rrset_sorted, key); + knot_rrset_t *saved_rr = map_get(&z_import->rrset_indexed, key); if (saved_rr) { - ret = knot_rdataset_merge(&saved_rr->rrs, &new_rr->rrs, + res = knot_rdataset_merge(&saved_rr->rrs, &new_rr->rrs, &z_import->pool); } else { - ret = map_set(&z_import->rrset_sorted, key, new_rr); + res = map_set(&z_import->rrset_indexed, key, new_rr); } - if (ret != 0) { + if (res != 0) { kr_log_error("[zscanner] line %lu: error saving parsed rrset\n", s->line_counter); return -1; } @@ -608,14 +688,20 @@ static int zi_state_parsing(zs_scanner_t *s) } break; case ZS_STATE_ERROR: - kr_log_error("[zscanner] line: %lu: error parsing record\n", s->line_counter); + kr_log_error("[zscanner] line: %lu: parse error; code: %i ('%s')\n", + s->line_counter, s->error.code, zs_strerror(s->error.code)); return -1; - break; case ZS_STATE_INCLUDE: + kr_log_error("[zscanner] line: %lu: INCLUDE is not supported\n", + s->line_counter); return -1; - break; - default: + case ZS_STATE_EOF: + case ZS_STATE_STOP: return (s->error.counter == 0) ? 0 : -1; + default: + kr_log_error("[zscanner] line: %lu: unexpected parse state: %i\n", + s->line_counter, s->state); + return -1; } } @@ -626,46 +712,45 @@ int zi_zone_import(struct zone_import_ctx *z_import, const char *zone_file, const char *origin, uint16_t rclass, uint32_t ttl) { - if (z_import->worker == NULL) { - kr_log_error("[zscanner] invalid <z_import> parameter\n"); - return -1; - } + assert (z_import != NULL && "[zimport] empty <z_import> parameter"); + assert (z_import->worker != NULL && "[zimport] invalid <z_import> parameter\n"); + assert (zone_file != NULL && "[zimport] empty <zone_file> parameter\n"); zs_scanner_t *s = malloc(sizeof(zs_scanner_t)); if (s == NULL) { - kr_log_error("[zscanner] error creating instance of zone scanner\n"); + kr_log_error("[zscanner] error creating instance of zone scanner (malloc() fails)\n"); return -1; } - if (zs_init(s, origin, rclass, ttl) != 0) { + /* zs_init(), zs_set_input_file(), zs_set_processing() returns -1 in case of error, + * so don't print error code as it meaningless. */ + int res = zs_init(s, origin, rclass, ttl); + if (res != 0) { free(s); - kr_log_error("[zscanner] error initializing zone scanner instance\n"); + kr_log_error("[zscanner] error initializing zone scanner instance, error: %i (%s)\n", + s->error.code, zs_strerror(s->error.code)); return -1; } - if (zs_set_input_file(s, zone_file) != 0) { + res = zs_set_input_file(s, zone_file); + if (res != 0) { zs_deinit(s); free(s); - kr_log_error("[zscanner] error opening zone file `%s`\n", zone_file); + kr_log_error("[zscanner] error opening zone file `%s`, error: %i (%s)\n", + zone_file, s->error.code, zs_strerror(s->error.code)); return -1; } - /* Don't set callbacks as we don't use automatic parsing. - * Store pointer to zone import context. */ + /* Don't set processing and error callbacks as we don't use automatic parsing. + * Parsing as well error processing will be performed in zi_state_parsing(). + * Store pointer to zone import context for further use. */ if (zs_set_processing(s, NULL, NULL, (void *)z_import) != 0) { zs_deinit(s); free(s); - kr_log_error("[zscanner] error opening zone file `%s`\n", zone_file); + kr_log_error("[zscanner] zs_set_input_file() fails\n"); return -1; } - /* To reduce time spent in the callback, import is split - * into two stages. In the first stage zone file is parsed and prepared - * for importing to cache. In the second stage parsed zone is imported - * into the cache. Since root zone isn't large it is imported as single - * chunk. If it would be considered as necessary, second stage can be - * split into shorter stages. */ - uint64_t elapsed = 0; int ret = zi_reset(z_import, 4096); if (ret == 0) { @@ -674,6 +759,19 @@ int zi_zone_import(struct zone_import_ctx *z_import, VERBOSE_MSG(NULL, "[zscanner] started; zone file `%s`\n", zone_file); ret = zi_state_parsing(s); + /* Try to find TA for worker->z_import.origin. */ + map_t *trust_anchors = &z_import->worker->engine->resolver.trust_anchors; + knot_rrset_t *rr = kr_ta_get(trust_anchors, z_import->origin); + if (rr) { + z_import->ta = rr; + } else { + /* For now - fail. + * TODO - query DS and continue after answer had been obtained. */ + char zone_name_str[KNOT_DNAME_MAXLEN]; + knot_dname_to_str(zone_name_str, z_import->origin, sizeof(zone_name_str)); + kr_log_error("[zimport] no TA found for `%s`, fail\n", zone_name_str); + ret = 1; + } elapsed = kr_now() - z_import->start_timestamp; elapsed = elapsed > UINT_MAX ? UINT_MAX : elapsed; } @@ -688,10 +786,9 @@ int zi_zone_import(struct zone_import_ctx *z_import, VERBOSE_MSG(NULL, "[zscanner] finished in %lu ms; zone file `%s`\n", elapsed, zone_file); + map_walk(&z_import->rrset_indexed, zi_mapwalk_preprocess, z_import); - map_walk(&z_import->rrset_sorted, zi_mapwalk_preprocess, z_import); - - /* Start import */ + /* Zone have been parsed already, so start the import. */ uv_timer_start(&z_import->timer, zi_zone_process, ZONE_IMPORT_PAUSE, ZONE_IMPORT_PAUSE); |