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