From 75607a957bcaef602a5c2d5ce6a39964bfad2b5f Mon Sep 17 00:00:00 2001 From: Marek Vavrusa <marek.vavrusa@nic.cz> Date: Wed, 29 Jan 2014 10:49:56 +0100 Subject: [PATCH] Split packet processing API from name-server.h to libknot/processing --- Knot.files | 8 +- src/Makefile.am | 6 +- src/knot/nameserver/axfr.c | 2 +- src/knot/nameserver/internet.c | 2 +- src/knot/nameserver/internet.h | 4 +- src/knot/nameserver/ixfr.c | 2 +- src/knot/nameserver/name-server.c | 96 ------------- src/knot/nameserver/name-server.h | 110 --------------- src/knot/nameserver/nsec_proofs.c | 2 +- .../{ns_proc_query.c => process_query.c} | 86 ++++++------ .../{ns_proc_query.h => process_query.h} | 40 +++--- src/knot/nameserver/update.c | 2 +- src/knot/server/notify.c | 2 +- src/knot/server/tcp-handler.c | 24 ++-- src/knot/server/udp-handler.c | 46 ++++--- src/libknot/processing/process.c | 119 ++++++++++++++++ src/libknot/processing/process.h | 127 ++++++++++++++++++ src/libknot/tsig.h | 13 ++ tests/Makefile.inc | 2 +- tests/TESTS | 2 +- tests/{ns.c => process_query.c} | 44 +++--- 21 files changed, 405 insertions(+), 334 deletions(-) rename src/knot/nameserver/{ns_proc_query.c => process_query.c} (85%) rename src/knot/nameserver/{ns_proc_query.h => process_query.h} (82%) create mode 100644 src/libknot/processing/process.c create mode 100644 src/libknot/processing/process.h rename tests/{ns.c => process_query.c} (87%) diff --git a/Knot.files b/Knot.files index 350c24524..f5afd3251 100644 --- a/Knot.files +++ b/Knot.files @@ -113,10 +113,10 @@ src/knot/nameserver/ixfr.c src/knot/nameserver/ixfr.h src/knot/nameserver/name-server.c src/knot/nameserver/name-server.h -src/knot/nameserver/ns_proc_query.c -src/knot/nameserver/ns_proc_query.h src/knot/nameserver/nsec_proofs.c src/knot/nameserver/nsec_proofs.h +src/knot/nameserver/process_query.c +src/knot/nameserver/process_query.h src/knot/nameserver/update.c src/knot/nameserver/update.h src/knot/other/debug.h @@ -205,6 +205,8 @@ src/libknot/packet/compr.h src/libknot/packet/pkt.c src/libknot/packet/pkt.h src/libknot/packet/wire.h +src/libknot/processing/process.c +src/libknot/processing/process.h src/libknot/rdata.h src/libknot/rrset-dump.c src/libknot/rrset-dump.h @@ -284,8 +286,8 @@ tests/fdset.c tests/hattrie.c tests/hhash.c tests/journal.c -tests/ns.c tests/pkt.c +tests/process_query.c tests/rrl.c tests/rrset.c tests/runtests.c diff --git a/src/Makefile.am b/src/Makefile.am index c3d79fd47..dceb1d471 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -113,6 +113,8 @@ libknot_la_SOURCES = \ libknot/packet/compr.c \ libknot/packet/compr.h \ libknot/packet/wire.h \ + libknot/processing/process.c \ + libknot/processing/process.h \ libknot/dname.c \ libknot/consts.h \ libknot/edns.h \ @@ -240,8 +242,8 @@ libknotd_la_SOURCES = \ knot/nameserver/ixfr.h \ knot/nameserver/name-server.c \ knot/nameserver/name-server.h \ - knot/nameserver/ns_proc_query.c \ - knot/nameserver/ns_proc_query.h \ + knot/nameserver/process_query.c \ + knot/nameserver/process_query.h \ knot/nameserver/nsec_proofs.c \ knot/nameserver/nsec_proofs.h \ knot/nameserver/update.c \ diff --git a/src/knot/nameserver/axfr.c b/src/knot/nameserver/axfr.c index e494c5922..3126e18d7 100644 --- a/src/knot/nameserver/axfr.c +++ b/src/knot/nameserver/axfr.c @@ -18,7 +18,7 @@ #include "knot/nameserver/axfr.h" #include "knot/nameserver/internet.h" -#include "knot/nameserver/ns_proc_query.h" +#include "knot/nameserver/process_query.h" #include "libknot/util/debug.h" #include "common/descriptor.h" #include "common/lists.h" diff --git a/src/knot/nameserver/internet.c b/src/knot/nameserver/internet.c index ca4366855..2c269bef4 100644 --- a/src/knot/nameserver/internet.c +++ b/src/knot/nameserver/internet.c @@ -2,7 +2,7 @@ #include "knot/nameserver/internet.h" #include "knot/nameserver/nsec_proofs.h" -#include "knot/nameserver/ns_proc_query.h" +#include "knot/nameserver/process_query.h" #include "libknot/common.h" #include "libknot/rdata.h" #include "libknot/util/debug.h" diff --git a/src/knot/nameserver/internet.h b/src/knot/nameserver/internet.h index dc114f1dc..e419bec8f 100644 --- a/src/knot/nameserver/internet.h +++ b/src/knot/nameserver/internet.h @@ -67,10 +67,10 @@ int internet_answer(knot_pkt_t *resp, struct query_data *qdata); /*! \brief Require authentication. */ #define NS_NEED_AUTH(acl, qdata) \ - if (!ns_proc_query_acl_check((acl), (qdata))) { \ + if (!process_query_acl_check((acl), (qdata))) { \ return NS_PROC_FAIL; \ } else { \ - if (ns_proc_query_verify(qdata) != KNOT_EOK) { \ + if (process_query_verify(qdata) != KNOT_EOK) { \ return NS_PROC_FAIL; \ } \ } diff --git a/src/knot/nameserver/ixfr.c b/src/knot/nameserver/ixfr.c index 5bbd7f23b..3ca336e7f 100644 --- a/src/knot/nameserver/ixfr.c +++ b/src/knot/nameserver/ixfr.c @@ -3,7 +3,7 @@ #include "knot/nameserver/ixfr.h" #include "knot/nameserver/axfr.h" #include "knot/nameserver/internet.h" -#include "knot/nameserver/ns_proc_query.h" +#include "knot/nameserver/process_query.h" #include "libknot/util/debug.h" #include "libknot/rdata.h" #include "knot/server/zones.h" diff --git a/src/knot/nameserver/name-server.c b/src/knot/nameserver/name-server.c index 0c64bcd86..7b91186cb 100644 --- a/src/knot/nameserver/name-server.c +++ b/src/knot/nameserver/name-server.c @@ -484,99 +484,3 @@ void knot_ns_destroy(knot_nameserver_t **nameserver) free(*nameserver); *nameserver = NULL; } - -/* State -> string translation table. */ -#ifdef KNOT_NS_DEBUG -#define NS_STATE_STR(x) _state_table[x] -static const char* _state_table[] = { - [NS_PROC_NOOP] = "NOOP", - [NS_PROC_MORE] = "MORE", - [NS_PROC_FULL] = "FULL", - [NS_PROC_DONE] = "DONE", - [NS_PROC_FAIL] = "FAIL" -}; -#endif /* KNOT_NS_DEBUG */ - -int ns_proc_begin(ns_proc_context_t *ctx, void *module_param, const ns_proc_module_t *module) -{ - /* Only in inoperable state. */ - if (ctx->state != NS_PROC_NOOP) { - return NS_PROC_NOOP; - } - -#ifdef KNOT_NS_DEBUG - /* Check module API. */ - assert(module->begin); - assert(module->in); - assert(module->out); - assert(module->err); - assert(module->reset); - assert(module->finish); -#endif /* KNOT_NS_DEBUG */ - - ctx->module = module; - ctx->state = module->begin(ctx, module_param); - - dbg_ns("%s -> %s\n", __func__, NS_STATE_STR(ctx->state)); - return ctx->state; -} - -int ns_proc_reset(ns_proc_context_t *ctx) -{ - ctx->state = ctx->module->reset(ctx); - dbg_ns("%s -> %s\n", __func__, NS_STATE_STR(ctx->state)); - return ctx->state; -} - -int ns_proc_finish(ns_proc_context_t *ctx) -{ - /* Only in operable state. */ - if (ctx->state == NS_PROC_NOOP) { - return NS_PROC_NOOP; - } - - ctx->state = ctx->module->finish(ctx); - dbg_ns("%s -> %s\n", __func__, NS_STATE_STR(ctx->state)); - return ctx->state; -} - -int ns_proc_in(const uint8_t *wire, uint16_t wire_len, ns_proc_context_t *ctx) -{ - /* Only if expecting data. */ - if (ctx->state != NS_PROC_MORE) { - return NS_PROC_NOOP; - } - - knot_pkt_t *pkt = knot_pkt_new((uint8_t *)wire, wire_len, &ctx->mm); - knot_pkt_parse(pkt, 0); - - ctx->state = ctx->module->in(pkt, ctx); - dbg_ns("%s -> %s\n", __func__, NS_STATE_STR(ctx->state)); - return ctx->state; -} - -int ns_proc_out(uint8_t *wire, uint16_t *wire_len, ns_proc_context_t *ctx) -{ - knot_pkt_t *pkt = knot_pkt_new(wire, *wire_len, &ctx->mm); - - switch(ctx->state) { - case NS_PROC_FULL: ctx->state = ctx->module->out(pkt, ctx); break; - case NS_PROC_FAIL: ctx->state = ctx->module->err(pkt, ctx); break; - default: - assert(0); /* Improper use. */ - knot_pkt_free(&pkt); - return NS_PROC_NOOP; - } - - /* Accept only finished result. */ - if (ctx->state != NS_PROC_FAIL) { - *wire_len = pkt->size; - } else { - *wire_len = 0; - } - - knot_pkt_free(&pkt); - - dbg_ns("%s -> %s\n", __func__, NS_STATE_STR(ctx->state)); - return ctx->state; -} diff --git a/src/knot/nameserver/name-server.h b/src/knot/nameserver/name-server.h index 83d8f60e6..a754114bd 100644 --- a/src/knot/nameserver/name-server.h +++ b/src/knot/nameserver/name-server.h @@ -296,116 +296,6 @@ int knot_ns_tsig_required(int packet_nr); */ void knot_ns_destroy(knot_nameserver_t **nameserver); -/* ^^^ - * NG processing API below, everything upwards should be slowly moved to appropriate - * files or removed. - */ - -/*! \brief Main packet processing states. - * Each state describes the current machine processing step - * and determines readiness for next action. - */ -enum ns_proc_state { - NS_PROC_NOOP = 0, /* N/A */ - NS_PROC_MORE = 1 << 0, /* More input data. */ - NS_PROC_FULL = 1 << 1, /* Has output data. */ - NS_PROC_DONE = 1 << 2, /* Finished. */ - NS_PROC_FAIL = 1 << 3 /* Error. */ -}; - -/* Forward declarations. */ -struct ns_proc_module; - -/*! \brief Packte processing context. */ -typedef struct ns_proc_context -{ - int state; - mm_ctx_t mm; - uint16_t type; - - knot_nameserver_t *ns; - void *data; - - /* Module implementation. */ - const struct ns_proc_module *module; -} ns_proc_context_t; - -/*! \brief Packet processing module API. */ -typedef struct ns_proc_module { - int (*begin)(ns_proc_context_t *ctx, void *module_param); - int (*reset)(ns_proc_context_t *ctx); - int (*finish)(ns_proc_context_t *ctx); - int (*in)(knot_pkt_t *pkt, ns_proc_context_t *ctx); - int (*out)(knot_pkt_t *pkt, ns_proc_context_t *ctx); - int (*err)(knot_pkt_t *pkt, ns_proc_context_t *ctx); -} ns_proc_module_t; - -/*! \brief Packet signing context. - * \todo This should be later moved to TSIG files when refactoring. */ -typedef struct ns_sign_context { - knot_tsig_key_t *tsig_key; - uint8_t *tsig_buf; - uint8_t *tsig_digest; - size_t tsig_buflen; - size_t tsig_digestlen; - uint8_t tsig_runlen; - uint64_t tsig_time_signed; - size_t pkt_count; -} ns_sign_context_t; - -/*! - * \brief Initialize packet processing context. - * - * Allowed from states: NOOP - * - * \param ctx Context. - * \param module_param Parameters for given module. - * \param module Module API. - * \return (module specific state) - */ -int ns_proc_begin(ns_proc_context_t *ctx, void *module_param, const ns_proc_module_t *module); - -/*! - * \brief Reset current packet processing context. - * \param ctx Context. - * \return (module specific state) - */ -int ns_proc_reset(ns_proc_context_t *ctx); - -/*! - * \brief Finish and close packet processing context. - * - * Allowed from states: MORE, FULL, DONE, FAIL - * - * \param ctx Context. - * \return (module specific state) - */ -int ns_proc_finish(ns_proc_context_t *ctx); - -/*! - * \brief Input more data into packet processing. - * - * Allowed from states: MORE - * - * \param wire Source data. - * \param wire_len Source data length. - * \param ctx Context. - * \return (module specific state) - */ -int ns_proc_in(const uint8_t *wire, uint16_t wire_len, ns_proc_context_t *ctx); - -/*! - * \brief Write out output from packet processing. - * - * Allowed from states: FULL, FAIL - * - * \param wire Destination. - * \param wire_len Destination length. - * \param ctx Context. - * \return (module specific state) - */ -int ns_proc_out(uint8_t *wire, uint16_t *wire_len, ns_proc_context_t *ctx); - #endif /* _KNOTNAME_SERVER_H_ */ /*! @} */ diff --git a/src/knot/nameserver/nsec_proofs.c b/src/knot/nameserver/nsec_proofs.c index 134733cbb..b5e832208 100644 --- a/src/knot/nameserver/nsec_proofs.c +++ b/src/knot/nameserver/nsec_proofs.c @@ -1,7 +1,7 @@ #include <config.h> #include "knot/nameserver/nsec_proofs.h" -#include "knot/nameserver/ns_proc_query.h" +#include "knot/nameserver/process_query.h" #include "libknot/common.h" #include "libknot/rdata.h" diff --git a/src/knot/nameserver/ns_proc_query.c b/src/knot/nameserver/process_query.c similarity index 85% rename from src/knot/nameserver/ns_proc_query.c rename to src/knot/nameserver/process_query.c index 44ea9fa87..eed6dfbb6 100644 --- a/src/knot/nameserver/ns_proc_query.c +++ b/src/knot/nameserver/process_query.c @@ -2,7 +2,7 @@ #include <stdio.h> #include <urcu.h> -#include "knot/nameserver/ns_proc_query.h" +#include "knot/nameserver/process_query.h" #include "libknot/consts.h" #include "libknot/util/debug.h" #include "libknot/common.h" @@ -23,38 +23,38 @@ /* Forward decls. */ static const knot_zone_t *answer_zone_find(const knot_pkt_t *pkt, knot_zonedb_t *zonedb); -static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, ns_proc_context_t *ctx); -static int query_internet(knot_pkt_t *pkt, ns_proc_context_t *ctx); -static int query_chaos(knot_pkt_t *pkt, ns_proc_context_t *ctx); -static int ratelimit_apply(int state, knot_pkt_t *pkt, ns_proc_context_t *ctx); +static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_process_t *ctx); +static int query_internet(knot_pkt_t *pkt, knot_process_t *ctx); +static int query_chaos(knot_pkt_t *pkt, knot_process_t *ctx); +static int ratelimit_apply(int state, knot_pkt_t *pkt, knot_process_t *ctx); /*! \brief Module implementation. */ -const ns_proc_module_t _ns_proc_query = { - &ns_proc_query_begin, - &ns_proc_query_reset, - &ns_proc_query_finish, - &ns_proc_query_in, - &ns_proc_query_out, - &ns_proc_query_err +const knot_process_module_t _process_query = { + &process_query_begin, + &process_query_reset, + &process_query_finish, + &process_query_in, + &process_query_out, + &process_query_err }; /*! \brief Accessor to query-specific data. */ #define QUERY_DATA(ctx) ((struct query_data *)(ctx)->data) /*! \brief Reinitialize query data structure. */ -static void query_data_init(ns_proc_context_t *ctx, void *module_param) +static void query_data_init(knot_process_t *ctx, void *module_param) { /* Initialize persistent data. */ struct query_data *data = QUERY_DATA(ctx); memset(data, 0, sizeof(struct query_data)); data->mm = &ctx->mm; - data->param = (struct ns_proc_query_param*)module_param; + data->param = (struct process_query_param*)module_param; /* Initialize list. */ init_list(&data->wildcards); } -int ns_proc_query_begin(ns_proc_context_t *ctx, void *module_param) +int process_query_begin(knot_process_t *ctx, void *module_param) { /* Initialize context. */ assert(ctx); @@ -68,13 +68,13 @@ int ns_proc_query_begin(ns_proc_context_t *ctx, void *module_param) return NS_PROC_MORE; } -int ns_proc_query_reset(ns_proc_context_t *ctx) +int process_query_reset(knot_process_t *ctx) { assert(ctx); struct query_data *qdata = QUERY_DATA(ctx); /* Remember persistent parameters. */ - struct ns_proc_query_param *module_param = qdata->param; + struct process_query_param *module_param = qdata->param; /* Free allocated data. */ knot_pkt_free(&qdata->query); @@ -89,15 +89,15 @@ int ns_proc_query_reset(ns_proc_context_t *ctx) /* Await packet. */ return NS_PROC_MORE; } -int ns_proc_query_finish(ns_proc_context_t *ctx) +int process_query_finish(knot_process_t *ctx) { - ns_proc_query_reset(ctx); + process_query_reset(ctx); ctx->mm.free(ctx->data); ctx->data = NULL; return NS_PROC_NOOP; } -int ns_proc_query_in(knot_pkt_t *pkt, ns_proc_context_t *ctx) +int process_query_in(knot_pkt_t *pkt, knot_process_t *ctx) { assert(pkt && ctx); struct query_data *qdata = QUERY_DATA(ctx); @@ -122,7 +122,7 @@ int ns_proc_query_in(knot_pkt_t *pkt, ns_proc_context_t *ctx) return NS_PROC_FULL; } -int ns_proc_query_out(knot_pkt_t *pkt, ns_proc_context_t *ctx) +int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx) { assert(pkt && ctx); struct query_data *qdata = QUERY_DATA(ctx); @@ -178,7 +178,7 @@ int ns_proc_query_out(knot_pkt_t *pkt, ns_proc_context_t *ctx) /* Transaction security (if applicable). */ if (next_state == NS_PROC_DONE || next_state == NS_PROC_FULL) { - if (ns_proc_query_sign_response(pkt, qdata) != KNOT_EOK) { + if (process_query_sign_response(pkt, qdata) != KNOT_EOK) { next_state = NS_PROC_FAIL; } } @@ -192,7 +192,7 @@ finish: return next_state; } -int ns_proc_query_err(knot_pkt_t *pkt, ns_proc_context_t *ctx) +int process_query_err(knot_pkt_t *pkt, knot_process_t *ctx) { assert(pkt && ctx); struct query_data *qdata = QUERY_DATA(ctx); @@ -214,14 +214,14 @@ int ns_proc_query_err(knot_pkt_t *pkt, ns_proc_context_t *ctx) knot_wire_set_rcode(pkt->wire, qdata->rcode); /* Transaction security (if applicable). */ - if (ns_proc_query_sign_response(pkt, qdata) != KNOT_EOK) { + if (process_query_sign_response(pkt, qdata) != KNOT_EOK) { return NS_PROC_FAIL; } return NS_PROC_DONE; } -bool ns_proc_query_acl_check(acl_t *acl, struct query_data *qdata) +bool process_query_acl_check(acl_t *acl, struct query_data *qdata) { knot_pkt_t *query = qdata->query; const sockaddr_t *query_source = &qdata->param->query_source; @@ -253,10 +253,10 @@ bool ns_proc_query_acl_check(acl_t *acl, struct query_data *qdata) return true; } -int ns_proc_query_verify(struct query_data *qdata) +int process_query_verify(struct query_data *qdata) { knot_pkt_t *query = qdata->query; - ns_sign_context_t *ctx = &qdata->sign; + knot_sign_context_t *ctx = &qdata->sign; /* NOKEY => no verification. */ if (query->tsig_rr == NULL) { @@ -303,11 +303,11 @@ int ns_proc_query_verify(struct query_data *qdata) return ret; } -int ns_proc_query_sign_response(knot_pkt_t *pkt, struct query_data *qdata) +int process_query_sign_response(knot_pkt_t *pkt, struct query_data *qdata) { int ret = KNOT_EOK; knot_pkt_t *query = qdata->query; - ns_sign_context_t *ctx = &qdata->sign; + knot_sign_context_t *ctx = &qdata->sign; /* KEY provided and verified TSIG or BADTIME allows signing. */ if (ctx->tsig_key != NULL && knot_tsig_can_sign(qdata->rcode_tsig)) { @@ -358,9 +358,10 @@ fail: /*! * \brief Create a response for a given query in the INTERNET class. */ -static int query_internet(knot_pkt_t *pkt, ns_proc_context_t *ctx) +static int query_internet(knot_pkt_t *pkt, knot_process_t *ctx) { struct query_data *data = QUERY_DATA(ctx); + knot_nameserver_t *ns = data->param->ns; int next_state = NS_PROC_FAIL; dbg_ns("%s(%p, %p, pkt_type=%u)\n", __func__, pkt, ctx, data->packet_type); @@ -369,16 +370,16 @@ static int query_internet(knot_pkt_t *pkt, ns_proc_context_t *ctx) next_state = internet_answer(pkt, data); break; case KNOT_QUERY_NOTIFY: - next_state = internet_notify(pkt, ctx->ns, data); + next_state = internet_notify(pkt, ns, data); break; case KNOT_QUERY_AXFR: - next_state = axfr_answer(pkt, ctx->ns, data); + next_state = axfr_answer(pkt, ns, data); break; case KNOT_QUERY_IXFR: - next_state = ixfr_answer(pkt, ctx->ns, data); + next_state = ixfr_answer(pkt, ns, data); break; case KNOT_QUERY_UPDATE: - next_state = update_answer(pkt, ctx->ns, data); + next_state = update_answer(pkt, ns, data); break; default: /* Nothing else is supported. */ @@ -393,11 +394,11 @@ static int query_internet(knot_pkt_t *pkt, ns_proc_context_t *ctx) /*! * \brief Apply rate limit. */ -static int ratelimit_apply(int state, knot_pkt_t *pkt, ns_proc_context_t *ctx) +static int ratelimit_apply(int state, knot_pkt_t *pkt, knot_process_t *ctx) { /* Check if rate limiting applies. */ struct query_data *qdata = QUERY_DATA(ctx); - server_t *server = (server_t *)ctx->ns->data; + server_t *server = (server_t *)qdata->param->ns->data; if (server->rrl == NULL) { return state; } @@ -417,7 +418,7 @@ static int ratelimit_apply(int state, knot_pkt_t *pkt, ns_proc_context_t *ctx) /* Now it is slip or drop. */ if (rrl_slip_roll(conf()->rrl_slip)) { /* Answer slips. */ - if (ns_proc_query_err(pkt, ctx) != KNOT_EOK) { + if (process_query_err(pkt, ctx) != KNOT_EOK) { return NS_PROC_FAIL; } knot_wire_set_tc(pkt->wire); @@ -432,7 +433,7 @@ static int ratelimit_apply(int state, knot_pkt_t *pkt, ns_proc_context_t *ctx) /*! * \brief Create a response for a given query in the CHAOS class. */ -static int query_chaos(knot_pkt_t *pkt, ns_proc_context_t *ctx) +static int query_chaos(knot_pkt_t *pkt, knot_process_t *ctx) { dbg_ns("%s(%p, %p)\n", __func__, pkt, ctx); struct query_data *data = QUERY_DATA(ctx); @@ -443,7 +444,7 @@ static int query_chaos(knot_pkt_t *pkt, ns_proc_context_t *ctx) return NS_PROC_FAIL; } - data->rcode = knot_chaos_answer(pkt, ctx->ns); + data->rcode = knot_chaos_answer(pkt, data->param->ns); if (data->rcode != KNOT_RCODE_NOERROR) { dbg_ns("%s: failed with RCODE=%d\n", __func__, data->rcode); return NS_PROC_FAIL; @@ -487,7 +488,7 @@ static const knot_zone_t *answer_zone_find(const knot_pkt_t *pkt, knot_zonedb_t } /*! \brief Initialize response, sizes and find zone from which we're going to answer. */ -static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, ns_proc_context_t *ctx) +static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_process_t *ctx) { int ret = knot_pkt_init_response(resp, query); if (ret != KNOT_EOK) { @@ -499,6 +500,7 @@ static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, ns_proc_con * Already checked for absence of compression and length. */ struct query_data *qdata = QUERY_DATA(ctx); + knot_nameserver_t *ns = qdata->param->ns; const knot_dname_t *qname = knot_pkt_qname(query); memcpy(qdata->orig_qname, qname, query->qname_size); ret = knot_dname_to_lower((knot_dname_t *)qname); @@ -508,7 +510,7 @@ static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, ns_proc_con } /* Find zone for QNAME. */ - qdata->zone = answer_zone_find(query, ctx->ns->zone_db); + qdata->zone = answer_zone_find(query, ns->zone_db); /* Update maximal answer size. */ if (qdata->param->proc_flags & NS_QUERY_LIMIT_SIZE) { @@ -519,7 +521,7 @@ static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, ns_proc_con if (!knot_pkt_have_edns(query)) { return KNOT_EOK; } - ret = knot_pkt_add_opt(resp, ctx->ns->opt_rr, knot_pkt_have_nsid(query)); + ret = knot_pkt_add_opt(resp, ns->opt_rr, knot_pkt_have_nsid(query)); if (ret != KNOT_EOK) { dbg_ns("%s: can't add OPT RR (%d)\n", __func__, ret); return ret; diff --git a/src/knot/nameserver/ns_proc_query.h b/src/knot/nameserver/process_query.h similarity index 82% rename from src/knot/nameserver/ns_proc_query.h rename to src/knot/nameserver/process_query.h index 5aad3a36e..2ab422923 100644 --- a/src/knot/nameserver/ns_proc_query.h +++ b/src/knot/nameserver/process_query.h @@ -1,5 +1,5 @@ /*! - * \file ns_proc_query.h + * \file process_query.h * * \author Marek Vavrusa <marek.vavrusa@nic.cz> * @@ -24,15 +24,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _KNOT_NS_PROC_QUERY_H_ -#define _KNOT_NS_PROC_QUERY_H_ +#ifndef _PROCESS_QUERY_H_ +#define _PROCESS_QUERY_H_ +#include "libknot/processing/process.h" #include "knot/nameserver/name-server.h" #include "common/acl.h" /* Query processing module implementation. */ -extern const ns_proc_module_t _ns_proc_query; -#define NS_PROC_QUERY (&_ns_proc_query) +extern const knot_process_module_t _process_query; +#define NS_PROC_QUERY (&_process_query) #define NS_PROC_QUERY_ID 1 /*! \brief Query processing logging common base. */ @@ -56,7 +57,7 @@ extern const ns_proc_module_t _ns_proc_query; NS_PROC_LOG(severity, qdata, what " of '%s' to '%s:%d': ", msg) /* Query processing specific flags. */ -enum ns_proc_query_flag { +enum process_query_flag { NS_QUERY_NO_AXFR = 1 << 0, /* Don't process AXFR */ NS_QUERY_NO_IXFR = 1 << 1, /* Don't process IXFR */ NS_QUERY_LIMIT_ANY = 1 << 2, /* Limit ANY QTYPE (respond with TC=1) */ @@ -65,9 +66,10 @@ enum ns_proc_query_flag { }; /* Module load parameters. */ -struct ns_proc_query_param { +struct process_query_param { uint16_t proc_flags; sockaddr_t query_source; + knot_nameserver_t *ns; }; /*! \brief Query processing intermediate data. */ @@ -89,10 +91,10 @@ struct query_data { /* Extensions. */ void *ext; void (*ext_cleanup)(struct query_data*); /*!< Extensions cleanup callback. */ - ns_sign_context_t sign; /*!< Signing context. */ + knot_sign_context_t sign; /*!< Signing context. */ /* Everything below should be kept on reset. */ - struct ns_proc_query_param *param; /*!< Module parameters. */ + struct process_query_param *param; /*!< Module parameters. */ mm_ctx_t *mm; /*!< Memory context. */ }; @@ -110,7 +112,7 @@ struct wildcard_hit { * \param module_param * \return MORE (awaits query) */ -int ns_proc_query_begin(ns_proc_context_t *ctx, void *module_param); +int process_query_begin(knot_process_t *ctx, void *module_param); /*! * \brief Reset query processing context. @@ -118,7 +120,7 @@ int ns_proc_query_begin(ns_proc_context_t *ctx, void *module_param); * \param ctx * \return MORE (awaits next query) */ -int ns_proc_query_reset(ns_proc_context_t *ctx); +int process_query_reset(knot_process_t *ctx); /*! * \brief Finish and close current query processing. @@ -126,7 +128,7 @@ int ns_proc_query_reset(ns_proc_context_t *ctx); * \param ctx * \return NOOP (context will be inoperable further on) */ -int ns_proc_query_finish(ns_proc_context_t *ctx); +int process_query_finish(knot_process_t *ctx); /*! * \brief Put query into query processing context. @@ -136,7 +138,7 @@ int ns_proc_query_finish(ns_proc_context_t *ctx); * \retval NOOP (unsupported query) * \retval FULL (ready to write answer) */ -int ns_proc_query_in(knot_pkt_t *pkt, ns_proc_context_t *ctx); +int process_query_in(knot_pkt_t *pkt, knot_process_t *ctx); /*! * \brief Make query response. @@ -147,7 +149,7 @@ int ns_proc_query_in(knot_pkt_t *pkt, ns_proc_context_t *ctx); * \retval FULL (partial response, send it and call again) * \retval FAIL (failure) */ -int ns_proc_query_out(knot_pkt_t *pkt, ns_proc_context_t *ctx); +int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx); /*! * \brief Make an error response. @@ -157,7 +159,7 @@ int ns_proc_query_out(knot_pkt_t *pkt, ns_proc_context_t *ctx); * \retval DONE (finished response) * \retval FAIL (failure) */ -int ns_proc_query_err(knot_pkt_t *pkt, ns_proc_context_t *ctx); +int process_query_err(knot_pkt_t *pkt, knot_process_t *ctx); /*! * \brief Check current query against ACL. @@ -166,7 +168,7 @@ int ns_proc_query_err(knot_pkt_t *pkt, ns_proc_context_t *ctx); * \param qdata * \return true if accepted, false if denied. */ -bool ns_proc_query_acl_check(acl_t *acl, struct query_data *qdata); +bool process_query_acl_check(acl_t *acl, struct query_data *qdata); /*! * \brief Verify current query transaction security and update query data. @@ -178,7 +180,7 @@ bool ns_proc_query_acl_check(acl_t *acl, struct query_data *qdata); * \retval KNOT_TSIG_EBADTIME * \retval (other generic errors) */ -int ns_proc_query_verify(struct query_data *qdata); +int process_query_verify(struct query_data *qdata); /*! * \brief Sign query response if applicable. @@ -188,8 +190,8 @@ int ns_proc_query_verify(struct query_data *qdata); * \retval KNOT_EOK * \retval (other generic errors) */ -int ns_proc_query_sign_response(knot_pkt_t *pkt, struct query_data *qdata); +int process_query_sign_response(knot_pkt_t *pkt, struct query_data *qdata); -#endif /* _KNOT_NS_PROC_QUERY_H_ */ +#endif /* _PROCESS_QUERY_H_ */ /*! @} */ diff --git a/src/knot/nameserver/update.c b/src/knot/nameserver/update.c index f56927c7d..b8b3e6e29 100644 --- a/src/knot/nameserver/update.c +++ b/src/knot/nameserver/update.c @@ -2,7 +2,7 @@ #include "knot/nameserver/update.h" #include "knot/nameserver/internet.h" -#include "knot/nameserver/ns_proc_query.h" +#include "knot/nameserver/process_query.h" #include "knot/nameserver/name-server.h" #include "libknot/util/debug.h" #include "knot/dnssec/zone-events.h" diff --git a/src/knot/server/notify.c b/src/knot/server/notify.c index 1b16f4a8a..afd23506c 100644 --- a/src/knot/server/notify.c +++ b/src/knot/server/notify.c @@ -35,7 +35,7 @@ #include "libknot/rdata.h" #include "knot/nameserver/internet.h" #include "libknot/util/debug.h" -#include "knot/nameserver/ns_proc_query.h" +#include "knot/nameserver/process_query.h" #include "libknot/dnssec/random.h" /*----------------------------------------------------------------------------*/ diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c index a86c79d38..336396dbf 100644 --- a/src/knot/server/tcp-handler.c +++ b/src/knot/server/tcp-handler.c @@ -41,13 +41,14 @@ #include "knot/server/zones.h" #include "knot/nameserver/name-server.h" #include "libknot/packet/wire.h" -#include "knot/nameserver/ns_proc_query.h" +#include "knot/nameserver/process_query.h" #include "libknot/dnssec/crypto.h" #include "libknot/dnssec/random.h" /*! \brief TCP context data. */ -typedef struct tcp_context_t { - ns_proc_context_t query_ctx; /*!< Query processing context. */ +typedef struct tcp_context { + knot_process_t query_ctx; /*!< Query processing context. */ + knot_nameserver_t *ns; /*!< Name server structure. */ struct iovec iov[2]; /*!< TX/RX buffers. */ unsigned client_threshold; /*!< Index of first TCP client. */ timev_t last_poll_time; /*!< Time of the last socket poll. */ @@ -104,12 +105,13 @@ static enum fdset_sweep_state tcp_sweep(fdset_t *set, int i, void *data) /*! * \brief TCP event handler function. */ -static int tcp_handle(ns_proc_context_t *query_ctx, int fd, +static int tcp_handle(tcp_context_t *tcp, int fd, struct iovec *rx, struct iovec *tx) { /* Create query processing parameter. */ - struct ns_proc_query_param param = {0}; + struct process_query_param param = {0}; sockaddr_prep(¶m.query_source); + param.ns = tcp->ns; rx->iov_len = KNOT_WIRE_MAX_PKTSIZE; tx->iov_len = KNOT_WIRE_MAX_PKTSIZE; @@ -133,16 +135,16 @@ static int tcp_handle(ns_proc_context_t *query_ctx, int fd, } /* Create query processing context. */ - ns_proc_begin(query_ctx, ¶m, NS_PROC_QUERY); + knot_process_begin(&tcp->query_ctx, ¶m, NS_PROC_QUERY); /* Input packet. */ - int state = ns_proc_in(rx->iov_base, rx->iov_len, query_ctx); + int state = knot_process_in(rx->iov_base, rx->iov_len, &tcp->query_ctx); /* Resolve until NOOP or finished. */ ret = KNOT_EOK; while (state & (NS_PROC_FULL|NS_PROC_FAIL)) { uint16_t tx_len = tx->iov_len; - state = ns_proc_out(tx->iov_base, &tx_len, query_ctx); + state = knot_process_out(tx->iov_base, &tx_len, &tcp->query_ctx); /* If it has response, send it. */ if (tx_len > 0) { @@ -154,7 +156,7 @@ static int tcp_handle(ns_proc_context_t *query_ctx, int fd, } /* Reset after processing. */ - ns_proc_finish(query_ctx); + knot_process_finish(&tcp->query_ctx); return ret; } @@ -298,7 +300,7 @@ static int tcp_event_accept(tcp_context_t *tcp, unsigned i) static int tcp_event_serve(tcp_context_t *tcp, unsigned i) { int fd = tcp->set.pfd[i].fd; - int ret = tcp_handle(&tcp->query_ctx, fd, &tcp->iov[0], &tcp->iov[1]); + int ret = tcp_handle(tcp, fd, &tcp->iov[0], &tcp->iov[1]); /* Flush per-query memory. */ mp_flush(tcp->query_ctx.mm.ctx); @@ -375,7 +377,7 @@ int tcp_master(dthread_t *thread) memset(&tcp, 0, sizeof(tcp_context_t)); /* Create TCP answering context. */ - tcp.query_ctx.ns = handler->server->nameserver; + tcp.ns = handler->server->nameserver; /* Create big enough memory cushion. */ mm_ctx_mempool(&tcp.query_ctx.mm, 4 * sizeof(knot_pkt_t)); diff --git a/src/knot/server/udp-handler.c b/src/knot/server/udp-handler.c index baa20faa0..de9dbe233 100644 --- a/src/knot/server/udp-handler.c +++ b/src/knot/server/udp-handler.c @@ -51,6 +51,7 @@ #include "knot/server/zones.h" #include "knot/server/notify.h" #include "libknot/dnssec/crypto.h" +#include "libknot/processing/process.h" /* Buffer identifiers. */ enum { @@ -59,6 +60,12 @@ enum { NBUFS = 2 }; +/*! \brief UDP context data. */ +typedef struct udp_context { + knot_process_t query_ctx; /*!< Query processing context. */ + knot_nameserver_t *ns; /*!< Name server structure. */ +} udp_context_t; + /* FD_COPY macro compat. */ #ifndef FD_COPY #define FD_COPY(src, dest) memcpy((dest), (src), sizeof(fd_set)) @@ -73,7 +80,7 @@ enum { /* Next-gen packet processing API. */ #define PACKET_NG #ifdef PACKET_NG -#include "knot/nameserver/ns_proc_query.h" +#include "knot/nameserver/process_query.h" #endif /* PPS measurement */ @@ -105,7 +112,7 @@ static inline void udp_pps_begin() {} static inline void udp_pps_sample(unsigned n, unsigned thr_id) {} #endif -int udp_handle(ns_proc_context_t *query_ctx, int fd, sockaddr_t *addr, +int udp_handle(udp_context_t *udp, int fd, sockaddr_t *addr, struct iovec *rx, struct iovec *tx) { #ifdef DEBUG_ENABLE_BRIEF @@ -117,34 +124,35 @@ int udp_handle(ns_proc_context_t *query_ctx, int fd, sockaddr_t *addr, #endif /* Create query processing parameter. */ - struct ns_proc_query_param param = {0}; + struct process_query_param param = {0}; sockaddr_copy(¶m.query_source, addr); param.proc_flags = NS_QUERY_NO_AXFR|NS_QUERY_NO_IXFR; /* No transfers. */ param.proc_flags |= NS_QUERY_LIMIT_SIZE; /* Enforce UDP packet size limit. */ param.proc_flags |= NS_QUERY_LIMIT_ANY; /* Limit ANY over UDP (depends on zone as well). */ + param.ns = NULL; /* Rate limit is applied? */ - server_t *server = (server_t *)query_ctx->ns->data; + server_t *server = (server_t *)udp->ns->data; if (knot_unlikely(server->rrl != NULL) && server->rrl->rate > 0) { param.proc_flags |= NS_QUERY_LIMIT_RATE; } /* Create query processing context. */ - ns_proc_begin(query_ctx, ¶m, NS_PROC_QUERY); + knot_process_begin(&udp->query_ctx, ¶m, NS_PROC_QUERY); /* Input packet. */ - int state = ns_proc_in(rx->iov_base, rx->iov_len, query_ctx); + int state = knot_process_in(rx->iov_base, rx->iov_len, &udp->query_ctx); /* Process answer. */ uint16_t tx_len = tx->iov_len; if (state == NS_PROC_FULL) { - state = ns_proc_out(tx->iov_base, &tx_len, query_ctx); + state = knot_process_out(tx->iov_base, &tx_len, &udp->query_ctx); } /* Process error response (if failed). */ if (state == NS_PROC_FAIL) { tx_len = tx->iov_len; /* Reset size. */ - state = ns_proc_out(tx->iov_base, &tx_len, query_ctx); + state = knot_process_out(tx->iov_base, &tx_len, &udp->query_ctx); } /* Send response only if finished successfuly. */ @@ -155,7 +163,7 @@ int udp_handle(ns_proc_context_t *query_ctx, int fd, sockaddr_t *addr, } /* Reset context. */ - ns_proc_finish(query_ctx); + knot_process_finish(&udp->query_ctx); return KNOT_EOK; } @@ -172,7 +180,7 @@ int udp_handle(ns_proc_context_t *query_ctx, int fd, sockaddr_t *addr, static void* (*_udp_init)(void) = 0; static int (*_udp_deinit)(void *) = 0; static int (*_udp_recv)(int, void *) = 0; -static int (*_udp_handle)(ns_proc_context_t *, void *) = 0; +static int (*_udp_handle)(udp_context_t *, void *) = 0; static int (*_udp_send)(void *) = 0; /* UDP recvfrom() request struct. */ @@ -227,7 +235,7 @@ static int udp_recvfrom_recv(int fd, void *d) return 0; } -static int udp_recvfrom_handle(ns_proc_context_t *ctx, void *d) +static int udp_recvfrom_handle(udp_context_t *ctx, void *d) { struct udp_recvfrom *rq = (struct udp_recvfrom *)d; @@ -378,7 +386,7 @@ static int udp_recvmmsg_recv(int fd, void *d) return n; } -static int udp_recvmmsg_handle(ns_proc_context_t *ctx, void *d) +static int udp_recvmmsg_handle(udp_context_t *ctx, void *d) { struct udp_recvmmsg *rq = (struct udp_recvmmsg *)d; @@ -482,12 +490,12 @@ int udp_master(dthread_t *thread) ifacelist_t *ref = NULL; /* Create UDP answering context. */ - ns_proc_context_t query_ctx; - memset(&query_ctx, 0, sizeof(query_ctx)); - query_ctx.ns = handler->server->nameserver; + udp_context_t udp; + memset(&udp, 0, sizeof(udp_context_t)); + udp.ns = handler->server->nameserver; /* Create big enough memory cushion. */ - mm_ctx_mempool(&query_ctx.mm, 4 * sizeof(knot_pkt_t)); + mm_ctx_mempool(&udp.query_ctx.mm, 4 * sizeof(knot_pkt_t)); /* Chose select as epoll/kqueue has larger overhead for a * single or handful of sockets. */ @@ -540,9 +548,9 @@ int udp_master(dthread_t *thread) for (unsigned fd = minfd; fd <= maxfd; ++fd) { if (FD_ISSET(fd, &rfds)) { while ((rcvd = _udp_recv(fd, rq)) > 0) { - _udp_handle(&query_ctx, rq); + _udp_handle(&udp, rq); /* Flush allocated memory. */ - mp_flush(query_ctx.mm.ctx); + mp_flush(udp.query_ctx.mm.ctx); _udp_send(rq); udp_pps_sample(rcvd, thr_id); } @@ -552,7 +560,7 @@ int udp_master(dthread_t *thread) _udp_deinit(rq); ref_release((ref_t *)ref); - mp_delete(query_ctx.mm.ctx); + mp_delete(udp.query_ctx.mm.ctx); return KNOT_EOK; } diff --git a/src/libknot/processing/process.c b/src/libknot/processing/process.c new file mode 100644 index 000000000..91abc3a1b --- /dev/null +++ b/src/libknot/processing/process.c @@ -0,0 +1,119 @@ +/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <assert.h> + +#include "libknot/processing/process.h" +#include "libknot/util/debug.h" + +/* State -> string translation table. */ +#ifdef KNOT_NS_DEBUG +#define PROCESSING_STATE_STR(x) _state_table[x] +static const char* _state_table[] = { + [NS_PROC_NOOP] = "NOOP", + [NS_PROC_MORE] = "MORE", + [NS_PROC_FULL] = "FULL", + [NS_PROC_DONE] = "DONE", + [NS_PROC_FAIL] = "FAIL" +}; +#endif /* KNOT_NS_DEBUG */ + +int knot_process_begin(knot_process_t *ctx, void *module_param, const knot_process_module_t *module) +{ + /* Only in inoperable state. */ + if (ctx->state != NS_PROC_NOOP) { + return NS_PROC_NOOP; + } + +#ifdef KNOT_NS_DEBUG + /* Check module API. */ + assert(module->begin); + assert(module->in); + assert(module->out); + assert(module->err); + assert(module->reset); + assert(module->finish); +#endif /* KNOT_NS_DEBUG */ + + ctx->module = module; + ctx->state = module->begin(ctx, module_param); + + dbg_ns("%s -> %s\n", __func__, PROCESSING_STATE_STR(ctx->state)); + return ctx->state; +} + +int knot_process_reset(knot_process_t *ctx) +{ + ctx->state = ctx->module->reset(ctx); + dbg_ns("%s -> %s\n", __func__, PROCESSING_STATE_STR(ctx->state)); + return ctx->state; +} + +int knot_process_finish(knot_process_t *ctx) +{ + /* Only in operable state. */ + if (ctx->state == NS_PROC_NOOP) { + return NS_PROC_NOOP; + } + + ctx->state = ctx->module->finish(ctx); + dbg_ns("%s -> %s\n", __func__, PROCESSING_STATE_STR(ctx->state)); + return ctx->state; +} + +int knot_process_in(const uint8_t *wire, uint16_t wire_len, knot_process_t *ctx) +{ + /* Only if expecting data. */ + if (ctx->state != NS_PROC_MORE) { + return NS_PROC_NOOP; + } + + knot_pkt_t *pkt = knot_pkt_new((uint8_t *)wire, wire_len, &ctx->mm); + knot_pkt_parse(pkt, 0); + + ctx->state = ctx->module->in(pkt, ctx); + dbg_ns("%s -> %s\n", __func__, PROCESSING_STATE_STR(ctx->state)); + return ctx->state; +} + +int knot_process_out(uint8_t *wire, uint16_t *wire_len, knot_process_t *ctx) +{ + knot_pkt_t *pkt = knot_pkt_new(wire, *wire_len, &ctx->mm); + + switch(ctx->state) { + case NS_PROC_FULL: ctx->state = ctx->module->out(pkt, ctx); break; + case NS_PROC_FAIL: ctx->state = ctx->module->err(pkt, ctx); break; + default: + assert(0); /* Improper use. */ + knot_pkt_free(&pkt); + return NS_PROC_NOOP; + } + + /* Accept only finished result. */ + if (ctx->state != NS_PROC_FAIL) { + *wire_len = pkt->size; + } else { + *wire_len = 0; + } + + knot_pkt_free(&pkt); + + dbg_ns("%s -> %s\n", __func__, PROCESSING_STATE_STR(ctx->state)); + return ctx->state; +} + +#undef PROCESSING_STATE_STR diff --git a/src/libknot/processing/process.h b/src/libknot/processing/process.h new file mode 100644 index 000000000..8be678a11 --- /dev/null +++ b/src/libknot/processing/process.h @@ -0,0 +1,127 @@ +/*! + * \file process.h + * + * \author Marek Vavrusa <marek.vavrusa@nic.cz> + * + * \addtogroup query_processing + * @{ + */ +/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _KNOT_PROCESS_H +#define _KNOT_PROCESS_H + +#include <stdint.h> + +#include "common/mempattern.h" +#include "libknot/consts.h" +#include "libknot/tsig.h" +#include "libknot/packet/pkt.h" + +/*! \brief Main packet processing states. + * Each state describes the current machine processing step + * and determines readiness for next action. + */ +enum knot_process_state { + NS_PROC_NOOP = 0, /* N/A */ + NS_PROC_MORE = 1 << 0, /* More input data. */ + NS_PROC_FULL = 1 << 1, /* Has output data. */ + NS_PROC_DONE = 1 << 2, /* Finished. */ + NS_PROC_FAIL = 1 << 3 /* Error. */ +}; + +/* Forward declarations. */ +struct knot_process_module; + +/*! \brief Packet processing context. */ +typedef struct knot_process_context +{ + uint16_t state; /* Bitmap of enum knot_process_state. */ + uint16_t type; /* Module identifier. */ + mm_ctx_t mm; /* Processing memory context. */ + + /* Module specific. */ + void *data; + const struct knot_process_module *module; +} knot_process_t; + +/*! \brief Packet processing module API. */ +typedef struct knot_process_module { + int (*begin)(knot_process_t *ctx, void *module_param); + int (*reset)(knot_process_t *ctx); + int (*finish)(knot_process_t *ctx); + int (*in)(knot_pkt_t *pkt, knot_process_t *ctx); + int (*out)(knot_pkt_t *pkt, knot_process_t *ctx); + int (*err)(knot_pkt_t *pkt, knot_process_t *ctx); +} knot_process_module_t; + +/*! + * \brief Initialize packet processing context. + * + * Allowed from states: NOOP + * + * \param ctx Context. + * \param module_param Parameters for given module. + * \param module Module API. + * \return (module specific state) + */ +int knot_process_begin(knot_process_t *ctx, void *module_param, const knot_process_module_t *module); + +/*! + * \brief Reset current packet processing context. + * \param ctx Context. + * \return (module specific state) + */ +int knot_process_reset(knot_process_t *ctx); + +/*! + * \brief Finish and close packet processing context. + * + * Allowed from states: MORE, FULL, DONE, FAIL + * + * \param ctx Context. + * \return (module specific state) + */ +int knot_process_finish(knot_process_t *ctx); + +/*! + * \brief Input more data into packet processing. + * + * Allowed from states: MORE + * + * \param wire Source data. + * \param wire_len Source data length. + * \param ctx Context. + * \return (module specific state) + */ +int knot_process_in(const uint8_t *wire, uint16_t wire_len, knot_process_t *ctx); + +/*! + * \brief Write out output from packet processing. + * + * Allowed from states: FULL, FAIL + * + * \param wire Destination. + * \param wire_len Destination length. + * \param ctx Context. + * \return (module specific state) + */ +int knot_process_out(uint8_t *wire, uint16_t *wire_len, knot_process_t *ctx); + +#endif /* _KNOT_PROCESS_H */ + +/*! @} */ diff --git a/src/libknot/tsig.h b/src/libknot/tsig.h index 580370080..bd9d364bb 100644 --- a/src/libknot/tsig.h +++ b/src/libknot/tsig.h @@ -54,6 +54,19 @@ enum tsig_consts { + 6 // time signed }; +/*! \brief Packet signing context. + * \todo This should be later moved to TSIG files when refactoring. */ +typedef struct knot_sign_context { + knot_tsig_key_t *tsig_key; + uint8_t *tsig_buf; + uint8_t *tsig_digest; + size_t tsig_buflen; + size_t tsig_digestlen; + uint8_t tsig_runlen; + uint64_t tsig_time_signed; + size_t pkt_count; +} knot_sign_context_t; + /*! * \brief Create TSIG RDATA. * diff --git a/tests/Makefile.inc b/tests/Makefile.inc index 83a9cbdec..4bf02b55b 100644 --- a/tests/Makefile.inc +++ b/tests/Makefile.inc @@ -25,7 +25,7 @@ check_PROGRAMS = \ tests/dnssec_zone_nsec \ tests/rrset \ tests/pkt \ - tests/ns + tests/process_query check_LIBRARIES = tests/tap/libtap.a diff --git a/tests/TESTS b/tests/TESTS index dbfec77b0..19f80ce5e 100644 --- a/tests/TESTS +++ b/tests/TESTS @@ -22,4 +22,4 @@ dnssec_sign dnssec_zone_nsec rrset pkt -ns +process_query diff --git a/tests/ns.c b/tests/process_query.c similarity index 87% rename from tests/ns.c rename to tests/process_query.c index 776509455..267719a4c 100644 --- a/tests/ns.c +++ b/tests/process_query.c @@ -21,7 +21,7 @@ #include "common/descriptor.h" #include "libknot/packet/wire.h" #include "knot/nameserver/name-server.h" -#include "knot/nameserver/ns_proc_query.h" +#include "knot/nameserver/process_query.h" #include "knot/server/zones.h" /* SOA RDATA. */ @@ -81,7 +81,7 @@ static void answer_sanity_check(const uint8_t *query, } /* Resolve query and check answer for sanity (2 TAP tests). */ -static void exec_query(ns_proc_context_t *query_ctx, const char *name, +static void exec_query(knot_process_t *query_ctx, const char *name, const uint8_t *query, uint16_t query_len, uint8_t expected_rcode) { @@ -89,16 +89,16 @@ static void exec_query(ns_proc_context_t *query_ctx, const char *name, uint8_t answer[KNOT_WIRE_MAX_PKTSIZE]; /* Input packet. */ - int state = ns_proc_in(query, query_len, query_ctx); + int state = knot_process_in(query, query_len, query_ctx); ok(state & (NS_PROC_FULL|NS_PROC_FAIL), "ns: process %s query", name); /* Create answer. */ - state = ns_proc_out(answer, &answer_len, query_ctx); + state = knot_process_out(answer, &answer_len, query_ctx); if (state & NS_PROC_FAIL) { /* Allow 1 generic error response. */ answer_len = KNOT_WIRE_MAX_PKTSIZE; - state = ns_proc_out(answer, &answer_len, query_ctx); + state = knot_process_out(answer, &answer_len, query_ctx); } ok(state == NS_PROC_DONE, "ns: answer %s query", name); @@ -119,8 +119,8 @@ int main(int argc, char *argv[]) plan(8*6 + 3); /* exec_query = 6 TAP tests */ /* Create processing context. */ - ns_proc_context_t query_ctx; - memset(&query_ctx, 0, sizeof(ns_proc_context_t)); + knot_process_t query_ctx; + memset(&query_ctx, 0, sizeof(knot_process_t)); mm_ctx_mempool(&query_ctx.mm, sizeof(knot_pkt_t)); /* Create name server. */ @@ -130,7 +130,6 @@ int main(int argc, char *argv[]) knot_edns_set_payload(ns->opt_rr, 4096); ns->identity = "bogus.ns"; ns->version = "0.11"; - query_ctx.ns = ns; /* Insert root zone. */ create_root_zone(ns, &query_ctx.mm); @@ -143,50 +142,51 @@ int main(int argc, char *argv[]) knot_pkt_t *query = knot_pkt_new(query_wire, query_len, &query_ctx.mm); /* Create query processing parameter. */ - struct ns_proc_query_param param = {0}; + struct process_query_param param = {0}; sockaddr_set(¶m.query_source, AF_INET, "127.0.0.1", 53); + param.ns = ns; /* Query processor (CH zone) */ - state = ns_proc_begin(&query_ctx, ¶m, NS_PROC_QUERY); + state = knot_process_begin(&query_ctx, ¶m, NS_PROC_QUERY); const uint8_t chaos_dname[] = "\2""id""\6""server"; /* id.server */ knot_pkt_clear(query); knot_pkt_put_question(query, chaos_dname, KNOT_CLASS_CH, KNOT_RRTYPE_TXT); exec_query(&query_ctx, "CH TXT", query->wire, query->size, KNOT_RCODE_NOERROR); /* Query processor (valid input). */ - state = ns_proc_reset(&query_ctx); + state = knot_process_reset(&query_ctx); knot_pkt_clear(query); knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_SOA); exec_query(&query_ctx, "IN/root", query->wire, query->size, KNOT_RCODE_NOERROR); /* Query processor (-1 bytes, not enough data). */ - state = ns_proc_reset(&query_ctx); + state = knot_process_reset(&query_ctx); exec_query(&query_ctx, "IN/few-data", query->wire, query->size - 1, KNOT_RCODE_FORMERR); /* Query processor (+1 bytes trailing). */ - state = ns_proc_reset(&query_ctx); + state = knot_process_reset(&query_ctx); query->wire[query->size] = '\1'; /* Initialize the "garbage" value. */ exec_query(&query_ctx, "IN/trail-garbage", query->wire, query->size + 1, KNOT_RCODE_FORMERR); /* Forge NOTIFY query from SOA query. */ - state = ns_proc_reset(&query_ctx); + state = knot_process_reset(&query_ctx); knot_wire_set_opcode(query->wire, KNOT_OPCODE_NOTIFY); exec_query(&query_ctx, "IN/notify", query->wire, query->size, KNOT_RCODE_NOTAUTH); /* Forge AXFR query. */ - ns_proc_reset(&query_ctx); + knot_process_reset(&query_ctx); knot_pkt_clear(query); knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_AXFR); exec_query(&query_ctx, "IN/axfr", query->wire, query->size, KNOT_RCODE_NOTAUTH); /* Forge IXFR query (badly formed, no SOA in AUTHORITY section). */ - ns_proc_reset(&query_ctx); + knot_process_reset(&query_ctx); knot_pkt_clear(query); knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_IXFR); exec_query(&query_ctx, "IN/ixfr-formerr", query->wire, query->size, KNOT_RCODE_FORMERR); /* Forge IXFR query (well formed). */ - ns_proc_reset(&query_ctx); + knot_process_reset(&query_ctx); /* Append SOA RR. */ knot_rrset_t *soa_rr = knot_node_get_rrset(zone->contents->apex, KNOT_RRTYPE_SOA); knot_pkt_begin(query, KNOT_AUTHORITY); @@ -199,20 +199,20 @@ int main(int argc, char *argv[]) /* #189 Process IXFR client. */ /* Query processor (smaller than DNS header, ignore). */ - state = ns_proc_reset(&query_ctx); + state = knot_process_reset(&query_ctx); knot_pkt_clear(query); knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_SOA); - state = ns_proc_in(query->wire, KNOT_WIRE_HEADER_SIZE - 1, &query_ctx); + state = knot_process_in(query->wire, KNOT_WIRE_HEADER_SIZE - 1, &query_ctx); ok(state == NS_PROC_NOOP, "ns: IN/less-than-header query ignored"); /* Query processor (response, ignore). */ - state = ns_proc_reset(&query_ctx); + state = knot_process_reset(&query_ctx); knot_wire_set_qr(query->wire); - state = ns_proc_in(query->wire, query->size, &query_ctx); + state = knot_process_in(query->wire, query->size, &query_ctx); ok(state == NS_PROC_NOOP, "ns: IN/less-than-header query ignored"); /* Finish. */ - state = ns_proc_finish(&query_ctx); + state = knot_process_finish(&query_ctx); ok(state == NS_PROC_NOOP, "ns: processing end" ); /* Cleanup. */ -- GitLab