mirror of
https://gitlab.nic.cz/knot/knot-dns.git
synced 2026-06-09 08:33:59 -04:00
nameserver: extend process_query
This commit is contained in:
parent
53f3073e53
commit
c6cb107ac2
2 changed files with 247 additions and 77 deletions
|
|
@ -10,6 +10,7 @@
|
|||
#include "knot/dnssec/rrset-sign.h"
|
||||
#include "knot/nameserver/process_query.h"
|
||||
#include "knot/nameserver/query_module.h"
|
||||
#include "knot/nameserver/query_state.h"
|
||||
#include "knot/nameserver/chaos.h"
|
||||
#include "knot/nameserver/internet.h"
|
||||
#include "knot/nameserver/axfr.h"
|
||||
|
|
@ -176,8 +177,42 @@ static knot_layer_state_t query_chaos(knot_pkt_t *pkt, knot_layer_t *ctx)
|
|||
return KNOT_STATE_DONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Lookup zone from plan if available, else fallback to regular DB lookup.
|
||||
*/
|
||||
static zone_t *lookup_zone(struct query_plan *plan, knotd_qdata_t *qdata, knot_pkt_t *query,
|
||||
knot_zonedb_t *db, const knot_dname_t *zone_name, bool is_suffix_match)
|
||||
{
|
||||
struct query_step *step;
|
||||
int next_state = KNOT_STATE_PRODUCE;
|
||||
qdata->extra->zone_lookup_params.is_suffix_match = is_suffix_match;
|
||||
qdata->extra->zone_lookup_params.zone_name = zone_name;
|
||||
|
||||
zone_t *static_zone_response = is_suffix_match ? knot_zonedb_find_suffix(db, zone_name)
|
||||
: knot_zonedb_find(db, zone_name);
|
||||
if (static_zone_response != NULL) {
|
||||
return static_zone_response;
|
||||
}
|
||||
|
||||
if (plan != NULL) {
|
||||
WALK_LIST(step, plan->stage[KNOTD_STAGE_ZONE_LOOKUP]) {
|
||||
next_state = step->general_hook(next_state, query, qdata, step->ctx);
|
||||
if (next_state == KNOT_STATE_FAIL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (next_state == KNOTD_STATE_ZONE_LOOKUPDONE) {
|
||||
return qdata->extra->zone;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*! \brief Find zone for given question. */
|
||||
static zone_t *answer_zone_find(const knot_pkt_t *query, knot_zonedb_t *zonedb)
|
||||
static zone_t *answer_zone_find(struct query_plan *plan, knotd_qdata_t *qdata,
|
||||
knot_pkt_t *query, knot_zonedb_t *zonedb)
|
||||
{
|
||||
uint16_t qtype = knot_pkt_qtype(query);
|
||||
uint16_t qclass = knot_pkt_qclass(query);
|
||||
|
|
@ -197,7 +232,7 @@ static zone_t *answer_zone_find(const knot_pkt_t *query, knot_zonedb_t *zonedb)
|
|||
bool deleg_query = (qtype == KNOT_RRTYPE_DELEG) && knot_pkt_has_deleg_aware(query);
|
||||
if ((ds_query || deleg_query) && qname[0] != '\0') {
|
||||
const knot_dname_t *parent = knot_dname_next_label(qname);
|
||||
zone = knot_zonedb_find_suffix(zonedb, parent);
|
||||
zone = lookup_zone(plan, qdata, query, zonedb, parent, true);
|
||||
/* If zone does not exist, search for its parent zone,
|
||||
this will later result to NODATA answer. */
|
||||
/*! \note This is not 100% right, it may lead to DS name for example
|
||||
|
|
@ -208,10 +243,10 @@ static zone_t *answer_zone_find(const knot_pkt_t *query, knot_zonedb_t *zonedb)
|
|||
|
||||
if (zone == NULL) {
|
||||
if (query_type(query) == KNOTD_QUERY_TYPE_NORMAL) {
|
||||
zone = knot_zonedb_find_suffix(zonedb, qname);
|
||||
zone = lookup_zone(plan, qdata, query, zonedb, qname, true);
|
||||
} else {
|
||||
// Direct match required.
|
||||
zone = knot_zonedb_find(zonedb, qname);
|
||||
zone = lookup_zone(plan, qdata, query, zonedb, qname, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -439,9 +474,9 @@ static int answer_edns_put(knot_pkt_t *resp, knotd_qdata_t *qdata)
|
|||
}
|
||||
|
||||
/*! \brief Initialize response, sizes and find zone from which we're going to answer. */
|
||||
static int prepare_answer(knot_pkt_t *query, knot_pkt_t *resp, knot_layer_t *ctx)
|
||||
static int prepare_answer(struct query_plan *plan, knotd_qdata_t *qdata, knot_pkt_t *query,
|
||||
knot_pkt_t *resp, knot_layer_t *ctx)
|
||||
{
|
||||
knotd_qdata_t *qdata = QUERY_DATA(ctx);
|
||||
server_t *server = qdata->params->server;
|
||||
|
||||
/* Initialize response. */
|
||||
|
|
@ -458,8 +493,9 @@ static int prepare_answer(knot_pkt_t *query, knot_pkt_t *resp, knot_layer_t *ctx
|
|||
}
|
||||
|
||||
/* Update maximal answer size. */
|
||||
uint16_t resp_size = KNOT_WIRE_MAX_PKTSIZE;
|
||||
if (qdata->params->proto == KNOTD_QUERY_PROTO_UDP) {
|
||||
resp->max_size = KNOT_WIRE_MIN_PKTSIZE;
|
||||
resp_size = KNOT_WIRE_MIN_PKTSIZE;
|
||||
if (knot_pkt_has_edns(query)) {
|
||||
uint16_t server_size;
|
||||
switch (knotd_qdata_remote_addr(qdata)->ss_family) {
|
||||
|
|
@ -474,11 +510,10 @@ static int prepare_answer(knot_pkt_t *query, knot_pkt_t *resp, knot_layer_t *ctx
|
|||
}
|
||||
uint16_t client_size = knot_edns_get_payload(query->opt_rr);
|
||||
uint16_t transfer = MIN(client_size, server_size);
|
||||
resp->max_size = MAX(resp->max_size, transfer);
|
||||
resp_size = MAX(resp_size, transfer);
|
||||
}
|
||||
} else {
|
||||
resp->max_size = KNOT_WIRE_MAX_PKTSIZE;
|
||||
}
|
||||
resp->max_size = MIN(resp->max_size, resp_size);
|
||||
|
||||
/* All supported OPCODEs require a question. */
|
||||
const knot_dname_t *qname = knot_pkt_qname(query);
|
||||
|
|
@ -496,7 +531,7 @@ static int prepare_answer(knot_pkt_t *query, knot_pkt_t *resp, knot_layer_t *ctx
|
|||
}
|
||||
|
||||
/* Find zone for QNAME. */
|
||||
qdata->extra->zone = answer_zone_find(query, server->zone_db);
|
||||
qdata->extra->zone = answer_zone_find(plan, qdata, query, server->zone_db);
|
||||
if (qdata->extra->zone != NULL && qdata->extra->contents == NULL) {
|
||||
qdata->extra->contents = qdata->extra->zone->contents;
|
||||
}
|
||||
|
|
@ -564,12 +599,20 @@ static knot_layer_state_t process_query_err(knot_layer_t *ctx, knot_pkt_t *pkt)
|
|||
return KNOT_STATE_DONE;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ASYNC_QUERY_HANDLING
|
||||
#define NON_CONTINUABLE_STATE(next_state) ((next_state) == KNOT_STATE_FAIL || (next_state) == KNOT_STATE_ASYNC)
|
||||
#define BREAK_IF_ASYNC(next_state) if ((next_state) == KNOT_STATE_ASYNC) { break; }
|
||||
#else
|
||||
#define NON_CONTINUABLE_STATE(next_state) ((next_state) == KNOT_STATE_FAIL)
|
||||
#define BREAK_IF_ASYNC(next_state)
|
||||
#endif
|
||||
|
||||
#define PROCESS_BEGIN(plan, step, next_state, qdata) \
|
||||
if (plan != NULL) { \
|
||||
WALK_LIST(step, plan->stage[KNOTD_STAGE_BEGIN]) { \
|
||||
assert(step->type == QUERY_HOOK_TYPE_GENERAL); \
|
||||
next_state = step->general_hook(next_state, pkt, qdata, step->ctx); \
|
||||
if (next_state == KNOT_STATE_FAIL) { \
|
||||
WALK_LIST_RESUME((step), plan->stage[KNOTD_STAGE_BEGIN]) { \
|
||||
assert((step)->type == QUERY_HOOK_TYPE_GENERAL); \
|
||||
next_state = (step)->general_hook(next_state, pkt, qdata, (step)->ctx); \
|
||||
if (NON_CONTINUABLE_STATE(next_state)) { \
|
||||
goto finish; \
|
||||
} \
|
||||
} \
|
||||
|
|
@ -577,15 +620,46 @@ static knot_layer_state_t process_query_err(knot_layer_t *ctx, knot_pkt_t *pkt)
|
|||
|
||||
#define PROCESS_END(plan, step, next_state, qdata) \
|
||||
if (plan != NULL) { \
|
||||
WALK_LIST(step, plan->stage[KNOTD_STAGE_END]) { \
|
||||
assert(step->type == QUERY_HOOK_TYPE_GENERAL); \
|
||||
next_state = step->general_hook(next_state, pkt, qdata, step->ctx); \
|
||||
WALK_LIST_RESUME((step), plan->stage[KNOTD_STAGE_END]) { \
|
||||
assert((step)->type == QUERY_HOOK_TYPE_GENERAL); \
|
||||
next_state = (step)->general_hook(next_state, pkt, qdata, (step)->ctx); \
|
||||
if (next_state == KNOT_STATE_FAIL) { \
|
||||
next_state = process_query_err(ctx, pkt); \
|
||||
} \
|
||||
BREAK_IF_ASYNC(next_state); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void init_state_machine(state_machine_t *state)
|
||||
{
|
||||
memset(state, 0, sizeof(*state));
|
||||
state->process_query_next_state = KNOT_STATE_PRODUCE;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ASYNC_QUERY_HANDLING
|
||||
static int complete_async_call(knotd_qdata_t *qdata)
|
||||
{
|
||||
return qdata->params->async_completed_callback(qdata->params);
|
||||
}
|
||||
|
||||
static int async_operation_in_completed_callback(knotd_qdata_t *qdata, int state)
|
||||
{
|
||||
assert(qdata->state);
|
||||
state_machine_t *state_machine = qdata->state;
|
||||
state_machine->process_query_next_state_in = state;
|
||||
return complete_async_call(qdata);
|
||||
}
|
||||
|
||||
static int async_operation_completed_callback(knotd_qdata_t *qdata, int state)
|
||||
{
|
||||
assert(qdata->state);
|
||||
state_machine_t *state_machine = qdata->state;
|
||||
state_machine->process_query_next_state = state;
|
||||
|
||||
return complete_async_call(qdata);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int process_query_out(knot_layer_t *ctx, knot_pkt_t *pkt)
|
||||
{
|
||||
assert(pkt && ctx);
|
||||
|
|
@ -595,9 +669,10 @@ static int process_query_out(knot_layer_t *ctx, knot_pkt_t *pkt)
|
|||
knotd_qdata_t *qdata = QUERY_DATA(ctx);
|
||||
struct query_plan *plan = conf()->query_plan;
|
||||
struct query_plan *zone_plan = NULL;
|
||||
struct query_step *step;
|
||||
|
||||
int next_state = KNOT_STATE_PRODUCE;
|
||||
state_machine_t *state = NULL;
|
||||
struct query_step *step = NULL;
|
||||
struct query_step **step_to_use = &step;
|
||||
int next_state;
|
||||
|
||||
/* Check parse state. */
|
||||
knot_pkt_t *query = qdata->query;
|
||||
|
|
@ -607,10 +682,44 @@ static int process_query_out(knot_layer_t *ctx, knot_pkt_t *pkt)
|
|||
goto finish;
|
||||
}
|
||||
|
||||
/* Preprocessing. */
|
||||
if (prepare_answer(query, pkt, ctx) != KNOT_EOK) {
|
||||
next_state = KNOT_STATE_FAIL;
|
||||
goto finish;
|
||||
state = qdata->state;
|
||||
if (state == NULL) {
|
||||
state = mm_alloc(ctx->mm, sizeof(*state));
|
||||
if (state == NULL) {
|
||||
qdata->rcode = KNOT_RCODE_SERVFAIL;
|
||||
next_state = KNOT_STATE_FAIL;
|
||||
goto finish;
|
||||
}
|
||||
init_state_machine(state);
|
||||
qdata->state = state;
|
||||
#ifdef ENABLE_ASYNC_QUERY_HANDLING
|
||||
qdata->async_completed = async_operation_completed_callback;
|
||||
qdata->async_in_completed = async_operation_in_completed_callback;
|
||||
#endif
|
||||
}
|
||||
step_to_use = &state->step;
|
||||
|
||||
next_state = state->process_query_next_state;
|
||||
#ifdef ENABLE_ASYNC_QUERY_HANDLING
|
||||
assert(next_state != KNOT_STATE_ASYNC); /* at the beginning or resuming cant be in async */
|
||||
#endif
|
||||
if (NON_CONTINUABLE_STATE(next_state)) {
|
||||
if (state->process_query_state == PROCESS_QUERY_STATE_DONE_ZONE_PLAN_BEGIN) {
|
||||
/* Async state and failurs are result of query_* methods
|
||||
* Go to query_* and recover execution from there. */
|
||||
goto run_query;
|
||||
} else {
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
STATE_MACHINE_RUN_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_PREPARE_ANSWER) {
|
||||
/* Preprocessing. */
|
||||
if (prepare_answer(plan, qdata, query, pkt, ctx) != KNOT_EOK) {
|
||||
next_state = KNOT_STATE_FAIL;
|
||||
goto finish;
|
||||
}
|
||||
STATE_MACHINE_COMPLETED_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_PREPARE_ANSWER);
|
||||
}
|
||||
|
||||
if (qdata->extra->zone != NULL && qdata->extra->zone->query_plan != NULL) {
|
||||
|
|
@ -618,77 +727,128 @@ static int process_query_out(knot_layer_t *ctx, knot_pkt_t *pkt)
|
|||
}
|
||||
|
||||
/* Before query processing code. */
|
||||
PROCESS_BEGIN(plan, step, next_state, qdata);
|
||||
PROCESS_BEGIN(zone_plan, step, next_state, qdata);
|
||||
|
||||
/* Answer based on qclass. */
|
||||
if (next_state == KNOT_STATE_PRODUCE) {
|
||||
switch (knot_pkt_qclass(pkt)) {
|
||||
case KNOT_CLASS_CH:
|
||||
next_state = query_chaos(pkt, ctx);
|
||||
break;
|
||||
case KNOT_CLASS_ANY:
|
||||
case KNOT_CLASS_IN:
|
||||
next_state = query_internet(pkt, ctx);
|
||||
break;
|
||||
default:
|
||||
qdata->rcode = KNOT_RCODE_REFUSED;
|
||||
next_state = KNOT_STATE_FAIL;
|
||||
break;
|
||||
}
|
||||
STATE_MACHINE_RUN_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_PLAN_BEGIN) {
|
||||
PROCESS_BEGIN(plan, *step_to_use, next_state, qdata);
|
||||
STATE_MACHINE_COMPLETED_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_PLAN_BEGIN);
|
||||
}
|
||||
|
||||
/* Postprocessing. */
|
||||
if (next_state == KNOT_STATE_DONE || next_state == KNOT_STATE_PRODUCE) {
|
||||
/* Move to Additionals to add OPT and TSIG. */
|
||||
if (pkt->current != KNOT_ADDITIONAL) {
|
||||
(void)knot_pkt_begin(pkt, KNOT_ADDITIONAL);
|
||||
}
|
||||
STATE_MACHINE_RUN_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_ZONE_PLAN_BEGIN) {
|
||||
PROCESS_BEGIN(zone_plan, *step_to_use, next_state, qdata);
|
||||
STATE_MACHINE_COMPLETED_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_ZONE_PLAN_BEGIN);
|
||||
}
|
||||
|
||||
/* Put OPT RR to the additional section. */
|
||||
if (answer_edns_put(pkt, qdata) != KNOT_EOK) {
|
||||
qdata->rcode = KNOT_RCODE_FORMERR;
|
||||
next_state = KNOT_STATE_FAIL;
|
||||
goto finish;
|
||||
run_query:
|
||||
STATE_MACHINE_RUN_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_QUERY) {
|
||||
/* Answer based on qclass. */
|
||||
if (next_state == KNOT_STATE_PRODUCE) {
|
||||
switch (knot_pkt_qclass(pkt)) {
|
||||
case KNOT_CLASS_CH:
|
||||
next_state = query_chaos(pkt, ctx);
|
||||
break;
|
||||
case KNOT_CLASS_ANY:
|
||||
case KNOT_CLASS_IN:
|
||||
next_state = query_internet(pkt, ctx);
|
||||
break;
|
||||
default:
|
||||
qdata->rcode = KNOT_RCODE_REFUSED;
|
||||
next_state = KNOT_STATE_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
STATE_MACHINE_COMPLETED_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_QUERY);
|
||||
}
|
||||
|
||||
/* Transaction security (if applicable). */
|
||||
if (process_query_sign_response(pkt, qdata) != KNOT_EOK) {
|
||||
next_state = KNOT_STATE_FAIL;
|
||||
goto finish;
|
||||
}
|
||||
STATE_MACHINE_RUN_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_POST_QUERY) {
|
||||
/* Postprocessing. */
|
||||
if (next_state == KNOT_STATE_DONE || next_state == KNOT_STATE_PRODUCE) {
|
||||
/* Move to Additionals to add OPT and TSIG. */
|
||||
if (pkt->current != KNOT_ADDITIONAL) {
|
||||
(void)knot_pkt_begin(pkt, KNOT_ADDITIONAL);
|
||||
}
|
||||
|
||||
/* Optional postprocessing with known final EDNS + TSIG (for XFR stats). */
|
||||
if (qdata->extra->ext_finished != NULL) {
|
||||
qdata->extra->ext_finished(qdata, pkt, next_state);
|
||||
/* Put OPT RR to the additional section. */
|
||||
if (answer_edns_put(pkt, qdata) != KNOT_EOK) {
|
||||
qdata->rcode = KNOT_RCODE_FORMERR;
|
||||
next_state = KNOT_STATE_FAIL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* Transaction security (if applicable). */
|
||||
if (process_query_sign_response(pkt, qdata) != KNOT_EOK) {
|
||||
next_state = KNOT_STATE_FAIL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* Optional postprocessing with known final EDNS + TSIG (for XFR stats). */
|
||||
if (qdata->extra->ext_finished != NULL) {
|
||||
qdata->extra->ext_finished(qdata, pkt, next_state);
|
||||
}
|
||||
}
|
||||
STATE_MACHINE_COMPLETED_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_POST_QUERY);
|
||||
}
|
||||
|
||||
finish:
|
||||
switch (next_state) {
|
||||
case KNOT_STATE_NOOP:
|
||||
break;
|
||||
case KNOT_STATE_FAIL:
|
||||
/* Error processing. */
|
||||
next_state = process_query_err(ctx, pkt);
|
||||
break;
|
||||
case KNOT_STATE_FINAL:
|
||||
/* Just skipped postprocessing. */
|
||||
next_state = KNOT_STATE_DONE;
|
||||
break;
|
||||
default:
|
||||
set_rcode_to_packet(pkt, qdata);
|
||||
STATE_MACHINE_RUN_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_HANDLE_ERROR) {
|
||||
switch (next_state) {
|
||||
case KNOT_STATE_NOOP:
|
||||
break;
|
||||
case KNOT_STATE_FAIL:
|
||||
/* Error processing. */
|
||||
next_state = process_query_err(ctx, pkt);
|
||||
break;
|
||||
case KNOT_STATE_FINAL:
|
||||
/* Just skipped postprocessing. */
|
||||
next_state = KNOT_STATE_DONE;
|
||||
break;
|
||||
default:
|
||||
set_rcode_to_packet(pkt, qdata);
|
||||
}
|
||||
STATE_MACHINE_COMPLETED_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_HANDLE_ERROR);
|
||||
}
|
||||
|
||||
/* After query processing code. */
|
||||
PROCESS_END(plan, step, next_state, qdata);
|
||||
PROCESS_END(zone_plan, step, next_state, qdata);
|
||||
STATE_MACHINE_RUN_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_PLAN_END) {
|
||||
PROCESS_END(plan, *step_to_use, next_state, qdata);
|
||||
STATE_MACHINE_COMPLETED_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_PLAN_END);
|
||||
}
|
||||
|
||||
STATE_MACHINE_RUN_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_ZONE_PLAN_END) {
|
||||
PROCESS_END(zone_plan, *step_to_use, next_state, qdata);
|
||||
STATE_MACHINE_COMPLETED_STATE(state, next_state, KNOT_STATE_ASYNC, process_query_state, PROCESS_QUERY_STATE_DONE_ZONE_PLAN_END);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
if (knot_layer_active_state(next_state)) {
|
||||
/* Exiting the state machine with an active state will result in more produce calls which need to resume from beginning.
|
||||
* Reset the state machine so it will execute all steps. */
|
||||
if (state) {
|
||||
init_state_machine(state);
|
||||
}
|
||||
}
|
||||
|
||||
return next_state;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ASYNC_QUERY_HANDLING
|
||||
static int process_query_set_async_state(knot_layer_t *ctx, knot_pkt_t *pkt, int layer_state)
|
||||
{
|
||||
assert(pkt && ctx);
|
||||
knotd_qdata_t *qdata = QUERY_DATA(ctx);
|
||||
if (qdata != NULL) {
|
||||
state_machine_t *state = qdata->state;
|
||||
if (state != NULL) {
|
||||
state->process_query_next_state = layer_state;
|
||||
if (layer_state == KNOT_STATE_FAIL) {
|
||||
state->process_query_next_state_in = KNOTD_IN_STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return layer_state;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool process_query_acl_check(conf_t *conf, acl_action_t action,
|
||||
knotd_qdata_t *qdata)
|
||||
{
|
||||
|
|
@ -1055,6 +1215,9 @@ const knot_layer_api_t *process_query_layer(void)
|
|||
.finish = &process_query_finish,
|
||||
.consume = &process_query_in,
|
||||
.produce = &process_query_out,
|
||||
#ifdef ENABLE_ASYNC_QUERY_HANDLING
|
||||
.set_async_state = &process_query_set_async_state,
|
||||
#endif
|
||||
};
|
||||
return &api;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,13 @@ typedef struct knotd_qdata_extra {
|
|||
void *ext;
|
||||
void (*ext_cleanup)(knotd_qdata_t *); /*!< Extensions cleanup callback. */
|
||||
void (*ext_finished)(knotd_qdata_t *, knot_pkt_t *, int); /*!< Optional postprocessing callback. */
|
||||
|
||||
struct {
|
||||
const knot_dname_t *zone_name;
|
||||
bool is_suffix_match;
|
||||
} zone_lookup_params;
|
||||
|
||||
int ext_result; /*!< Additional error code from module. Modules MUST return this value for : KNOTD_STAGE_NAME_LOOKUP */
|
||||
} knotd_qdata_extra_t;
|
||||
|
||||
/*! \brief Visited wildcard node list. */
|
||||
|
|
|
|||
Loading…
Reference in a new issue