1 /*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2 
3     This program is free software: you can redistribute it and/or modify
4     it under the terms of the GNU General Public License as published by
5     the Free Software Foundation, either version 3 of the License, or
6     (at your option) any later version.
7 
8     This program is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11     GNU General Public License for more details.
12 
13     You should have received a copy of the GNU General Public License
14     along with this program.  If not, see <https://www.gnu.org/licenses/>.
15  */
16 
17 #pragma once
18 
19 #include "libknot/libknot.h"
20 #include "knot/conf/conf.h"
21 #include "knot/dnssec/context.h"
22 #include "knot/dnssec/zone-keys.h"
23 #include "knot/include/module.h"
24 #include "knot/server/server.h"
25 #include "contrib/ucw/lists.h"
26 
27 #ifdef HAVE_ATOMIC
28  #define ATOMIC_GET(src) __atomic_load_n(&(src), __ATOMIC_RELAXED)
29 #else
30  #define ATOMIC_GET(src) (src)
31 #endif
32 
33 #define KNOTD_STAGES (KNOTD_STAGE_END + 1)
34 
35 typedef unsigned (*query_step_process_f)
36 	(unsigned state, knot_pkt_t *pkt, knotd_qdata_t *qdata, knotd_mod_t *mod);
37 
38 /*! \brief Single processing step in query processing. */
39 struct query_step {
40 	node_t node;
41 	void *ctx;
42 	query_step_process_f process;
43 };
44 
45 /*! Query plan represents a sequence of steps needed for query processing
46  *  divided into several stages, where each stage represents a current response
47  *  assembly phase, for example 'before processing', 'answer section' and so on.
48  */
49 struct query_plan {
50 	list_t stage[KNOTD_STAGES];
51 };
52 
53 /*! \brief Create an empty query plan. */
54 struct query_plan *query_plan_create(void);
55 
56 /*! \brief Free query plan and all planned steps. */
57 void query_plan_free(struct query_plan *plan);
58 
59 /*! \brief Plan another step for given stage. */
60 int query_plan_step(struct query_plan *plan, knotd_stage_t stage,
61                     query_step_process_f process, void *ctx);
62 
63 /*! \brief Open query module identified by name. */
64 knotd_mod_t *query_module_open(conf_t *conf, server_t *server, conf_mod_id_t *mod_id,
65                                struct query_plan *plan, const knot_dname_t *zone);
66 
67 /*! \brief Close query module. */
68 void query_module_close(knotd_mod_t *module);
69 
70 /*! \brief Close and open existing query module. */
71 void query_module_reset(conf_t *conf, knotd_mod_t *module, struct query_plan *new_plan);
72 
73 typedef char* (*mod_idx_to_str_f)(uint32_t idx, uint32_t count);
74 
75 typedef struct {
76 	const char *name;
77 	mod_idx_to_str_f idx_to_str; // unused if count == 1
78 	uint32_t offset; // offset of counters in stats_vals[thread_id]
79 	uint32_t count;
80 } mod_ctr_t;
81 
82 struct knotd_mod {
83 	node_t node;
84 	conf_t *config;
85 	server_t *server;
86 	conf_mod_id_t *id;
87 	struct query_plan *plan;
88 	const knot_dname_t *zone;
89 	const knotd_mod_api_t *api;
90 	kdnssec_ctx_t *dnssec;
91 	zone_keyset_t *keyset;
92 	zone_sign_ctx_t *sign_ctx;
93 	mod_ctr_t *stats_info;
94 	uint64_t **stats_vals;
95 	uint32_t stats_count;
96 	void *ctx;
97 };
98 
99 void knotd_mod_stats_free(knotd_mod_t *mod);
100