resolve.h 11.5 KB
Newer Older
1
/*  Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2

Marek Vavruša's avatar
Marek Vavruša committed
3 4 5 6
    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.
7

Marek Vavruša's avatar
Marek Vavruša committed
8 9 10 11
    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.
12

Marek Vavruša's avatar
Marek Vavruša committed
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/>.
Marek Vavruša's avatar
Marek Vavruša committed
15
 */
16 17 18

#pragma once

19
#include <netinet/in.h>
20
#include <sys/socket.h>
Marek Vavruša's avatar
Marek Vavruša committed
21
#include <libknot/packet/pkt.h>
22

23
#include "lib/cookies/control.h"
24
#include "lib/cookies/lru_cache.h"
25
#include "lib/layer.h"
26
#include "lib/generic/map.h"
27
#include "lib/generic/array.h"
28
#include "lib/nsrep.h"
29
#include "lib/rplan.h"
30
#include "lib/module.h"
31
#include "lib/cache/api.h"
32

33 34
/**
 * @file resolve.h
35 36
 * @brief The API provides an API providing a "consumer-producer"-like interface to enable
 * user to plug it into existing event loop or I/O code.
37 38 39 40 41 42
 *
 * # Example usage of the iterative API:
 *
 * @code{.c}
 *
 * // Create request and its memory pool
43 44 45 46 47 48
 * struct kr_request req = {
 * 	.pool = {
 * 		.ctx = mp_new (4096),
 * 		.alloc = (mm_alloc_t) mp_alloc
 * 	}
 * };
49 50 51 52
 *
 * // Setup and provide input query
 * int state = kr_resolve_begin(&req, ctx, final_answer);
 * state = kr_resolve_consume(&req, query);
53 54
 *
 * // Generate answer
55
 * while (state == KR_STATE_PRODUCE) {
56 57 58
 *
 *     // Additional query generate, do the I/O and pass back answer
 *     state = kr_resolve_produce(&req, &addr, &type, query);
59
 *     while (state == KR_STATE_CONSUME) {
60 61 62
 *         int ret = sendrecv(addr, proto, query, resp);
 *
 *         // If I/O fails, make "resp" empty
63
 *         state = kr_resolve_consume(&request, addr, resp);
64 65 66 67 68 69 70 71 72 73 74
 *         knot_pkt_clear(resp);
 *     }
 *     knot_pkt_clear(query);
 * }
 *
 * // "state" is either DONE or FAIL
 * kr_resolve_finish(&request, state);
 *
 * @endcode
 */

75 76

/**
77
 * RRset rank - for cache and ranked_rr_*.
78
 *
79 80 81 82
 * The rank meaning consists of one independent flag - KR_RANK_AUTH,
 * and the rest have meaning of values where only one can hold at any time.
 * You can use one of the enums as a safe initial value, optionally | KR_RANK_AUTH;
 * otherwise it's best to manipulate ranks via the kr_rank_* functions.
83
 *
84
 * @note The representation is complicated by restrictions on integer comparison:
85
 * - AUTH must be > than !AUTH
86
 * - AUTH INSECURE must be > than AUTH (because it attempted validation)
87
 * - !AUTH SECURE must be > than AUTH (because it's valid)
88 89 90 91 92 93
 *
 * See also:
 *   https://tools.ietf.org/html/rfc2181#section-5.4.1
 *   https://tools.ietf.org/html/rfc4035#section-4.3
 */
enum kr_rank {
94
	/* Initial-like states.  No validation has been attempted (yet). */
Vladimír Čunát's avatar
Vladimír Čunát committed
95 96 97 98 99 100
	KR_RANK_INITIAL = 0, /**< Did not attempt to validate. It's assumed
					compulsory to validate (or prove insecure). */
	KR_RANK_OMIT,        /**< Do not attempt to validate.
					(And don't consider it a validation failure.) */
	KR_RANK_TRY,         /**< Attempt to validate, but failures are non-fatal. */

101
	/* Failure states.  These have higher value because they have more information. */
Vladimír Čunát's avatar
Vladimír Čunát committed
102
	KR_RANK_INDET = 4,   /**< Unable to determine whether it should be secure. */
103
	KR_RANK_BOGUS,       /**< Ought to be secure but isn't. */
104
	KR_RANK_MISMATCH,
105
	KR_RANK_MISSING,     /**< Unable to obtain a good signature. */
106

107 108 109 110
	/** Proven to be insecure, i.e. we have a chain of trust from TAs
	 * that cryptographically denies the possibility of existence
	 * of a positive chain of trust from the TAs to the record. */
	KR_RANK_INSECURE = 8,
111 112 113 114 115 116 117 118 119

	/** Authoritative data flag; the chain of authority was "verified".
	 *  Even if not set, only in-bailiwick stuff is acceptable,
	 *  i.e. almost authoritative (example: mandatory glue and its NS RR). */
	KR_RANK_AUTH = 16,

