iterator.h revision 285206
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;
54238106Sdes
55275853Sdelphij/** max number of targets spawned for a query and its subqueries */
56275853Sdelphij#define MAX_TARGET_COUNT	32
57238106Sdes/** max number of query restarts. Determines max number of CNAME chain. */
58238106Sdes#define MAX_RESTART_COUNT       8
59238106Sdes/** max number of referrals. Makes sure resolver does not run away */
60238106Sdes#define MAX_REFERRAL_COUNT	130
61238106Sdes/** max number of queries-sent-out.  Make sure large NS set does not loop */
62285206Sdes#define MAX_SENT_COUNT		32
63238106Sdes/** at what query-sent-count to stop target fetch policy */
64238106Sdes#define TARGET_FETCH_STOP	3
65238106Sdes/** how nice is a server without further information, in msec
66238106Sdes * Equals rtt initial timeout value.
67238106Sdes */
68238106Sdes#define UNKNOWN_SERVER_NICENESS 376
69238106Sdes/** maximum timeout before a host is deemed unsuitable, in msec.
70238106Sdes * After host_ttl this will be timed out and the host will be tried again.
71238106Sdes * Equals RTT_MAX_TIMEOUT
72238106Sdes */
73238106Sdes#define USEFUL_SERVER_TOP_TIMEOUT	120000
74238106Sdes/** number of retries on outgoing queries */
75238106Sdes#define OUTBOUND_MSG_RETRY 5
76238106Sdes/** RTT band, within this amount from the best, servers are chosen randomly.
77238106Sdes * Chosen so that the UNKNOWN_SERVER_NICENESS falls within the band of a
78238106Sdes * fast server, this causes server exploration as a side benefit. msec. */
79238106Sdes#define RTT_BAND 400
80238106Sdes/** Start value for blacklisting a host, 2*USEFUL_SERVER_TOP_TIMEOUT in sec */
81238106Sdes#define INFRA_BACKOFF_INITIAL 240
82238106Sdes
83238106Sdes/**
84238106Sdes * Global state for the iterator.
85238106Sdes */
86238106Sdesstruct iter_env {
87238106Sdes	/** A flag to indicate whether or not we have an IPv6 route */
88238106Sdes	int supports_ipv6;
89238106Sdes
90238106Sdes	/** A flag to indicate whether or not we have an IPv4 route */
91238106Sdes	int supports_ipv4;
92238106Sdes
93238106Sdes	/** A set of inetaddrs that should never be queried. */
94238106Sdes	struct iter_donotq* donotq;
95238106Sdes
96238106Sdes	/** private address space and private domains */
97238106Sdes	struct iter_priv* priv;
98238106Sdes
99238106Sdes	/** The maximum dependency depth that this resolver will pursue. */
100238106Sdes	int max_dependency_depth;
101238106Sdes
102238106Sdes	/**
103238106Sdes	 * The target fetch policy for each dependency level. This is
104238106Sdes	 * described as a simple number (per dependency level):
105238106Sdes	 *	negative numbers (usually just -1) mean fetch-all,
106238106Sdes	 *	0 means only fetch on demand, and
107238106Sdes	 *	positive numbers mean to fetch at most that many targets.
108238106Sdes	 * array of max_dependency_depth+1 size.
109238106Sdes	 */
110238106Sdes	int* target_fetch_policy;
111238106Sdes};
112238106Sdes
113238106Sdes/**
114238106Sdes * State of the iterator for a query.
115238106Sdes */
116238106Sdesenum iter_state {
117238106Sdes	/**
118238106Sdes	 * Externally generated queries start at this state. Query restarts are
119238106Sdes	 * reset to this state.
120238106Sdes	 */
121238106Sdes	INIT_REQUEST_STATE = 0,
122238106Sdes
123238106Sdes	/**
124238106Sdes	 * Root priming events reactivate here, most other events pass
125238106Sdes	 * through this naturally as the 2nd part of the INIT_REQUEST_STATE.
126238106Sdes	 */
127238106Sdes	INIT_REQUEST_2_STATE,
128238106Sdes
129238106Sdes	/**
130238106Sdes	 * Stub priming events reactivate here, most other events pass
131238106Sdes	 * through this naturally as the 3rd part of the INIT_REQUEST_STATE.
132238106Sdes	 */
133238106Sdes	INIT_REQUEST_3_STATE,
134238106Sdes
135238106Sdes	/**
136238106Sdes	 * Each time a delegation point changes for a given query or a
137238106Sdes	 * query times out and/or wakes up, this state is (re)visited.
138238106Sdes	 * This state is reponsible for iterating through a list of
139238106Sdes	 * nameserver targets.
140238106Sdes	 */
141238106Sdes	QUERYTARGETS_STATE,
142238106Sdes
143238106Sdes	/**
144238106Sdes	 * Responses to queries start at this state. This state handles
145238106Sdes	 * the decision tree associated with handling responses.
146238106Sdes	 */
147238106Sdes	QUERY_RESP_STATE,
148238106Sdes
149238106Sdes	/** Responses to priming queries finish at this state. */
150238106Sdes	PRIME_RESP_STATE,
151238106Sdes
152238106Sdes	/** Collecting query class information, for qclass=ANY, when
153238106Sdes	 * it spawns off queries for every class, it returns here. */
154238106Sdes	COLLECT_CLASS_STATE,
155238106Sdes
156238106Sdes	/** Find NS record to resolve DS record from, walking to the right
157238106Sdes	 * NS spot until we find it */
158238106Sdes	DSNS_FIND_STATE,
159238106Sdes
160238106Sdes	/** Responses that are to be returned upstream end at this state.
161238106Sdes	 * As well as responses to target queries. */
162238106Sdes	FINISHED_STATE
163238106Sdes};
164238106Sdes
165238106Sdes/**
166238106Sdes * Per query state for the iterator module.
167238106Sdes */
168238106Sdesstruct iter_qstate {
169238106Sdes	/**
170238106Sdes	 * State of the iterator module.
171238106Sdes	 * This is the state that event is in or should sent to -- all
172238106Sdes	 * requests should start with the INIT_REQUEST_STATE. All
173238106Sdes	 * responses should start with QUERY_RESP_STATE. Subsequent
174238106Sdes	 * processing of the event will change this state.
175238106Sdes	 */
176238106Sdes	enum iter_state state;
177238106Sdes
178238106Sdes	/**
179238106Sdes	 * Final state for the iterator module.
180238106Sdes	 * This is the state that responses should be routed to once the
181238106Sdes	 * response is final. For externally initiated queries, this
182238106Sdes	 * will be FINISHED_STATE, locally initiated queries will have
183238106Sdes	 * different final states.
184238106Sdes	 */
185238106Sdes	enum iter_state final_state;
186238106Sdes
187238106Sdes	/**
188238106Sdes	 * The depth of this query, this means the depth of recursion.
189238106Sdes	 * This address is needed for another query, which is an address
190238106Sdes	 * needed for another query, etc. Original client query has depth 0.
191238106Sdes	 */
192238106Sdes	int depth;
193238106Sdes
194238106Sdes	/**
195238106Sdes	 * The response
196238106Sdes	 */
197238106Sdes	struct dns_msg* response;
198238106Sdes
199238106Sdes	/**
200238106Sdes	 * This is a list of RRsets that must be prepended to the
201238106Sdes	 * ANSWER section of a response before being sent upstream.
202238106Sdes	 */
203238106Sdes	struct iter_prep_list* an_prepend_list;
204238106Sdes	/** Last element of the prepend list */
205238106Sdes	struct iter_prep_list* an_prepend_last;
206238106Sdes
207238106Sdes	/**
208238106Sdes	 * This is the list of RRsets that must be prepended to the
209238106Sdes	 * AUTHORITY section of the response before being sent upstream.
210238106Sdes	 */
211238106Sdes	struct iter_prep_list* ns_prepend_list;
212238106Sdes	/** Last element of the authority prepend list */
213238106Sdes	struct iter_prep_list* ns_prepend_last;
214238106Sdes
215238106Sdes	/** query name used for chasing the results. Initially the same as
216238106Sdes	 * the state qinfo, but after CNAMEs this will be different.
217238106Sdes	 * The query info used to elicit the results needed. */
218238106Sdes	struct query_info qchase;
219238106Sdes	/** query flags to use when chasing the answer (i.e. RD flag) */
220238106Sdes	uint16_t chase_flags;
221238106Sdes	/** true if we set RD bit because of last resort recursion lame query*/
222238106Sdes	int chase_to_rd;
223238106Sdes
224238106Sdes	/**
225238106Sdes	 * This is the current delegation point for an in-progress query. This
226238106Sdes	 * object retains state as to which delegation targets need to be
227238106Sdes	 * (sub)queried for vs which ones have already been visited.
228238106Sdes	 */
229238106Sdes	struct delegpt* dp;
230238106Sdes
231238106Sdes	/** state for 0x20 fallback when capsfail happens, 0 not a fallback */
232238106Sdes	int caps_fallback;
233238106Sdes	/** state for capsfail: current server number to try */
234238106Sdes	size_t caps_server;
235285206Sdes	/** state for capsfail: stored query for comparisons. Can be NULL if
236285206Sdes	 * no response had been seen prior to starting the fallback. */
237238106Sdes	struct reply_info* caps_reply;
238238106Sdes
239238106Sdes	/** Current delegation message - returned for non-RD queries */
240238106Sdes	struct dns_msg* deleg_msg;
241238106Sdes
242238106Sdes	/** number of outstanding target sub queries */
243238106Sdes	int num_target_queries;
244238106Sdes
245238106Sdes	/** outstanding direct queries */
246238106Sdes	int num_current_queries;
247238106Sdes
248238106Sdes	/** the number of times this query has been restarted. */
249238106Sdes	int query_restart_count;
250238106Sdes
251238106Sdes	/** the number of times this query as followed a referral. */
252238106Sdes	int referral_count;
253238106Sdes
254238106Sdes	/** number of queries fired off */
255238106Sdes	int sent_count;
256275853Sdelphij
257275853Sdelphij	/** number of target queries spawned in [1], for this query and its
258275853Sdelphij	 * subqueries, the malloced-array is shared, [0] refcount. */
259275853Sdelphij	int* target_count;
260238106Sdes
261238106Sdes	/**
262238106Sdes	 * The query must store NS records from referrals as parentside RRs
263238106Sdes	 * Enabled once it hits resolution problems, to throttle retries.
264238106Sdes	 * If enabled it is the pointer to the old delegation point with
265238106Sdes	 * the old retry counts for bad-nameserver-addresses.
266238106Sdes	 */
267238106Sdes	struct delegpt* store_parent_NS;
268238106Sdes
269238106Sdes	/**
270238106Sdes	 * The query is for parent-side glue(A or AAAA) for a nameserver.
271238106Sdes	 * If the item is seen as glue in a referral, and pside_glue is NULL,
272238106Sdes	 * then it is stored in pside_glue for later.
273238106Sdes	 * If it was never seen, at the end, then a negative caching element
274238106Sdes	 * must be created.
275238106Sdes	 * The (data or negative) RR cache element then throttles retries.
276238106Sdes	 */
277238106Sdes	int query_for_pside_glue;
278238106Sdes	/** the parent-side-glue element (NULL if none, its first match) */
279238106Sdes	struct ub_packed_rrset_key* pside_glue;
280238106Sdes
281238106Sdes	/** If nonNULL we are walking upwards from DS query to find NS */
282238106Sdes	uint8_t* dsns_point;
283238106Sdes	/** length of the dname in dsns_point */
284238106Sdes	size_t dsns_point_len;
285238106Sdes
286238106Sdes	/**
287238106Sdes	 * expected dnssec information for this iteration step.
288238106Sdes	 * If dnssec rrsigs are expected and not given, the server is marked
289238106Sdes	 * lame (dnssec-lame).
290238106Sdes	 */
291238106Sdes	int dnssec_expected;
292238106Sdes
293238106Sdes	/**
294238106Sdes	 * We are expecting dnssec information, but we also know the server
295238106Sdes	 * is DNSSEC lame.  The response need not be marked dnssec-lame again.
296238106Sdes	 */
297238106Sdes	int dnssec_lame_query;
298238106Sdes
299238106Sdes	/**
300238106Sdes	 * This is flag that, if true, means that this event is
301238106Sdes	 * waiting for a stub priming query.
302238106Sdes	 */
303238106Sdes	int wait_priming_stub;
304238106Sdes
305238106Sdes	/**
306238106Sdes	 * This is a flag that, if true, means that this query is
307238106Sdes	 * for (re)fetching glue from a zone. Since the address should
308238106Sdes	 * have been glue, query again to the servers that should have
309238106Sdes	 * been returning it as glue.
310238106Sdes	 * The delegation point must be set to the one that should *not*
311238106Sdes	 * be used when creating the state. A higher one will be attempted.
312238106Sdes	 */
313238106Sdes	int refetch_glue;
314238106Sdes
315238106Sdes	/** list of pending queries to authoritative servers. */
316238106Sdes	struct outbound_list outlist;
317238106Sdes};
318238106Sdes
319238106Sdes/**
320238106Sdes * List of prepend items
321238106Sdes */
322238106Sdesstruct iter_prep_list {
323238106Sdes	/** next in list */
324238106Sdes	struct iter_prep_list* next;
325238106Sdes	/** rrset */
326238106Sdes	struct ub_packed_rrset_key* rrset;
327238106Sdes};
328238106Sdes
329238106Sdes/**
330238106Sdes * Get the iterator function block.
331238106Sdes * @return: function block with function pointers to iterator methods.
332238106Sdes */
333238106Sdesstruct module_func_block* iter_get_funcblock(void);
334238106Sdes
335238106Sdes/**
336238106Sdes * Get iterator state as a string
337238106Sdes * @param state: to convert
338238106Sdes * @return constant string that is printable.
339238106Sdes */
340238106Sdesconst char* iter_state_to_string(enum iter_state state);
341238106Sdes
342238106Sdes/**
343238106Sdes * See if iterator state is a response state
344238106Sdes * @param s: to inspect
345238106Sdes * @return true if response state.
346238106Sdes */
347238106Sdesint iter_state_is_responsestate(enum iter_state s);
348238106Sdes
349238106Sdes/** iterator init */
350238106Sdesint iter_init(struct module_env* env, int id);
351238106Sdes
352238106Sdes/** iterator deinit */
353238106Sdesvoid iter_deinit(struct module_env* env, int id);
354238106Sdes
355238106Sdes/** iterator operate on a query */
356238106Sdesvoid iter_operate(struct module_qstate* qstate, enum module_ev event, int id,
357238106Sdes	struct outbound_entry* outbound);
358238106Sdes
359238106Sdes/**
360238106Sdes * Return priming query results to interestes super querystates.
361238106Sdes *
362238106Sdes * Sets the delegation point and delegation message (not nonRD queries).
363238106Sdes * This is a callback from walk_supers.
364238106Sdes *
365238106Sdes * @param qstate: query state that finished.
366238106Sdes * @param id: module id.
367238106Sdes * @param super: the qstate to inform.
368238106Sdes */
369238106Sdesvoid iter_inform_super(struct module_qstate* qstate, int id,
370238106Sdes	struct module_qstate* super);
371238106Sdes
372238106Sdes/** iterator cleanup query state */
373238106Sdesvoid iter_clear(struct module_qstate* qstate, int id);
374238106Sdes
375238106Sdes/** iterator alloc size routine */
376238106Sdessize_t iter_get_mem(struct module_env* env, int id);
377238106Sdes
378238106Sdes#endif /* ITERATOR_ITERATOR_H */
379