rplan.h 8.81 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

Marek Vavruša's avatar
Marek Vavruša committed
19
#include <sys/time.h>
20
#include <libknot/dname.h>
21
#include <libknot/codes.h>
22

23
#include "lib/cache/api.h"
Marek Vavruša's avatar
Marek Vavruša committed
24
#include "lib/zonecut.h"
25
#include "lib/nsrep.h"
26

Marek Vavruša's avatar
Marek Vavruša committed
27
/** Query flags */
Vladimír Čunát's avatar
Vladimír Čunát committed
28
struct kr_qflags {
29 30 31 32 33
	bool NO_MINIMIZE : 1;    /**< Don't minimize QNAME. */
	bool NO_THROTTLE : 1;    /**< No query/slow NS throttling. */
	bool NO_IPV6 : 1;        /**< Disable IPv6 */
	bool NO_IPV4 : 1;        /**< Disable IPv4 */
	bool TCP : 1;            /**< Use TCP for this query. */
34 35
	bool RESOLVED : 1;       /**< Query is resolved.  Note that kr_query gets
				  *   RESOLVED before following a CNAME chain; see .CNAME. */
36 37 38 39 40 41 42 43 44 45 46 47
	bool AWAIT_IPV4 : 1;     /**< Query is waiting for A address. */
	bool AWAIT_IPV6 : 1;     /**< Query is waiting for AAAA address. */
	bool AWAIT_CUT : 1;      /**< Query is waiting for zone cut lookup */
	bool SAFEMODE : 1;       /**< Don't use fancy stuff (EDNS, 0x20, ...) */
	bool CACHED : 1;         /**< Query response is cached. */
	bool NO_CACHE : 1;       /**< No cache for lookup; exception: finding NSs and subqueries. */
	bool EXPIRING : 1;       /**< Query response is cached, but expiring. */
	bool ALLOW_LOCAL : 1;    /**< Allow queries to local or private address ranges. */
	bool DNSSEC_WANT : 1;    /**< Want DNSSEC secured answer; exception: +cd,
				  * i.e. knot_wire_set_cd(request->answer->wire). */
	bool DNSSEC_BOGUS : 1;   /**< Query response is DNSSEC bogus. */
	bool DNSSEC_INSECURE : 1;/**< Query response is DNSSEC insecure. */
48
	bool DNSSEC_CD : 1;      /**< Instruction to set CD bit in request. */
49 50 51 52 53 54 55 56
	bool STUB : 1;           /**< Stub resolution, accept received answer as solved. */
	bool ALWAYS_CUT : 1;     /**< Always recover zone cut (even if cached). */
	bool DNSSEC_WEXPAND : 1; /**< Query response has wildcard expansion. */
	bool PERMISSIVE : 1;     /**< Permissive resolver mode. */
	bool STRICT : 1;         /**< Strict resolver mode. */
	bool BADCOOKIE_AGAIN : 1;/**< Query again because bad cookie returned. */
	bool CNAME : 1;          /**< Query response contains CNAME in answer section. */
	bool REORDER_RR : 1;     /**< Reorder cached RRs. */
Vladimír Čunát's avatar
Vladimír Čunát committed
57
	bool TRACE : 1;          /**< Also log answers if --verbose. */
58 59 60 61 62 63 64
	bool NO_0X20 : 1;        /**< Disable query case randomization . */
	bool DNSSEC_NODS : 1;    /**< DS non-existance is proven */
	bool DNSSEC_OPTOUT : 1;  /**< Closest encloser proof has optout */
	bool NONAUTH : 1;        /**< Non-authoritative in-bailiwick records are enough.
				  * TODO: utilize this also outside cache. */
	bool FORWARD : 1;        /**< Forward all queries to upstream; validate answers. */
	bool DNS64_MARK : 1;     /**< Internal mark for dns64 module. */
Vladimír Čunát's avatar
Vladimír Čunát committed
65
	bool CACHE_TRIED : 1;    /**< Internal to cache module. */
66
	bool NO_NS_FOUND : 1;    /**< No valid NS found during last PRODUCE stage. */
67 68
	bool PKT_IS_SANE : 1;    /**< Set by iterator in consume phase to indicate whether
				  * some basic aspects of the packet are OK, e.g. QNAME. */
69 70
};