	KR_RANK_SECURE = 32,  /**< Verified whole chain of trust from the closest TA. */
	/* @note Rank must not exceed 6 bits */
};
Grigorii Demidov's avatar
Grigorii Demidov committed
120

121 122 123 124 125
/** Check that a rank value is valid.  Meant for assertions. */
bool kr_rank_check(uint8_t rank) KR_PURE;

/** Test the presence of any flag/state in a rank, i.e. including KR_RANK_AUTH. */
static inline bool kr_rank_test(uint8_t rank, uint8_t kr_flag)
126
{
127 128 129 130 131 132 133
	assert(kr_rank_check(rank) && kr_rank_check(kr_flag));
	if (kr_flag == KR_RANK_AUTH) {
		return rank & KR_RANK_AUTH;
	}
	assert(!(kr_flag & KR_RANK_AUTH));
	/* The rest are exclusive values - exactly one has to be set. */
	return (rank & ~KR_RANK_AUTH) == kr_flag;
134
}
135 136 137

/** Set the rank state. The _AUTH flag is kept as it was. */
static inline void kr_rank_set(uint8_t *rank, uint8_t kr_flag)
138
{
139 140 141
	assert(rank && kr_rank_check(*rank));
	assert(kr_rank_check(kr_flag) && !(kr_flag & KR_RANK_AUTH));
	*rank = kr_flag | (*rank & KR_RANK_AUTH);
142 143
}

144

145
/** @cond internal Array of modules. */
146
typedef array_t(struct kr_module *) module_array_t;
147
/* @endcond */
148 149 150 151 152 153 154 155 156 157

/**
 * Name resolution context.
 *
 * Resolution context provides basic services like cache, configuration and options.
 *
 * @note This structure is persistent between name resolutions and may
 *       be shared between threads.
 */
struct kr_context
158
{
Vladimír Čunát's avatar
Vladimír Čunát committed
159
	struct kr_qflags options;
160 161
	knot_rrset_t *opt_rr;
	map_t trust_anchors;
162
	map_t negative_anchors;
163
	struct kr_zonecut root_hints;
164
	struct kr_cache cache;
165
	kr_nsrep_rtt_lru_t *cache_rtt;
166
	unsigned cache_rtt_tout_retry_interval;
167
	kr_nsrep_lru_t *cache_rep;
168
	module_array_t *modules;
169 170
	/* The cookie context structure should not be held within the cookies
	 * module because of better access. */
171
	struct kr_cookie_ctx cookie_ctx;
172
	kr_cookie_lru_t *cache_cookie;
173
	int32_t tls_padding; /**< See net.tls_padding in ../daemon/README.rst -- -1 is "true" (default policy), 0 is "false" (no padding) */
174
	knot_mm_t *pool;
175
};
176

177 178 179
/* Kept outside, because kres-gen.lua can't handle this depth
 * (and lines here were too long anyway). */
struct kr_request_qsource_flags {
180 181
	bool tcp:1; /**< true if the request is on TCP (or TLS); only meaningful if (dst_addr). */
	bool tls:1; /**< true if the request is on TLS; only meaningful if (dst_addr). */
Petr Špaček's avatar
Petr Špaček committed
182
	bool http:1; /**< true if the request is on HTTP; only meaningful if (dst_addr). */
183 184
};

185 186 187 188 189 190 191 192 193 194 195
/**
 * Name resolution request.
 *
 * Keeps information about current query processing between calls to
 * processing APIs, i.e. current resolved query, resolution plan, ...
 * Use this instead of the simple interface if you want to implement
 * multiplexing or custom I/O.
 *
 * @note All data for this request must be allocated from the given pool.
 */
struct kr_request {
Grigorii Demidov's avatar
Grigorii Demidov committed
196 197 198 199
	struct kr_context *ctx;
	knot_pkt_t *answer;
	struct kr_query *current_query;    /**< Current evaluated query. */
	struct {
200
		/** Address that originated the request. NULL for internal origin. */
Grigorii Demidov's avatar
Grigorii Demidov committed
201
		const struct sockaddr *addr;
202
		/** Address that accepted the request.  NULL for internal origin. */
Grigorii Demidov's avatar
Grigorii Demidov committed
203 204
		const struct sockaddr *dst_addr;
		const knot_pkt_t *packet;
205
		struct kr_request_qsource_flags flags; /**< See definition above. */
206
		size_t size; /**< query packet size */
Grigorii Demidov's avatar
Grigorii Demidov committed
207 208 209 210 211
	} qsource;
	struct {
		unsigned rtt;                  /**< Current upstream RTT */
		const struct sockaddr *addr;   /**< Current upstream address */
	} upstream;                        /**< Upstream information, valid only in consume() phase */
Vladimír Čunát's avatar
Vladimír Čunát committed
212
	struct kr_qflags options;
Grigorii Demidov's avatar
Grigorii Demidov committed
213 214 215
	int state;
	ranked_rr_array_t answ_selected;
	ranked_rr_array_t auth_selected;
Vladimír Čunát's avatar
.  
Vladimír Čunát committed
216
	ranked_rr_array_t add_selected;
217 218
	bool answ_validated; /**< internal to validator; beware of caching, etc. */
	bool auth_validated; /**< see answ_validated ^^ ; TODO */
219 220 221 222 223 224 225 226 227 228

