diff --git a/lib/resolve.c b/lib/resolve.c index 1408d3289657f7c22af77bfd3c9936e4a99a826c..bb365ff75201a2f94e0eaf65dd452fd6d77fb7f8 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -10,61 +10,90 @@ #include <libknot/rrset-dump.h> #include <common/print.h> +#ifndef NDEBUG +static void print_result(struct kr_result *result) +{ + char *qnamestr = knot_dname_to_str(knot_pkt_qname(result->ans)); + char *cnamestr = knot_dname_to_str(result->cname); + printf("resolution of %s -> %s\n", qnamestr, cnamestr); + free(qnamestr); free(cnamestr); + + printf("rcode = %d (%u RR)\n", knot_wire_get_rcode(result->ans->wire), result->ans->rrset_count); + char strbuf[4096] = {0}; + int buflen = sizeof(strbuf); + knot_dump_style_t style = {0}; + for (unsigned i = 0; i < result->ans->rrset_count; ++i) { + int r = knot_rrset_txt_dump(&result->ans->rr[i], strbuf, buflen, &style); + if (r > 0) buflen -= r; + } + + printf("%s", strbuf); + printf("queries: %u\n", result->nr_queries); + printf("rtt %.02f msecs\n", time_diff(&result->t_start, &result->t_end)); +} + +#define print_step(s...) \ +do { \ + char *_qstr = knot_dname_to_str(ctx->sname); \ + char _astr[SOCKADDR_STRLEN]; \ + sockaddr_tostr(&kr_slist_top(ctx)->addr, _astr, sizeof(_astr)); \ + char *_soastr = knot_dname_to_str(kr_slist_top(ctx)->name); \ + printf("[%s] at %s (soa %s) ", _qstr, _astr, _soastr); \ + printf(s); \ + printf("\n"); \ +} while(0) +#else +static void print_result(struct kr_result *result) {} +#define print_step +#endif + int kr_resolve(struct kr_context* ctx, struct kr_result* result, - const knot_dname_t *qname, uint16_t qclass, uint16_t qtype) + const knot_dname_t *qname, uint16_t qclass, uint16_t qtype) { - /* TODO: how to load all the layers? no API support yet */ - ctx->sname = knot_dname_copy(qname, ctx->mm); + if (ctx == NULL || result == NULL || qname == NULL) { + return -1; + } + + ctx->sname = qname; ctx->sclass = qclass; ctx->stype = qtype; + ctx->state = NS_PROC_MORE; kr_result_init(ctx, result); struct layer_param param; param.ctx = ctx; param.result = result; - /* TODO: read root hints. */ - struct sockaddr_in root_addr = uv_ip4_addr("198.41.0.4", 53); - kr_slist_add(ctx, knot_dname_copy((const uint8_t *)"", NULL), (struct sockaddr *)&root_addr); - - /* Resolve. */ - struct knot_requestor req; - knot_requestor_init(&req, LAYER_ITERATE, ctx->mm); - struct timeval tv = { 5, 0 }; - struct kr_ns *ns = NULL; - struct knot_request *tx = NULL; - int watchdog = 0; + /* TODO: how to load all the layers? no API support yet */ + struct timeval timeout = { 5, 0 }; + struct knot_requestor requestor; + knot_requestor_init(&requestor, LAYER_ITERATE, ctx->pool); + while(ctx->state != NS_PROC_DONE) { - ns = kr_slist_top(ctx); - tx = knot_requestor_make(&req, (const struct sockaddr *)&ns->addr, - NULL, NULL); - knot_requestor_enqueue(&req, tx, ¶m); - knot_requestor_exec(&req, &tv); - - /* TODO: restart if sname != originating */ - if (qname != ctx->sname) { - printf("we didn't resolve the cname target...yet\n"); - } + /* Sort preference list to the SNAME and pick a NS. */ + kr_slist_sort(ctx); + struct kr_ns *ns = kr_slist_top(ctx); - /* TODO: safety check, remove */ - assert(++watchdog < 10); - } - knot_requestor_clear(&req); + print_step("iterating"); - char *qnamestr = knot_dname_to_str(qname); - char *cnamestr = knot_dname_to_str(ctx->sname); - printf("resolution of %s -> %s\n", qnamestr, cnamestr); - free(qnamestr); free(cnamestr); - printf("rcode = %d (%u RR)\n", knot_wire_get_rcode(result->ans->wire), result->ans->rrset_count); - char strbuf[4096] = {0}; int buflen = sizeof(strbuf); - knot_dump_style_t style = {0}; - for (unsigned i = 0; i < result->ans->rrset_count; ++i) { - int r = knot_rrset_txt_dump(&result->ans->rr[i], strbuf, buflen, &style); - if (r > 0) buflen -= r; + /* Resolve. */ + struct knot_request *tx = knot_requestor_make(&requestor, + (const struct sockaddr *)&ns->addr, + NULL, NULL, 0); + knot_requestor_enqueue(&requestor, tx, ¶m); + int ret = knot_requestor_exec(&requestor, &timeout); + /* TODO: soft remove, retry later */ + if (ret != 0) { + print_step("server failure %d", ret); + kr_slist_pop(ctx); + } } - printf("%s", strbuf); - printf("queries: %u\n", result->nr_queries); - printf("rtt %.02f msecs\n", time_diff(&result->t_start, &result->t_end)); + + print_step(" ---> done"); + + knot_requestor_clear(&requestor); + + print_result(result); return 0; } diff --git a/lib/resolve.h b/lib/resolve.h index 3adc30597bacb583ae9e238a00a377211645fe9f..fd69484e59eb753a7a797f3142946e9d0905c2e7 100644 --- a/lib/resolve.h +++ b/lib/resolve.h @@ -18,4 +18,4 @@ limitations under the License. #include "context.h" int kr_resolve(struct kr_context* ctx, struct kr_result* result, - const knot_dname_t *qname, uint16_t qclass, uint16_t qtype); \ No newline at end of file + const knot_dname_t *qname, uint16_t qclass, uint16_t qtype); \ No newline at end of file diff --git a/tests/context.c b/tests/context.c index 86698c600f9cf63d6df585f1d477b20ad807f16e..cb9494a356b3e28d3e516cdeabb64e83ef5b6f1b 100644 --- a/tests/context.c +++ b/tests/context.c @@ -13,7 +13,7 @@ static void tests_ctx_create(void **state) mm_ctx_init(&mm); struct kr_context ctx; assert_int_equal(kr_context_init(&ctx, &mm), 0); - assert_int_equal(kr_context_close(&ctx), 0); + assert_int_equal(kr_context_deinit(&ctx), 0); } int main(void) diff --git a/tests/resolve.c b/tests/resolve.c index 8435d2fb860809e1d1b6305face0c6ae3b8ba361..05c55e2cf6a2aae013c596be7b8d7853f7a779c2 100644 --- a/tests/resolve.c +++ b/tests/resolve.c @@ -17,7 +17,7 @@ void test_resolve_sync(void **state) const knot_dname_t *qname = (const uint8_t *)"\x06""dnssec""\x02""cz"; int ret = kr_resolve(&ctx, &res, qname, KNOT_CLASS_IN, KNOT_RRTYPE_A); assert_int_equal(ret, 0); - kr_context_close(&ctx); + kr_result_deinit(&res); } int main(void)