summaryrefslogtreecommitdiffstats
path: root/src/knot/nameserver/process_query.h
blob: 00e1790c03361a51191a398086b3dc6ce1df0aa8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*  Copyright (C) 2019 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 <https://www.gnu.org/licenses/>.
 */

#pragma once

#include "knot/include/module.h"
#include "knot/query/layer.h"
#include "knot/updates/acl.h"
#include "knot/zone/zone.h"

/* Query processing module implementation. */
const knot_layer_api_t *process_query_layer(void);

/*! \brief Query processing intermediate data. */
typedef struct knotd_qdata_extra {
	const zone_t *zone;  /*!< Zone from which is answered. */
	const zone_contents_t *contents; /*!< Zone contents from which is answered. */
	list_t wildcards;    /*!< Visited wildcards. */
	list_t rrsigs;       /*!< Section RRSIGs. */
	uint8_t *opt_rr_pos; /*!< Place of the OPT RR in wire. */

	/* Currently processed nodes. */
	const zone_node_t *node, *encloser, *previous;

	/* Original QNAME case. */
	knot_dname_storage_t orig_qname;
	uint8_t cname_chain; /*!< Length of the CNAME chain so far. */

	/* Extensions. */
	void *ext;
	void (*ext_cleanup)(knotd_qdata_t *); /*!< Extensions cleanup callback. */
} knotd_qdata_extra_t;

/*! \brief Visited wildcard node list. */
struct wildcard_hit {
	node_t n;
	const zone_node_t *node;   /* Visited node. */
	const zone_node_t *prev;   /* Previous node from the SNAME. */
	const knot_dname_t *sname; /* Name leading to this node. */
};

/*! \brief RRSIG info node list. */
struct rrsig_info {
	node_t n;
	knot_rrset_t synth_rrsig; /* Synthesized RRSIG. */
	knot_rrinfo_t *rrinfo;    /* RR info. */
};

/*!
 * \brief Check current query against ACL.
 *
 * \param conf       Configuration.
 * \param action     ACL action.
 * \param qdata      Query data.
 * \return true if accepted, false if denied.
 */
bool process_query_acl_check(conf_t *conf, acl_action_t action,
                             knotd_qdata_t *qdata);

/*!
 * \brief Verify current query transaction security and update query data.
 *
 * \param qdata
 * \retval KNOT_EOK
 * \retval KNOT_TSIG_EBADKEY
 * \retval KNOT_TSIG_EBADSIG
 * \retval KNOT_TSIG_EBADTIME
 * \retval (other generic errors)
 */
int process_query_verify(knotd_qdata_t *qdata);

/*!
 * \brief Sign current query using configured TSIG keys.
 *
 * \param pkt    Outgoing message.
 * \param qdata  Query data.
 *
 * \retval KNOT_E*
 */
int process_query_sign_response(knot_pkt_t *pkt, knotd_qdata_t *qdata);

/*!
 * \brief Restore QNAME letter case.
 *
 * \param pkt    Incoming message.
 * \param qdata  Query data.
 */
static inline void process_query_qname_case_restore(knot_pkt_t *pkt, knotd_qdata_t *qdata)
{
	// If original QNAME is empty, query is either unparsed or for root domain.
	if (qdata->extra->orig_qname[0] != '\0') {
		memcpy(pkt->wire + KNOT_WIRE_HEADER_SIZE,
		       qdata->extra->orig_qname, qdata->query->qname_size);
	}
}

/*!
 * \brief Convert QNAME to lowercase format for processing.
 *
 * \param pkt    Incoming message.
 */
static inline void process_query_qname_case_lower(knot_pkt_t *pkt)
{
	knot_dname_to_lower(knot_pkt_qname(pkt));
}

/*!
 * \brief Puts RRSet to packet, will store its RRSIG for later use.
 *
 * \param pkt         Packet to store RRSet into.
 * \param qdata       Query data structure.
 * \param rr          RRSet to be stored.
 * \param rrsigs      RRSIGs to be stored.
 * \param compr_hint  Compression hint.
 * \param flags       Flags.
 *
 * \return KNOT_E*
 */
int process_query_put_rr(knot_pkt_t *pkt, knotd_qdata_t *qdata,
                         const knot_rrset_t *rr, const knot_rrset_t *rrsigs,
                         uint16_t compr_hint, uint32_t flags);