	/** Overall rank for the request.
	 *
	 * Values from kr_rank, currently just KR_RANK_SECURE and _INITIAL.
	 * Only read this in finish phase and after validator, please.
	 * Meaning of _SECURE: all RRs in answer+authority are _SECURE,
	 *   including any negative results implied (NXDOMAIN, NODATA).
	 */
	uint8_t rank;

Grigorii Demidov's avatar
Grigorii Demidov committed
229
	struct kr_rplan rplan;
230
	trace_log_f trace_log; /**< Logging tracepoint */
231
	trace_callback_f trace_finish; /**< Request finish tracepoint */
232
	int vars_ref; /**< Reference to per-request variable table. LUA_NOREF if not set. */
Grigorii Demidov's avatar
Grigorii Demidov committed
233
	knot_mm_t pool;
234
	unsigned int uid; /** for logging purposes only */
235 236
};

Vladimír Čunát's avatar
.  
Vladimír Čunát committed
237 238 239 240 241 242 243
/** Initializer for an array of *_selected. */
#define kr_request_selected(req) { \
	[KNOT_ANSWER] = &(req)->answ_selected, \
	[KNOT_AUTHORITY] = &(req)->auth_selected, \
	[KNOT_ADDITIONAL] = &(req)->add_selected, \
	}

244 245 246 247 248 249 250 251 252 253 254
/**
 * Begin name resolution.
 *
 * @note Expects a request to have an initialized mempool, the "answer" packet will
 *       be kept during the resolution and will contain the final answer at the end.
 *
 * @param request request state with initialized mempool
 * @param ctx     resolution context
 * @param answer  allocated packet for final answer
 * @return        CONSUME (expecting query)
 */
255
KR_EXPORT
256 257 258 259 260 261 262 263
int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx, knot_pkt_t *answer);

/**
 * Consume input packet (may be either first query or answer to query originated from kr_resolve_produce())
 *
 * @note If the I/O fails, provide an empty or NULL packet, this will make iterator recognize nameserver failure.
 * 
 * @param  request request state (awaiting input)
264
 * @param  src     [in] packet source address
265 266 267
 * @param  packet  [in] input packet
 * @return         any state
 */
268
KR_EXPORT
269
int kr_resolve_consume(struct kr_request *request, const struct sockaddr *src, knot_pkt_t *packet);
270 271 272 273 274 275 276 277 278 279 280 281 282 283

/**
 * Produce either next additional query or finish.
 *
 * If the CONSUME is returned then dst, type and packet will be filled with
 * appropriate values and caller is responsible to send them and receive answer.
 * If it returns any other state, then content of the variables is undefined.
 * 
 * @param  request request state (in PRODUCE state)
 * @param  dst     [out] possible address of the next nameserver
 * @param  type    [out] possible used socket type (SOCK_STREAM, SOCK_DGRAM)
 * @param  packet  [out] packet to be filled with additional query
 * @return         any state
 */
284
KR_EXPORT
285 286
int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *type, knot_pkt_t *packet);

287
/**
288
 * Finalises the outbound query packet with the knowledge of the IP addresses.
289 290 291 292
 *
 * @note The function must be called before actual sending of the request packet.
 *
 * @param  request request state (in PRODUCE state)
293
 * @param  src     address from which the query is going to be sent
294 295 296
 * @param  dst     address of the name server
 * @param  type    used socket type (SOCK_STREAM, SOCK_DGRAM)
 * @param  packet  [in,out] query packet to be finalised
297
 * @return         kr_ok() or error code
298 299
 */
KR_EXPORT
300
int kr_resolve_checkout(struct kr_request *request, const struct sockaddr *src,
301
                        struct sockaddr *dst, int type, knot_pkt_t *packet);
302

303 304 305 306 307 308 309
/**
 * Finish resolution and commit results if the state is DONE.
 *
 * @note The structures will be deinitialized, but the assigned memory pool is not going to
 *       be destroyed, as it's owned by caller.
 *
 * @param  request request state
310
 * @param  state   either DONE or FAIL state (to be assigned to request->state)
311 312
 * @return         DONE
 */
313
KR_EXPORT
314
int kr_resolve_finish(struct kr_request *request, int state);
315 316 317

/**
 * Return resolution plan.
318 319
 * @param  request request state
 * @return         pointer to rplan
320
 */
321
KR_EXPORT KR_PURE
322 323
struct kr_rplan *kr_resolve_plan(struct kr_request *request);

324 325 326 327 328
/**
 * Return memory pool associated with request.
 * @param  request request state
 * @return         mempool
 */
329
KR_EXPORT KR_PURE
330
knot_mm_t *kr_resolve_pool(struct kr_request *request);
331