71 72 73 74 75 76 77
/** Combine flags together.  This means set union for simple flags. */
KR_EXPORT
void kr_qflags_set(struct kr_qflags *fl1, struct kr_qflags fl2);

/** Remove flags.  This means set-theoretic difference. */
KR_EXPORT
void kr_qflags_clear(struct kr_qflags *fl1, struct kr_qflags fl2);
78

Vladimír Čunát's avatar
Vladimír Čunát committed
79 80 81 82 83 84 85
/** Callback for serve-stale decisions.
 * @param ttl the expired TTL (i.e. it's < 0)
 * @return the adjusted TTL (typically 1) or < 0.
 */
typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type,
				const struct kr_query *qry);

Marek Vavruša's avatar
Marek Vavruša committed
86 87
/**
 * Single query representation.
Marek Vavruša's avatar
Marek Vavruša committed
88
 */
89
struct kr_query {
90
	struct kr_query *parent;
91
	knot_dname_t *sname; /**< The name to resolve - lower-cased, uncompressed. */
92 93
	uint16_t stype;
	uint16_t sclass;
Marek Vavruša's avatar
Marek Vavruša committed
94
	uint16_t id;
95
	uint16_t reorder; /**< Seed to reorder (cached) RRs in answer or zero. */
Vladimír Čunát's avatar
Vladimír Čunát committed
96
	struct kr_qflags flags, forward_flags;
Marek Vavruša's avatar
Marek Vavruša committed
97
	uint32_t secret;
98
	uint32_t uid; /**< Query iteration number, unique within the kr_rplan. */
99
	uint64_t creation_time_mono; /* The time of query's creation (milliseconds).
Vitezslav Kriz's avatar
Vitezslav Kriz committed
100 101
				 * Or time of creation of an oldest
				 * ancestor if it is a subquery. */
102 103
	uint64_t timestamp_mono; /**< Time of query created or time of
	                           * query to upstream resolver (milliseconds). */
104
	struct timeval timestamp; /**< Real time for TTL+DNSSEC checks (.tv_sec only). */
105
	struct kr_zonecut zone_cut;
106
	struct kr_layer_pickle *deferred;
107
	/** Pointer to the query that originated this one because of following a CNAME (or NULL). */
108
	struct kr_query *cname_parent;
109
	struct kr_request *request; /**< Parent resolution request. */
Vladimír Čunát's avatar
Vladimír Čunát committed
110
	kr_stale_cb stale_cb; /**< See the type */
111 112
	/* Beware: this must remain the last, because of lua bindings. */
	struct kr_nsrep ns;
113 114
};

115
/** @cond internal Array of queries. */
116
typedef array_t(struct kr_query *) kr_qarray_t;
117
/* @endcond */
118

Marek Vavruša's avatar
Marek Vavruša committed
119 120
/**
 * Query resolution plan structure.
Marek Vavruša's avatar
Marek Vavruša committed
121 122 123 124 125
 *
 * The structure most importantly holds the original query, answer and the
 * list of pending queries required to resolve the original query.
 * It also keeps a notion of current zone cut.
 */
126
struct kr_rplan {
127 128 129 130
	kr_qarray_t pending;        /**< List of pending queries.
					Beware: order is significant ATM,
					as the last is the next one to solve,
					and they may be inter-dependent. */
131 132
	kr_qarray_t resolved;       /**< List of resolved queries. */
	struct kr_request *request; /**< Parent resolution request. */
133 134
	knot_mm_t *pool;            /**< Temporary memory pool. */
	uint32_t next_uid;          /**< Next value for kr_query::uid (incremental). */
135 136
};

Marek Vavruša's avatar
Marek Vavruša committed
137 138 139
/**
 * Initialize resolution plan (empty).
 * @param rplan plan instance
140
 * @param request resolution request
Marek Vavruša's avatar
Marek Vavruša committed
141
 * @param pool ephemeral memory pool for whole resolution
Marek Vavruša's avatar
Marek Vavruša committed
142
 */
