diff --git a/daemon/engine.h b/daemon/engine.h index d7acd94d8a8d8db8c8ccd6e3eaa2b4ff7840585a..bb1f9c37cdc0a1df9acccac4504f0da6cc880015 100644 --- a/daemon/engine.h +++ b/daemon/engine.h @@ -39,6 +39,6 @@ int engine_start(struct engine *engine); void engine_stop(struct engine *engine); int engine_register(struct engine *engine, const char *module); int engine_unregister(struct engine *engine, const char *module); -/** Return engine light userdata. */ void engine_lualib(struct engine *engine, const char *name, int (*lib_cb) (struct lua_State *)); +/** Return engine light userdata. */ struct engine *engine_luaget(struct lua_State *L); diff --git a/daemon/io.c b/daemon/io.c index 6f7e01187b50f75f3e5b33128e210aae55250350..548100371c3e5cc541833ab68f95abd2f1f6e3e9 100644 --- a/daemon/io.c +++ b/daemon/io.c @@ -56,7 +56,7 @@ void udp_recv(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf, /* UDP requests are oneshot, always close afterwards */ if (handle->data && !uv_is_closing((uv_handle_t *)handle)) { /* Do not free master socket */ - uv_close((uv_handle_t *)handle, handle_free); + io_close((uv_handle_t *)handle); } /* Check the incoming wire length. */ @@ -96,7 +96,7 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf) /* Check for connection close */ if (nread <= 0) { - uv_close((uv_handle_t *)handle, handle_free); + io_close((uv_handle_t *)handle); return; } else if (nread < 2) { /* Not enough bytes to read length */ @@ -175,6 +175,11 @@ uv_handle_t *io_create(uv_loop_t *loop, int type) } } +void io_close(uv_handle_t *handle) +{ + uv_close(handle, (uv_close_cb) handle_free); +} + int io_start_read(uv_handle_t *handle) { if (handle->type == UV_UDP) { @@ -191,4 +196,4 @@ int io_stop_read(uv_handle_t *handle) } else { return uv_read_stop((uv_stream_t *)handle); } -} \ No newline at end of file +} diff --git a/daemon/io.h b/daemon/io.h index 815387f0a7c348c19243a12a3920877f0e14fbe0..83e01a0683228e235b87f98263dfe6eeecbc43dc 100644 --- a/daemon/io.h +++ b/daemon/io.h @@ -25,5 +25,6 @@ void udp_unbind(struct endpoint *ep); int tcp_bind(struct endpoint *ep, struct sockaddr *addr); void tcp_unbind(struct endpoint *ep); uv_handle_t *io_create(uv_loop_t *loop, int type); +void io_close(uv_handle_t *handle); int io_start_read(uv_handle_t *handle); int io_stop_read(uv_handle_t *handle); \ No newline at end of file diff --git a/daemon/worker.c b/daemon/worker.c index 732b309774861e779b39cfb5ce7977ebb22495e3..55fbbd9a475b17f619c1c3967957f0b9aacc7f3f 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -15,7 +15,6 @@ */ #include <uv.h> - #include <libknot/packet/pkt.h> #include <libknot/internal/net.h> #include <libknot/internal/mempool.h> @@ -43,8 +42,11 @@ struct qr_task } addr; uv_handle_t *handle; } source; + uint16_t iter_count; + uint16_t flags; }; +/* Forward decls */ static int qr_task_step(struct qr_task *task, knot_pkt_t *packet); static int parse_query(knot_pkt_t *query) @@ -71,6 +73,7 @@ static struct qr_task *qr_task_create(struct worker_ctx *worker, uv_handle_t *ha /* Create worker task */ struct engine *engine = worker->engine; struct qr_task *task = mm_alloc(&pool, sizeof(*task)); + memset(task, 0, sizeof(*task)); if (!task) { mp_delete(pool.ctx); return NULL; @@ -98,7 +101,7 @@ static struct qr_task *qr_task_create(struct worker_ctx *worker, uv_handle_t *ha return task; } -static void qr_task_close(uv_handle_t *handle) +static void qr_task_free(uv_handle_t *handle) { struct qr_task *task = handle->data; mp_delete(task->req.pool.ctx); @@ -123,9 +126,8 @@ static void qr_task_on_send(uv_req_t* req, int status) if (status == 0 && task->next_handle) { io_start_read(task->next_handle); } - } else { - /* Finalize task */ - uv_close((uv_handle_t *)&task->timeout, qr_task_close); + } else { /* Finalize task */ + uv_close((uv_handle_t *)&task->timeout, qr_task_free); } } } @@ -163,7 +165,6 @@ static void qr_task_on_connect(uv_connect_t *connect, int status) static int qr_task_finalize(struct qr_task *task, int state) { kr_resolve_finish(&task->req, state); - uv_timer_stop(&task->timeout); qr_task_send(task, task->source.handle, (struct sockaddr *)&task->source.addr, task->req.answer); return state == KNOT_STATE_DONE ? 0 : kr_error(EIO); } @@ -188,6 +189,11 @@ static int qr_task_step(struct qr_task *task, knot_pkt_t *packet) return qr_task_finalize(task, state); } + /* Iteration limit */ + if (++task->iter_count > KR_ITER_LIMIT) { + return qr_task_finalize(task, KNOT_STATE_FAIL); + } + /* Create connection for iterative query */ uv_handle_t *source_handle = task->source.handle; task->next_handle = io_create(source_handle->loop, sock_type); @@ -233,7 +239,6 @@ int worker_exec(struct worker_ctx *worker, uv_handle_t *handle, knot_pkt_t *quer struct qr_task *task = handle->data; bool is_master_socket = (!task); if (is_master_socket) { - /* Accept only queries */ if (knot_wire_get_qr(query->wire)) { return kr_error(EINVAL); /* Ignore. */ } diff --git a/lib/defines.h b/lib/defines.h index 141f219557df72af09e1b7b5f38297ec84595925..773314a11b1de3cd81f89d36c2641f9ba8342022 100644 --- a/lib/defines.h +++ b/lib/defines.h @@ -33,7 +33,7 @@ * @cond internal */ #define KR_CONN_RTT_MAX 5000 /* Timeout for network activity */ -#define ITER_LIMIT 50 /* Built-in iterator limit */ +#define KR_ITER_LIMIT 50 /* Built-in iterator limit */ /* * Timers. diff --git a/lib/layer/iterate.c b/lib/layer/iterate.c index f7673cce31fe47cbdf2cf6a4da5434acc56d74d9..d13d876c03708bf412c1d256ca0ba95e7b99f93d 100644 --- a/lib/layer/iterate.c +++ b/lib/layer/iterate.c @@ -276,7 +276,9 @@ static int process_answer(knot_pkt_t *pkt, struct kr_request *req) */ bool is_final = (query->parent == NULL); int pkt_class = response_classify(pkt); - if (!knot_dname_is_equal(knot_pkt_qname(pkt), query->sname) && (pkt_class & (PKT_NXDOMAIN|PKT_NODATA))) { + if (!knot_dname_is_equal(knot_pkt_qname(pkt), query->sname) && + (pkt_class & (PKT_NOERROR|PKT_NXDOMAIN|PKT_NODATA))) { + DEBUG_MSG("<= found cut, retrying with non-minimized name\n"); query->flags |= QUERY_NO_MINIMIZE; return KNOT_STATE_DONE; } @@ -301,6 +303,7 @@ static int process_answer(knot_pkt_t *pkt, struct kr_request *req) /* Follow canonical name as next SNAME. */ if (cname != query->sname) { + DEBUG_MSG("<= cname chain, following\n"); (void) kr_rplan_push(&req->rplan, query->parent, cname, query->sclass, query->stype); } else { if (query->parent == NULL) { diff --git a/lib/resolve.c b/lib/resolve.c index 4c1b912008452f5a483b796b86943578f7159631..281efe69ece50cd5846db456cfd14ecafc0c7be0 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -168,8 +168,8 @@ int kr_resolve(struct kr_context* ctx, knot_pkt_t *answer, int state = kr_resolve_query(&request, qname, qclass, qtype); while (state == KNOT_STATE_PRODUCE) { /* Hardlimit on iterative queries */ - if (++iter_count > ITER_LIMIT) { - DEBUG_MSG("iteration limit %d reached\n", ITER_LIMIT); + if (++iter_count > KR_ITER_LIMIT) { + DEBUG_MSG("iteration limit %d reached\n", KR_ITER_LIMIT); state = KNOT_STATE_FAIL; break; } diff --git a/tests/testdata/iter_minim_nonempty.rpl b/tests/testdata/iter_minim_nonempty.rpl new file mode 100644 index 0000000000000000000000000000000000000000..44e88349c05f01b219e93023ffcf186b4c0dfec1 --- /dev/null +++ b/tests/testdata/iter_minim_nonempty.rpl @@ -0,0 +1,125 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + query-minimization: on + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test query minimization with terminal in resolution path. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +gtld-servers.net. IN NS +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS lame-addr.gtld-servers.net. +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +lame-addr.gtld-servers.net. IN A 1.1.1.1 +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; lame.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 1.1.1.1 + +EANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN CNAME nowhere. +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN NS +SECTION ANSWER +www.example.com. IN NS blackhole. +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN NS +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN NS +SECTION ANSWER +www.example.com. IN NS blackhole. +ENTRY_END + +SCENARIO_END