diff --git a/src/knot/query/layer.h b/src/knot/query/layer.h index 948663a11e8cea669a04305314d9f23093481515..a1f6eaf64a379dfbe80649d7a3f49396369c7d1c 100644 --- a/src/knot/query/layer.h +++ b/src/knot/query/layer.h @@ -29,6 +29,7 @@ enum knot_layer_state { KNOT_STATE_NOOP = 0, //!< Invalid. KNOT_STATE_CONSUME, //!< Consume data. KNOT_STATE_PRODUCE, //!< Produce data. + KNOT_STATE_RESET, //!< Restart processing. KNOT_STATE_DONE, //!< Finished. KNOT_STATE_FAIL //!< Error. }; diff --git a/src/knot/query/requestor.c b/src/knot/query/requestor.c index 5a9a435d51bd98e3ca89d61a10061124df247df7..6024a3c03fa9575963e51cf00e2a40798787681d 100644 --- a/src/knot/query/requestor.c +++ b/src/knot/query/requestor.c @@ -105,6 +105,7 @@ struct knot_request *knot_request_make(knot_mm_t *mm, const struct sockaddr *remote, const struct sockaddr *source, knot_pkt_t *query, + const knot_tsig_key_t *tsig_key, unsigned flags) { if (remote == NULL || query == NULL) { @@ -133,6 +134,8 @@ struct knot_request *knot_request_make(knot_mm_t *mm, request->source.ss_family = AF_UNSPEC; } + tsig_init(&request->tsig, tsig_key); + return request; } @@ -147,6 +150,7 @@ void knot_request_free(struct knot_request *request, knot_mm_t *mm) } knot_pkt_free(&request->query); knot_pkt_free(&request->resp); + tsig_cleanup(&request->tsig); mm_free(mm, request); } @@ -163,7 +167,7 @@ int knot_requestor_init(struct knot_requestor *requestor, requestor->mm = mm; knot_layer_init(&requestor->layer, mm, proc); - requestor->layer.state = knot_layer_begin(&requestor->layer, proc_param); + knot_layer_begin(&requestor->layer, proc_param); return KNOT_EOK; } @@ -179,53 +183,89 @@ void knot_requestor_clear(struct knot_requestor *requestor) memset(requestor, 0, sizeof(*requestor)); } -static int request_io(struct knot_requestor *req, struct knot_request *last, - int timeout_ms) +static int request_reset(struct knot_requestor *req, + struct knot_request *last) { - int ret = KNOT_EOK; - knot_pkt_t *query = last->query; - knot_pkt_t *resp = last->resp; + knot_layer_reset(&req->layer); + tsig_reset(&last->tsig); + + if (req->layer.state == KNOT_STATE_RESET) { + return KNOT_LAYER_ERROR; + } - /* Data to be sent. */ - if (req->layer.state == KNOT_STATE_PRODUCE) { + return KNOT_EOK; +} - /* Process query and send it out. */ - knot_layer_produce(&req->layer, query); +static int request_produce(struct knot_requestor *req, + struct knot_request *last, + int timeout_ms) +{ + knot_layer_produce(&req->layer, last->query); - if (req->layer.state == KNOT_STATE_CONSUME) { - ret = request_send(last, timeout_ms); - if (ret != KNOT_EOK) { - return ret; - } - } + int ret = tsig_sign_packet(&last->tsig, last->query); + if (ret != KNOT_EOK) { + return ret; } - /* Data to be read. */ + // TODO: verify condition if (req->layer.state == KNOT_STATE_CONSUME) { - /* Read answer and process it. */ - ret = request_recv(last, timeout_ms); - if (ret < 0) { - return ret; - } + ret = request_send(last, timeout_ms); + } + + return ret; +} - (void) knot_pkt_parse(resp, 0); - knot_layer_consume(&req->layer, resp); +static int request_consume(struct knot_requestor *req, + struct knot_request *last, + int timeout_ms) +{ + int ret = request_recv(last, timeout_ms); + if (ret < 0) { + return ret; } + ret = knot_pkt_parse(last->resp, 0); + if (ret != KNOT_EOK) { + return ret; + } + + ret = tsig_verify_packet(&last->tsig, last->resp); + if (ret != KNOT_EOK) { + return ret; + } + + knot_layer_consume(&req->layer, last->resp); + return KNOT_EOK; } static bool layer_active(enum knot_layer_state state) { switch (state) { - case KNOT_STATE_PRODUCE: case KNOT_STATE_CONSUME: + case KNOT_STATE_PRODUCE: + case KNOT_STATE_RESET: return true; default: return false; } } +static int request_io(struct knot_requestor *req, struct knot_request *last, + int timeout_ms) +{ + switch (req->layer.state) { + case KNOT_STATE_CONSUME: + return request_consume(req, last, timeout_ms); + case KNOT_STATE_PRODUCE: + return request_produce(req, last, timeout_ms); + case KNOT_STATE_RESET: + return request_reset(req, last); + default: + return KNOT_EINVAL; + } +} + int knot_requestor_exec(struct knot_requestor *requestor, struct knot_request *request, int timeout_ms) @@ -240,7 +280,7 @@ int knot_requestor_exec(struct knot_requestor *requestor, while (layer_active(requestor->layer.state)) { ret = request_io(requestor, request, timeout_ms); if (ret != KNOT_EOK) { - knot_layer_reset(&requestor->layer); + knot_layer_finish(&requestor->layer); return ret; } } @@ -250,8 +290,13 @@ int knot_requestor_exec(struct knot_requestor *requestor, ret = KNOT_LAYER_ERROR; } + /* Verify last TSIG */ + if (tsig_unsigned_count(&request->tsig) != 0) { + ret = KNOT_LAYER_ERROR; + } + /* Finish current query processing. */ - knot_layer_reset(&requestor->layer); + knot_layer_finish(&requestor->layer); return ret; } diff --git a/src/knot/query/requestor.h b/src/knot/query/requestor.h index 1a8822a7c6c7071b3df05bbbe691fbe13e3ef8f4..335a4b15faf5cd345c7bacdefaf1d7bb646ed4a0 100644 --- a/src/knot/query/requestor.h +++ b/src/knot/query/requestor.h @@ -19,6 +19,7 @@ #include <sys/socket.h> #include <sys/time.h> +#include "knot/nameserver/tsig_ctx.h" #include "knot/query/layer.h" #include "libknot/mm_ctx.h" #include "libknot/rrtype/tsig.h" @@ -46,7 +47,9 @@ struct knot_request { struct sockaddr_storage remote, source; knot_pkt_t *query; knot_pkt_t *resp; - knot_sign_context_t sign; + tsig_ctx_t tsig; + knot_sign_context_t sign; // TODO: WIPE? + knot_layer_t layer; }; /*! @@ -56,6 +59,7 @@ struct knot_request { * \param dst Remote endpoint address. * \param src Source address (or NULL). * \param query Query message. + * \param key TSIG key for authentication. * \param flags Request flags. * * \return Prepared request or NULL in case of error. @@ -64,6 +68,7 @@ struct knot_request *knot_request_make(knot_mm_t *mm, const struct sockaddr *dst, const struct sockaddr *src, knot_pkt_t *query, + const knot_tsig_key_t *key, unsigned flags); /*! diff --git a/tests/requestor.c b/tests/requestor.c index d3afc5ac394bcf41a51bbe766cb1d6a9f8b44556..13c32438526b26c6b472d2023f3944e4986311f8 100644 --- a/tests/requestor.c +++ b/tests/requestor.c @@ -34,7 +34,7 @@ * but simply if the requesting/receiving works, so mirror is okay. */ static int reset(knot_layer_t *ctx) { return KNOT_STATE_PRODUCE; } static int begin(knot_layer_t *ctx, void *module_param) { return reset(ctx); } -static int finish(knot_layer_t *ctx) { return KNOT_STATE_NOOP; } +static int finish(knot_layer_t *ctx) { return reset(ctx); } static int in(knot_layer_t *ctx, knot_pkt_t *pkt) { return KNOT_STATE_DONE; } static int out(knot_layer_t *ctx, knot_pkt_t *pkt) { return KNOT_STATE_CONSUME; } @@ -42,8 +42,7 @@ static const int TIMEOUT = 2000; /*! \brief Dummy answer processing module. */ const knot_layer_api_t dummy_module = { - &begin, &reset, &finish, - &in, &out, NULL + &begin, &reset, &finish, &in, &out, NULL }; static void set_blocking_mode(int sock)