143
KR_EXPORT
144
int kr_rplan_init(struct kr_rplan *rplan, struct kr_request *request, knot_mm_t *pool);
Marek Vavruša's avatar
Marek Vavruša committed
145

Marek Vavruša's avatar
Marek Vavruša committed
146 147 148
/**
 * Deinitialize resolution plan, aborting any uncommited transactions.
 * @param rplan plan instance
Marek Vavruša's avatar
Marek Vavruša committed
149
 */
150
KR_EXPORT
Marek Vavruša's avatar
Marek Vavruša committed
151 152
void kr_rplan_deinit(struct kr_rplan *rplan);

Marek Vavruša's avatar
Marek Vavruša committed
153 154 155
/**
 * Return true if the resolution plan is empty (i.e. finished or initialized)
 * @param rplan plan instance
156
 * @return true or false
Marek Vavruša's avatar
Marek Vavruša committed
157
 */
158
KR_EXPORT KR_PURE
Marek Vavruša's avatar
Marek Vavruša committed
159 160
bool kr_rplan_empty(struct kr_rplan *rplan);

161 162 163 164 165 166 167 168 169 170 171
/**
 * Push empty query to the top of the resolution plan.
 * @note This query serves as a cookie query only.
 * @param rplan plan instance
 * @param parent query parent (or NULL)
 * @return query instance or NULL
 */
KR_EXPORT
struct kr_query *kr_rplan_push_empty(struct kr_rplan *rplan,
                                     struct kr_query *parent);

Marek Vavruša's avatar
Marek Vavruša committed
172 173 174 175 176 177 178 179
/**
 * Push a query to the top of the resolution plan.
 * @note This means that this query takes precedence before all pending queries.
 * @param rplan plan instance
 * @param parent query parent (or NULL)
 * @param name resolved name
 * @param cls  resolved class
 * @param type resolved type
180
 * @return query instance or NULL
Marek Vavruša's avatar
Marek Vavruša committed
181
 */
182
KR_EXPORT
183 184
struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent,
                               const knot_dname_t *name, uint16_t cls, uint16_t type);
Marek Vavruša's avatar
Marek Vavruša committed
185

Marek Vavruša's avatar
Marek Vavruša committed
186 187 188 189 190
/**
 * Pop existing query from the resolution plan.
 * @note Popped queries are not discarded, but moved to the resolved list.
 * @param rplan plan instance
 * @param qry resolved query
191
 * @return 0 or an error
Marek Vavruša's avatar
Marek Vavruša committed
192
 */
193
KR_EXPORT
194 195
int kr_rplan_pop(struct kr_rplan *rplan, struct kr_query *qry);

Marek Vavruša's avatar
Marek Vavruša committed
196 197
/**
 * Return true if resolution chain satisfies given query.
198
 */
199
KR_EXPORT KR_PURE
200 201 202
bool kr_rplan_satisfies(struct kr_query *closure, const knot_dname_t *name, uint16_t cls, uint16_t type);

/** Return last resolved query. */
203
KR_EXPORT KR_PURE
204 205
struct kr_query *kr_rplan_resolved(struct kr_rplan *rplan);

206 207 208 209 210 211 212
/**
  * Return last query (either currently being solved or last resolved).
  * This is necessary to retrieve the last query in case of resolution failures (e.g. time limit reached).
  */
KR_EXPORT KR_PURE
struct kr_query *kr_rplan_last(struct kr_rplan *rplan);

Grigorii Demidov's avatar
Grigorii Demidov committed
213 214 215 216 217 218 219 220 221 222 223 224 225

/**
 * Check if a given query already resolved.
 * @param rplan plan instance
 * @param parent query parent (or NULL)
 * @param name resolved name
 * @param cls  resolved class
 * @param type resolved type
 * @return query instance or NULL
 */
KR_EXPORT KR_PURE
struct kr_query *kr_rplan_find_resolved(struct kr_rplan *rplan, struct kr_query *parent,
                               const knot_dname_t *name, uint16_t cls, uint16_t type);