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