1238106Sdes/*
2238106Sdes * iterator/iterator.h - iterative resolver DNS query response module
3238106Sdes *
4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved.
5238106Sdes *
6238106Sdes * This software is open source.
7238106Sdes *
8238106Sdes * Redistribution and use in source and binary forms, with or without
9238106Sdes * modification, are permitted provided that the following conditions
10238106Sdes * are met:
11238106Sdes *
12238106Sdes * Redistributions of source code must retain the above copyright notice,
13238106Sdes * this list of conditions and the following disclaimer.
14238106Sdes *
15238106Sdes * Redistributions in binary form must reproduce the above copyright notice,
16238106Sdes * this list of conditions and the following disclaimer in the documentation
17238106Sdes * and/or other materials provided with the distribution.
18238106Sdes *
19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may
20238106Sdes * be used to endorse or promote products derived from this software without
21238106Sdes * specific prior written permission.
22238106Sdes *
23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24269257Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25269257Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26269257Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27269257Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28269257Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29269257Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30269257Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31269257Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32269257Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33269257Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34238106Sdes */
35238106Sdes
36238106Sdes/**
37238106Sdes * \file
38238106Sdes *
39238106Sdes * This file contains a module that performs recusive iterative DNS query
40238106Sdes * processing.
41238106Sdes */
42238106Sdes
43238106Sdes#ifndef ITERATOR_ITERATOR_H
44238106Sdes#define ITERATOR_ITERATOR_H
45238106Sdes#include "services/outbound_list.h"
46238106Sdes#include "util/data/msgreply.h"
47238106Sdes#include "util/module.h"
48238106Sdesstruct delegpt;
49238106Sdesstruct iter_hints;
50238106Sdesstruct iter_forwards;
51238106Sdesstruct iter_donotq;
52238106Sdesstruct iter_prep_list;
53238106Sdesstruct iter_priv;
54291767Sdesstruct rbtree_t;
55238106Sdes
56275853Sdelphij/** max number of targets spawned for a query and its subqueries */
57291767Sdes#define MAX_TARGET_COUNT	64
58238106Sdes/** max number of query restarts. Determines max number of CNAME chain. */
59238106Sdes#define MAX_RESTART_COUNT       8
60238106Sdes/** max number of referrals. Makes sure resolver does not run away */
61238106Sdes#define MAX_REFERRAL_COUNT	130
62238106Sdes/** max number of queries-sent-out.  Make sure large NS set does not loop */
63285206Sdes#define MAX_SENT_COUNT		32
64238106Sdes/** at what query-sent-count to stop target fetch policy */
65238106Sdes#define TARGET_FETCH_STOP	3
66238106Sdes/** how nice is a server without further information, in msec
67238106Sdes * Equals rtt initial timeout value.
68238106Sdes */
69238106Sdes#define UNKNOWN_SERVER_NICENESS 376
70238106Sdes/** maximum timeout before a host is deemed unsuitable, in msec.
71238106Sdes * After host_ttl this will be timed out and the host will be tried again.
72238106Sdes * Equals RTT_MAX_TIMEOUT
73238106Sdes */
74238106Sdes#define USEFUL_SERVER_TOP_TIMEOUT	120000
75238106Sdes/** number of retries on outgoing queries */
76238106Sdes#define OUTBOUND_MSG_RETRY 5
77238106Sdes/** RTT band, within this amount from the best, servers are chosen randomly.
78238106Sdes * Chosen so that the UNKNOWN_SERVER_NICENESS falls within the band of a
79238106Sdes * fast server, this causes server exploration as a side benefit. msec. */
80238106Sdes#define RTT_BAND 400
81238106Sdes/** Start value for blacklisting a host, 2*USEFUL_SERVER_TOP_TIMEOUT in sec */
82238106Sdes#define INFRA_BACKOFF_INITIAL 240
83238106Sdes
84238106Sdes/**
85238106Sdes * Global state for the iterator.
86238106Sdes */
87238106Sdesstruct iter_env {
88238106Sdes	/** A flag to indicate whether or not we have an IPv6 route */
89238106Sdes	int supports_ipv6;
90238106Sdes
91238106Sdes	/** A flag to indicate whether or not we have an IPv4 route */
92238106Sdes	int supports_ipv4;
93238106Sdes
94238106Sdes	/** A set of inetaddrs that should never be queried. */
95238106Sdes	struct iter_donotq* donotq;
96238106Sdes
97238106Sdes	/** private address space and private domains */
98238106Sdes	struct iter_priv* priv;
99238106Sdes
100291767Sdes	/** whitelist for capsforid names */
101291767Sdes	struct rbtree_t* caps_white;
102291767Sdes
103238106Sdes	/** The maximum dependency depth that this resolver will pursue. */
104238106Sdes	int max_dependency_depth;
105238106Sdes
106238106Sdes	/**
107238106Sdes	 * The target fetch policy for each dependency level. This is
108238106Sdes	 * described as a simple number (per dependency level):
109238106Sdes	 *	negative numbers (usually just -1) mean fetch-all,
110238106Sdes	 *	0 means only fetch on demand, and
111238106Sdes	 *	positive numbers mean to fetch at most that many targets.
112238106Sdes	 * array of max_dependency_depth+1 size.
113238106Sdes	 */
114238106Sdes	int* target_fetch_policy;
115294190Sdes
116294190Sdes	/** ip6.arpa dname in wireformat, used for qname-minimisation */
117294190Sdes	uint8_t* ip6arpa_dname;
118238106Sdes};
119238106Sdes
120238106Sdes/**
121294190Sdes * QNAME minimisation state
122294190Sdes */
123294190Sdesenum minimisation_state {
124294190Sdes	/**
125294190Sdes	 * (Re)start minimisation. Outgoing QNAME should be set to dp->name.
126294190Sdes	 * State entered on new query or after following refferal or CNAME.
127294190Sdes	 */
128294190Sdes	INIT_MINIMISE_STATE = 0,
129294190Sdes	/**
130294190Sdes	 * QNAME minimisataion ongoing. Increase QNAME on every iteration.
131294190Sdes	 */
132294190Sdes	MINIMISE_STATE,
133294190Sdes	/**
134294190Sdes	 * Don't increment QNAME this iteration
135294190Sdes	 */
136294190Sdes	SKIP_MINIMISE_STATE,
137294190Sdes	/**
138294190Sdes	 * Send out full QNAME + original QTYPE
139294190Sdes	 */
140294190Sdes	DONOT_MINIMISE_STATE,
141294190Sdes};
142294190Sdes
143294190Sdes/**
144238106Sdes * State of the iterator for a query.
145238106Sdes */
146238106Sdesenum iter_state {
147238106Sdes	/**
148238106Sdes	 * Externally generated queries start at this state. Query restarts are
149238106Sdes	 * reset to this state.
150238106Sdes	 */
151238106Sdes	INIT_REQUEST_STATE = 0,
152238106Sdes
153238106Sdes	/**
154238106Sdes	 * Root priming events reactivate here, most other events pass
155238106Sdes	 * through this naturally as the 2nd part of the INIT_REQUEST_STATE.
156238106Sdes	 */
157238106Sdes	INIT_REQUEST_2_STATE,
158238106Sdes
159238106Sdes	/**
160238106Sdes	 * Stub priming events reactivate here, most other events pass
161238106Sdes	 * through this naturally as the 3rd part of the INIT_REQUEST_STATE.
162238106Sdes	 */
163238106Sdes	INIT_REQUEST_3_STATE,
164238106Sdes
165238106Sdes	/**
166238106Sdes	 * Each time a delegation point changes for a given query or a
167238106Sdes	 * query times out and/or wakes up, this state is (re)visited.
168238106Sdes	 * This state is reponsible for iterating through a list of
169238106Sdes	 * nameserver targets.
170238106Sdes	 */
171238106Sdes	QUERYTARGETS_STATE,
172238106Sdes
173238106Sdes	/**
174238106Sdes	 * Responses to queries start at this state. This state handles
175238106Sdes	 * the decision tree associated with handling responses.
176238106Sdes	 */
177238106Sdes	QUERY_RESP_STATE,
178238106Sdes
179238106Sdes	/** Responses to priming queries finish at this state. */
180238106Sdes	PRIME_RESP_STATE,
181238106Sdes
182238106Sdes	/** Collecting query class information, for qclass=ANY, when
183238106Sdes	 * it spawns off queries for every class, it returns here. */
184238106Sdes	COLLECT_CLASS_STATE,
185238106Sdes
186238106Sdes	/** Find NS record to resolve DS record from, walking to the right
187238106Sdes	 * NS spot until we find it */
188238106Sdes	DSNS_FIND_STATE,
189238106Sdes
190238106Sdes	/** Responses that are to be returned upstream end at this state.
191238106Sdes	 * As well as responses to target queries. */
192238106Sdes	FINISHED_STATE
193238106Sdes};
194238106Sdes
195238106Sdes/**
196238106Sdes * Per query state for the iterator module.
197238106Sdes */
198238106Sdesstruct iter_qstate {
199238106Sdes	/**
200238106Sdes	 * State of the iterator module.
201238106Sdes	 * This is the state that event is in or should sent to -- all
202238106Sdes	 * requests should start with the INIT_REQUEST_STATE. All
203238106Sdes	 * responses should start with QUERY_RESP_STATE. Subsequent
204238106Sdes	 * processing of the event will change this state.
205238106Sdes	 */
206238106Sdes	enum iter_state state;
207238106Sdes
208238106Sdes	/**
209238106Sdes	 * Final state for the iterator module.
210238106Sdes	 * This is the state that responses should be routed to once the
211238106Sdes	 * response is final. For externally initiated queries, this
212238106Sdes	 * will be FINISHED_STATE, locally initiated queries will have
213238106Sdes	 * different final states.
214238106Sdes	 */
215238106Sdes	enum iter_state final_state;
216238106Sdes
217238106Sdes	/**
218238106Sdes	 * The depth of this query, this means the depth of recursion.
219238106Sdes	 * This address is needed for another query, which is an address
220238106Sdes	 * needed for another query, etc. Original client query has depth 0.
221238106Sdes	 */
222238106Sdes	int depth;
223238106Sdes
224238106Sdes	/**
225238106Sdes	 * The response
226238106Sdes	 */
227238106Sdes	struct dns_msg* response;
228238106Sdes
229238106Sdes	/**
230238106Sdes	 * This is a list of RRsets that must be prepended to the
231238106Sdes	 * ANSWER section of a response before being sent upstream.
232238106Sdes	 */
233238106Sdes	struct iter_prep_list* an_prepend_list;
234238106Sdes	/** Last element of the prepend list */
235238106Sdes	struct iter_prep_list* an_prepend_last;
236238106Sdes
237238106Sdes	/**
238238106Sdes	 * This is the list of RRsets that must be prepended to the
239238106Sdes	 * AUTHORITY section of the response before being sent upstream.
240238106Sdes	 */
241238106Sdes	struct iter_prep_list* ns_prepend_list;
242238106Sdes	/** Last element of the authority prepend list */
243238106Sdes	struct iter_prep_list* ns_prepend_last;
244238106Sdes
245238106Sdes	/** query name used for chasing the results. Initially the same as
246238106Sdes	 * the state qinfo, but after CNAMEs this will be different.
247238106Sdes	 * The query info used to elicit the results needed. */
248238106Sdes	struct query_info qchase;
249238106Sdes	/** query flags to use when chasing the answer (i.e. RD flag) */
250238106Sdes	uint16_t chase_flags;
251238106Sdes	/** true if we set RD bit because of last resort recursion lame query*/
252238106Sdes	int chase_to_rd;
253238106Sdes
254238106Sdes	/**
255238106Sdes	 * This is the current delegation point for an in-progress query. This
256238106Sdes	 * object retains state as to which delegation targets need to be
257238106Sdes	 * (sub)queried for vs which ones have already been visited.
258238106Sdes	 */
259238106Sdes	struct delegpt* dp;
260238106Sdes
261238106Sdes	/** state for 0x20 fallback when capsfail happens, 0 not a fallback */
262238106Sdes	int caps_fallback;
263238106Sdes	/** state for capsfail: current server number to try */
264238106Sdes	size_t caps_server;
265285206Sdes	/** state for capsfail: stored query for comparisons. Can be NULL if
266285206Sdes	 * no response had been seen prior to starting the fallback. */
267238106Sdes	struct reply_info* caps_reply;
268291767Sdes	struct dns_msg* caps_response;
269238106Sdes
270238106Sdes	/** Current delegation message - returned for non-RD queries */
271238106Sdes	struct dns_msg* deleg_msg;
272238106Sdes
273238106Sdes	/** number of outstanding target sub queries */
274238106Sdes	int num_target_queries;
275238106Sdes
276238106Sdes	/** outstanding direct queries */
277238106Sdes	int num_current_queries;
278238106Sdes
279238106Sdes	/** the number of times this query has been restarted. */
280238106Sdes	int query_restart_count;
281238106Sdes
282238106Sdes	/** the number of times this query as followed a referral. */
283238106Sdes	int referral_count;
284238106Sdes
285238106Sdes	/** number of queries fired off */
286238106Sdes	int sent_count;
287275853Sdelphij
288275853Sdelphij	/** number of target queries spawned in [1], for this query and its
289275853Sdelphij	 * subqueries, the malloced-array is shared, [0] refcount. */
290275853Sdelphij	int* target_count;
291238106Sdes
292291767Sdes	/** if true, already tested for ratelimiting and passed the test */
293291767Sdes	int ratelimit_ok;
294291767Sdes
295238106Sdes	/**
296238106Sdes	 * The query must store NS records from referrals as parentside RRs
297238106Sdes	 * Enabled once it hits resolution problems, to throttle retries.
298238106Sdes	 * If enabled it is the pointer to the old delegation point with
299238106Sdes	 * the old retry counts for bad-nameserver-addresses.
300238106Sdes	 */
301238106Sdes	struct delegpt* store_parent_NS;
302238106Sdes
303238106Sdes	/**
304238106Sdes	 * The query is for parent-side glue(A or AAAA) for a nameserver.
305238106Sdes	 * If the item is seen as glue in a referral, and pside_glue is NULL,
306238106Sdes	 * then it is stored in pside_glue for later.
307238106Sdes	 * If it was never seen, at the end, then a negative caching element
308238106Sdes	 * must be created.
309238106Sdes	 * The (data or negative) RR cache element then throttles retries.
310238106Sdes	 */
311238106Sdes	int query_for_pside_glue;
312238106Sdes	/** the parent-side-glue element (NULL if none, its first match) */
313238106Sdes	struct ub_packed_rrset_key* pside_glue;
314238106Sdes
315238106Sdes	/** If nonNULL we are walking upwards from DS query to find NS */
316238106Sdes	uint8_t* dsns_point;
317238106Sdes	/** length of the dname in dsns_point */
318238106Sdes	size_t dsns_point_len;
319238106Sdes
320238106Sdes	/**
321238106Sdes	 * expected dnssec information for this iteration step.
322238106Sdes	 * If dnssec rrsigs are expected and not given, the server is marked
323238106Sdes	 * lame (dnssec-lame).
324238106Sdes	 */
325238106Sdes	int dnssec_expected;
326238106Sdes
327238106Sdes	/**
328238106Sdes	 * We are expecting dnssec information, but we also know the server
329238106Sdes	 * is DNSSEC lame.  The response need not be marked dnssec-lame again.
330238106Sdes	 */
331238106Sdes	int dnssec_lame_query;
332238106Sdes
333238106Sdes	/**
334238106Sdes	 * This is flag that, if true, means that this event is
335238106Sdes	 * waiting for a stub priming query.
336238106Sdes	 */
337238106Sdes	int wait_priming_stub;
338238106Sdes
339238106Sdes	/**
340238106Sdes	 * This is a flag that, if true, means that this query is
341238106Sdes	 * for (re)fetching glue from a zone. Since the address should
342238106Sdes	 * have been glue, query again to the servers that should have
343238106Sdes	 * been returning it as glue.
344238106Sdes	 * The delegation point must be set to the one that should *not*
345238106Sdes	 * be used when creating the state. A higher one will be attempted.
346238106Sdes	 */
347238106Sdes	int refetch_glue;
348238106Sdes
349238106Sdes	/** list of pending queries to authoritative servers. */
350238106Sdes	struct outbound_list outlist;
351294190Sdes
352294190Sdes	/** QNAME minimisation state */
353294190Sdes	enum minimisation_state minimisation_state;
354294190Sdes
355294190Sdes	/**
356294190Sdes	 * The query info that is sent upstream. Will be a subset of qchase
357294190Sdes	 * when qname minimisation is enabled.
358294190Sdes	 */
359294190Sdes	struct query_info qinfo_out;
360238106Sdes};
361238106Sdes
362238106Sdes/**
363238106Sdes * List of prepend items
364238106Sdes */
365238106Sdesstruct iter_prep_list {
366238106Sdes	/** next in list */
367238106Sdes	struct iter_prep_list* next;
368238106Sdes	/** rrset */
369238106Sdes	struct ub_packed_rrset_key* rrset;
370238106Sdes};
371238106Sdes
372238106Sdes/**
373238106Sdes * Get the iterator function block.
374238106Sdes * @return: function block with function pointers to iterator methods.
375238106Sdes */
376238106Sdesstruct module_func_block* iter_get_funcblock(void);
377238106Sdes
378238106Sdes/**
379238106Sdes * Get iterator state as a string
380238106Sdes * @param state: to convert
381238106Sdes * @return constant string that is printable.
382238106Sdes */
383238106Sdesconst char* iter_state_to_string(enum iter_state state);
384238106Sdes
385238106Sdes/**
386238106Sdes * See if iterator state is a response state
387238106Sdes * @param s: to inspect
388238106Sdes * @return true if response state.
389238106Sdes */
390238106Sdesint iter_state_is_responsestate(enum iter_state s);
391238106Sdes
392238106Sdes/** iterator init */
393238106Sdesint iter_init(struct module_env* env, int id);
394238106Sdes
395238106Sdes/** iterator deinit */
396238106Sdesvoid iter_deinit(struct module_env* env, int id);
397238106Sdes
398238106Sdes/** iterator operate on a query */
399238106Sdesvoid iter_operate(struct module_qstate* qstate, enum module_ev event, int id,
400238106Sdes	struct outbound_entry* outbound);
401238106Sdes
402238106Sdes/**
403238106Sdes * Return priming query results to interestes super querystates.
404238106Sdes *
405238106Sdes * Sets the delegation point and delegation message (not nonRD queries).
406238106Sdes * This is a callback from walk_supers.
407238106Sdes *
408238106Sdes * @param qstate: query state that finished.
409238106Sdes * @param id: module id.
410238106Sdes * @param super: the qstate to inform.
411238106Sdes */
412238106Sdesvoid iter_inform_super(struct module_qstate* qstate, int id,
413238106Sdes	struct module_qstate* super);
414238106Sdes
415238106Sdes/** iterator cleanup query state */
416238106Sdesvoid iter_clear(struct module_qstate* qstate, int id);
417238106Sdes
418238106Sdes/** iterator alloc size routine */
419238106Sdessize_t iter_get_mem(struct module_env* env, int id);
420238106Sdes
421238106Sdes#endif /* ITERATOR_ITERATOR_H */
422