]>
Commit | Line | Data |
---|---|---|
89c4ed63 A |
1 | /* |
2 | * util/module.h - DNS handling module interface | |
3 | * | |
4 | * Copyright (c) 2007, NLnet Labs. All rights reserved. | |
5 | * | |
6 | * This software is open source. | |
7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * | |
12 | * Redistributions of source code must retain the above copyright notice, | |
13 | * this list of conditions and the following disclaimer. | |
14 | * | |
15 | * Redistributions in binary form must reproduce the above copyright notice, | |
16 | * this list of conditions and the following disclaimer in the documentation | |
17 | * and/or other materials provided with the distribution. | |
18 | * | |
19 | * Neither the name of the NLNET LABS nor the names of its contributors may | |
20 | * be used to endorse or promote products derived from this software without | |
21 | * specific prior written permission. | |
22 | * | |
23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
26 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
27 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
29 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
30 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
31 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
32 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
33 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
34 | */ | |
35 | ||
36 | /** | |
37 | * \file | |
38 | * | |
39 | * This file contains the interface for DNS handling modules. | |
40 | * | |
41 | * The module interface uses the DNS modules as state machines. The | |
42 | * state machines are activated in sequence to operate on queries. Once | |
43 | * they are done, the reply is passed back. In the usual setup the mesh | |
44 | * is the caller of the state machines and once things are done sends replies | |
45 | * and invokes result callbacks. | |
46 | * | |
47 | * The module provides a number of functions, listed in the module_func_block. | |
48 | * The module is inited and destroyed and memory usage queries, for the | |
49 | * module as a whole, for entire-module state (such as a cache). And per-query | |
50 | * functions are called, operate to move the state machine and cleanup of | |
51 | * the per-query state. | |
52 | * | |
53 | * Most per-query state should simply be allocated in the query region. | |
54 | * This is destroyed at the end of the query. | |
55 | * | |
56 | * The module environment contains services and information and caches | |
57 | * shared by the modules and the rest of the system. It also contains | |
58 | * function pointers for module-specific tasks (like sending queries). | |
59 | * | |
60 | * *** Example module calls for a normal query | |
61 | * | |
62 | * In this example, the query does not need recursion, all the other data | |
63 | * can be found in the cache. This makes the example shorter. | |
64 | * | |
65 | * At the start of the program the iterator module is initialised. | |
66 | * The iterator module sets up its global state, such as donotquery lists | |
67 | * and private address trees. | |
68 | * | |
69 | * A query comes in, and a mesh entry is created for it. The mesh | |
70 | * starts the resolution process. The validator module is the first | |
71 | * in the list of modules, and it is started on this new query. The | |
72 | * operate() function is called. The validator decides it needs not do | |
73 | * anything yet until there is a result and returns wait_module, that | |
74 | * causes the next module in the list to be started. | |
75 | * | |
76 | * The next module is the iterator. It is started on the passed query and | |
77 | * decides to perform a lookup. For this simple example, the delegation | |
78 | * point information is available, and all the iterator wants to do is | |
79 | * send a UDP query. The iterator uses env.send_query() to send the | |
80 | * query. Then the iterator suspends (returns from the operate call). | |
81 | * | |
82 | * When the UDP reply comes back (and on errors and timeouts), the | |
83 | * operate function is called for the query, on the iterator module, | |
84 | * with the event that there is a reply. The iterator decides that this | |
85 | * is enough, the work is done. It returns the value finished from the | |
86 | * operate call, which causes the previous module to be started. | |
87 | * | |
88 | * The previous module, the validator module, is started with the event | |
89 | * that the iterator module is done. The validator decides to validate | |
90 | * the query. Once it is done (which could take recursive lookups, but | |
91 | * in this example no recursive lookups are needed), it returns from the | |
92 | * operate function with finished. | |
93 | * | |
94 | * There is no previous module from the validator module, and the mesh | |
95 | * takes this to mean that the query is finally done. The mesh invokes | |
96 | * callbacks and sends packets to queriers. | |
97 | * | |
98 | * If other modules had been waiting (recursively) on the answer to this | |
99 | * query, then the mesh will tell them about it. It calls the inform_super | |
100 | * routine on all the waiting modules, and once that is done it calls all of | |
101 | * them with the operate() call. During inform_super the query that is done | |
102 | * still exists and information can be copied from it (but the module should | |
103 | * not really re-entry codepoints and services). During the operate call | |
104 | * the modules can use stored state to continue operation with the results. | |
105 | * (network buffers are used to contain the answer packet during the | |
106 | * inform_super phase, but after that the network buffers will be cleared | |
107 | * of their contents so that other tasks can be performed). | |
108 | * | |
109 | * *** Example module calls for recursion | |
110 | * | |
111 | * A module is called in operate, and it decides that it wants to perform | |
112 | * recursion. That is, it wants the full state-machine-list to operate on | |
113 | * a different query. It calls env.attach_sub() to create a new query state. | |
114 | * The routine returns the newly created state, and potentially the module | |
115 | * can edit the module-states for the newly created query (i.e. pass along | |
116 | * some information, like delegation points). The module then suspends, | |
117 | * returns from the operate routine. | |
118 | * | |
119 | * The mesh meanwhile will have the newly created query (or queries) on | |
120 | * a waiting list, and will call operate() on this query (or queries). | |
121 | * It starts again at the start of the module list for them. The query | |
122 | * (or queries) continue to operate their state machines, until they are | |
123 | * done. When they are done the mesh calls inform_super on the module that | |
124 | * wanted the recursion. After that the mesh calls operate() on the module | |
125 | * that wanted to do the recursion, and during this phase the module could, | |
126 | * for example, decide to create more recursions. | |
127 | * | |
128 | * If the module decides it no longer wants the recursive information | |
129 | * it can call detach_subs. Those queries will still run to completion, | |
130 | * potentially filling the cache with information. Inform_super is not | |
131 | * called any more. | |
132 | * | |
133 | * The iterator module will fetch items from the cache, so a recursion | |
134 | * attempt may complete very quickly if the item is in cache. The calling | |
135 | * module has to wait for completion or eventual timeout. A recursive query | |
136 | * that times out returns a servfail rcode (servfail is also returned for | |
137 | * other errors during the lookup). | |
138 | * | |
139 | * Results are passed in the qstate, the rcode member is used to pass | |
140 | * errors without requiring memory allocation, so that the code can continue | |
141 | * in out-of-memory conditions. If the rcode member is 0 (NOERROR) then | |
142 | * the dns_msg entry contains a filled out message. This message may | |
143 | * also contain an rcode that is nonzero, but in this case additional | |
144 | * information (query, additional) can be passed along. | |
145 | * | |
146 | * The rcode and dns_msg are used to pass the result from the the rightmost | |
147 | * module towards the leftmost modules and then towards the user. | |
148 | * | |
149 | * If you want to avoid recursion-cycles where queries need other queries | |
150 | * that need the first one, use detect_cycle() to see if that will happen. | |
151 | * | |
152 | */ | |
153 | ||
154 | #ifndef UTIL_MODULE_H | |
155 | #define UTIL_MODULE_H | |
156 | #include "util/storage/lruhash.h" | |
157 | #include "util/data/msgreply.h" | |
158 | #include "util/data/msgparse.h" | |
159 | struct sldns_buffer; | |
160 | struct alloc_cache; | |
161 | struct rrset_cache; | |
162 | struct key_cache; | |
163 | struct config_file; | |
164 | struct slabhash; | |
165 | struct query_info; | |
166 | struct edns_data; | |
167 | struct regional; | |
168 | struct worker; | |
169 | struct module_qstate; | |
170 | struct ub_randstate; | |
171 | struct mesh_area; | |
172 | struct mesh_state; | |
173 | struct val_anchors; | |
174 | struct val_neg_cache; | |
175 | struct iter_forwards; | |
176 | struct iter_hints; | |
177 | ||
178 | /** Maximum number of modules in operation */ | |
179 | #define MAX_MODULE 5 | |
180 | ||
181 | /** | |
182 | * Module environment. | |
183 | * Services and data provided to the module. | |
184 | */ | |
185 | struct module_env { | |
186 | /* --- data --- */ | |
187 | /** config file with config options */ | |
188 | struct config_file* cfg; | |
189 | /** shared message cache */ | |
190 | struct slabhash* msg_cache; | |
191 | /** shared rrset cache */ | |
192 | struct rrset_cache* rrset_cache; | |
193 | /** shared infrastructure cache (edns, lameness) */ | |
194 | struct infra_cache* infra_cache; | |
195 | /** shared key cache */ | |
196 | struct key_cache* key_cache; | |
197 | ||
198 | /* --- services --- */ | |
199 | /** | |
200 | * Send serviced DNS query to server. UDP/TCP and EDNS is handled. | |
201 | * operate() should return with wait_reply. Later on a callback | |
202 | * will cause operate() to be called with event timeout or reply. | |
203 | * The time until a timeout is calculated from roundtrip timing, | |
204 | * several UDP retries are attempted. | |
205 | * @param qname: query name. (host order) | |
206 | * @param qnamelen: length in bytes of qname, including trailing 0. | |
207 | * @param qtype: query type. (host order) | |
208 | * @param qclass: query class. (host order) | |
209 | * @param flags: host order flags word, with opcode and CD bit. | |
210 | * @param dnssec: if set, EDNS record will have bits set. | |
211 | * If EDNS_DO bit is set, DO bit is set in EDNS records. | |
212 | * If BIT_CD is set, CD bit is set in queries with EDNS records. | |
213 | * @param want_dnssec: if set, the validator wants DNSSEC. Without | |
214 | * EDNS, the answer is likely to be useless for this domain. | |
215 | * @param nocaps: do not use caps_for_id, use the qname as given. | |
216 | * (ignored if caps_for_id is disabled). | |
217 | * @param addr: where to. | |
218 | * @param addrlen: length of addr. | |
219 | * @param zone: delegation point name. | |
220 | * @param zonelen: length of zone name. | |
221 | * @param q: wich query state to reactivate upon return. | |
222 | * @return: false on failure (memory or socket related). no query was | |
223 | * sent. Or returns an outbound entry with qsent and qstate set. | |
224 | * This outbound_entry will be used on later module invocations | |
225 | * that involve this query (timeout, error or reply). | |
226 | */ | |
227 | struct outbound_entry* (*send_query)(uint8_t* qname, size_t qnamelen, | |
228 | uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, | |
229 | int want_dnssec, int nocaps, struct sockaddr_storage* addr, | |
230 | socklen_t addrlen, uint8_t* zone, size_t zonelen, | |
231 | struct module_qstate* q); | |
232 | ||
233 | /** | |
234 | * Detach-subqueries. | |
235 | * Remove all sub-query references from this query state. | |
236 | * Keeps super-references of those sub-queries correct. | |
237 | * Updates stat items in mesh_area structure. | |
238 | * @param qstate: used to find mesh state. | |
239 | */ | |
240 | void (*detach_subs)(struct module_qstate* qstate); | |
241 | ||
242 | /** | |
243 | * Attach subquery. | |
244 | * Creates it if it does not exist already. | |
245 | * Keeps sub and super references correct. | |
246 | * Updates stat items in mesh_area structure. | |
247 | * Pass if it is priming query or not. | |
248 | * return: | |
249 | * o if error (malloc) happened. | |
250 | * o need to initialise the new state (module init; it is a new state). | |
251 | * so that the next run of the query with this module is successful. | |
252 | * o no init needed, attachment successful. | |
253 | * | |
254 | * @param qstate: the state to find mesh state, and that wants to | |
255 | * receive the results from the new subquery. | |
256 | * @param qinfo: what to query for (copied). | |
257 | * @param qflags: what flags to use (RD, CD flag or not). | |
258 | * @param prime: if it is a (stub) priming query. | |
259 | * @param valrec: validation lookup recursion, does not need validation | |
260 | * @param newq: If the new subquery needs initialisation, it is | |
261 | * returned, otherwise NULL is returned. | |
262 | * @return: false on error, true if success (and init may be needed). | |
263 | */ | |
264 | int (*attach_sub)(struct module_qstate* qstate, | |
265 | struct query_info* qinfo, uint16_t qflags, int prime, | |
266 | int valrec, struct module_qstate** newq); | |
267 | ||
268 | /** | |
269 | * Kill newly attached sub. If attach_sub returns newq for | |
270 | * initialisation, but that fails, then this routine will cleanup and | |
271 | * delete the fresly created sub. | |
272 | * @param newq: the new subquery that is no longer needed. | |
273 | * It is removed. | |
274 | */ | |
275 | void (*kill_sub)(struct module_qstate* newq); | |
276 | ||
277 | /** | |
278 | * Detect if adding a dependency for qstate on name,type,class will | |
279 | * create a dependency cycle. | |
280 | * @param qstate: given mesh querystate. | |
281 | * @param qinfo: query info for dependency. | |
282 | * @param flags: query flags of dependency, RD/CD flags. | |
283 | * @param prime: if dependency is a priming query or not. | |
284 | * @param valrec: validation lookup recursion, does not need validation | |
285 | * @return true if the name,type,class exists and the given | |
286 | * qstate mesh exists as a dependency of that name. Thus | |
287 | * if qstate becomes dependent on name,type,class then a | |
288 | * cycle is created. | |
289 | */ | |
290 | int (*detect_cycle)(struct module_qstate* qstate, | |
291 | struct query_info* qinfo, uint16_t flags, int prime, | |
292 | int valrec); | |
293 | ||
294 | /** region for temporary usage. May be cleared after operate() call. */ | |
295 | struct regional* scratch; | |
296 | /** buffer for temporary usage. May be cleared after operate() call. */ | |
297 | struct sldns_buffer* scratch_buffer; | |
298 | /** internal data for daemon - worker thread. */ | |
299 | struct worker* worker; | |
300 | /** mesh area with query state dependencies */ | |
301 | struct mesh_area* mesh; | |
302 | /** allocation service */ | |
303 | struct alloc_cache* alloc; | |
304 | /** random table to generate random numbers */ | |
305 | struct ub_randstate* rnd; | |
306 | /** time in seconds, converted to integer */ | |
307 | time_t* now; | |
308 | /** time in microseconds. Relatively recent. */ | |
309 | struct timeval* now_tv; | |
310 | /** is validation required for messages, controls client-facing | |
311 | * validation status (AD bits) and servfails */ | |
312 | int need_to_validate; | |
313 | /** trusted key storage; these are the configured keys, if not NULL, | |
314 | * otherwise configured by validator. These are the trust anchors, | |
315 | * and are not primed and ready for validation, but on the bright | |
316 | * side, they are read only memory, thus no locks and fast. */ | |
317 | struct val_anchors* anchors; | |
318 | /** negative cache, configured by the validator. if not NULL, | |
319 | * contains NSEC record lookup trees. */ | |
320 | struct val_neg_cache* neg_cache; | |
321 | /** the 5011-probe timer (if any) */ | |
322 | struct comm_timer* probe_timer; | |
323 | /** Mapping of forwarding zones to targets. | |
324 | * iterator forwarder information. per-thread, created by worker */ | |
325 | struct iter_forwards* fwds; | |
326 | /** | |
327 | * iterator forwarder information. per-thread, created by worker. | |
328 | * The hints -- these aren't stored in the cache because they don't | |
329 | * expire. The hints are always used to "prime" the cache. Note | |
330 | * that both root hints and stub zone "hints" are stored in this | |
331 | * data structure. | |
332 | */ | |
333 | struct iter_hints* hints; | |
334 | /** module specific data. indexed by module id. */ | |
335 | void* modinfo[MAX_MODULE]; | |
336 | }; | |
337 | ||
338 | /** | |
339 | * External visible states of the module state machine | |
340 | * Modules may also have an internal state. | |
341 | * Modules are supposed to run to completion or until blocked. | |
342 | */ | |
343 | enum module_ext_state { | |
344 | /** initial state - new query */ | |
345 | module_state_initial = 0, | |
346 | /** waiting for reply to outgoing network query */ | |
347 | module_wait_reply, | |
348 | /** module is waiting for another module */ | |
349 | module_wait_module, | |
350 | /** module is waiting for another module; that other is restarted */ | |
351 | module_restart_next, | |
352 | /** module is waiting for sub-query */ | |
353 | module_wait_subquery, | |
354 | /** module could not finish the query */ | |
355 | module_error, | |
356 | /** module is finished with query */ | |
357 | module_finished | |
358 | }; | |
359 | ||
360 | /** | |
361 | * Events that happen to modules, that start or wakeup modules. | |
362 | */ | |
363 | enum module_ev { | |
364 | /** new query */ | |
365 | module_event_new = 0, | |
366 | /** query passed by other module */ | |
367 | module_event_pass, | |
368 | /** reply inbound from server */ | |
369 | module_event_reply, | |
370 | /** no reply, timeout or other error */ | |
371 | module_event_noreply, | |
372 | /** reply is there, but capitalisation check failed */ | |
373 | module_event_capsfail, | |
374 | /** next module is done, and its reply is awaiting you */ | |
375 | module_event_moddone, | |
376 | /** error */ | |
377 | module_event_error | |
378 | }; | |
379 | ||
380 | /** | |
381 | * Linked list of sockaddrs | |
382 | * May be allocated such that only 'len' bytes of addr exist for the structure. | |
383 | */ | |
384 | struct sock_list { | |
385 | /** next in list */ | |
386 | struct sock_list* next; | |
387 | /** length of addr */ | |
388 | socklen_t len; | |
389 | /** sockaddr */ | |
390 | struct sockaddr_storage addr; | |
391 | }; | |
392 | ||
393 | /** | |
394 | * Module state, per query. | |
395 | */ | |
396 | struct module_qstate { | |
397 | /** which query is being answered: name, type, class */ | |
398 | struct query_info qinfo; | |
399 | /** flags uint16 from query */ | |
400 | uint16_t query_flags; | |
401 | /** if this is a (stub or root) priming query (with hints) */ | |
402 | int is_priming; | |
403 | /** if this is a validation recursion query that does not get | |
404 | * validation itself */ | |
405 | int is_valrec; | |
406 | ||
407 | /** comm_reply contains server replies */ | |
408 | struct comm_reply* reply; | |
409 | /** the reply message, with message for client and calling module */ | |
410 | struct dns_msg* return_msg; | |
411 | /** the rcode, in case of error, instead of a reply message */ | |
412 | int return_rcode; | |
413 | /** origin of the reply (can be NULL from cache, list for cnames) */ | |
414 | struct sock_list* reply_origin; | |
415 | /** IP blacklist for queries */ | |
416 | struct sock_list* blacklist; | |
417 | /** region for this query. Cleared when query process finishes. */ | |
418 | struct regional* region; | |
419 | /** failure reason information if val-log-level is high */ | |
420 | struct config_strlist* errinf; | |
421 | ||
422 | /** which module is executing */ | |
423 | int curmod; | |
424 | /** module states */ | |
425 | enum module_ext_state ext_state[MAX_MODULE]; | |
426 | /** module specific data for query. indexed by module id. */ | |
427 | void* minfo[MAX_MODULE]; | |
428 | /** environment for this query */ | |
429 | struct module_env* env; | |
430 | /** mesh related information for this query */ | |
431 | struct mesh_state* mesh_info; | |
432 | /** how many seconds before expiry is this prefetched (0 if not) */ | |
433 | time_t prefetch_leeway; | |
434 | }; | |
435 | ||
436 | /** | |
437 | * Module functionality block | |
438 | */ | |
439 | struct module_func_block { | |
440 | /** text string name of module */ | |
441 | const char* name; | |
442 | ||
443 | /** | |
444 | * init the module. Called once for the global state. | |
445 | * This is the place to apply settings from the config file. | |
446 | * @param env: module environment. | |
447 | * @param id: module id number. | |
448 | * return: 0 on error | |
449 | */ | |
450 | int (*init)(struct module_env* env, int id); | |
451 | ||
452 | /** | |
453 | * de-init, delete, the module. Called once for the global state. | |
454 | * @param env: module environment. | |
455 | * @param id: module id number. | |
456 | */ | |
457 | void (*deinit)(struct module_env* env, int id); | |
458 | ||
459 | /** | |
460 | * accept a new query, or work further on existing query. | |
461 | * Changes the qstate->ext_state to be correct on exit. | |
462 | * @param ev: event that causes the module state machine to | |
463 | * (re-)activate. | |
464 | * @param qstate: the query state. | |
465 | * Note that this method is not allowed to change the | |
466 | * query state 'identity', that is query info, qflags, | |
467 | * and priming status. | |
468 | * Attach a subquery to get results to a different query. | |
469 | * @param id: module id number that operate() is called on. | |
470 | * @param outbound: if not NULL this event is due to the reply/timeout | |
471 | * or error on this outbound query. | |
472 | * @return: if at exit the ext_state is: | |
473 | * o wait_module: next module is started. (with pass event). | |
474 | * o error or finished: previous module is resumed. | |
475 | * o otherwise it waits until that event happens (assumes | |
476 | * the service routine to make subrequest or send message | |
477 | * have been called. | |
478 | */ | |
479 | void (*operate)(struct module_qstate* qstate, enum module_ev event, | |
480 | int id, struct outbound_entry* outbound); | |
481 | ||
482 | /** | |
483 | * inform super querystate about the results from this subquerystate. | |
484 | * Is called when the querystate is finished. The method invoked is | |
485 | * the one from the current module active in the super querystate. | |
486 | * @param qstate: the query state that is finished. | |
487 | * Examine return_rcode and return_reply in the qstate. | |
488 | * @param id: module id for this module. | |
489 | * This coincides with the current module for the super qstate. | |
490 | * @param super: the super querystate that needs to be informed. | |
491 | */ | |
492 | void (*inform_super)(struct module_qstate* qstate, int id, | |
493 | struct module_qstate* super); | |
494 | ||
495 | /** | |
496 | * clear module specific data | |
497 | */ | |
498 | void (*clear)(struct module_qstate* qstate, int id); | |
499 | ||
500 | /** | |
501 | * How much memory is the module specific data using. | |
502 | * @param env: module environment. | |
503 | * @param id: the module id. | |
504 | * @return the number of bytes that are alloced. | |
505 | */ | |
506 | size_t (*get_mem)(struct module_env* env, int id); | |
507 | }; | |
508 | ||
509 | /** | |
510 | * Debug utility: module external qstate to string | |
511 | * @param s: the state value. | |
512 | * @return descriptive string. | |
513 | */ | |
514 | const char* strextstate(enum module_ext_state s); | |
515 | ||
516 | /** | |
517 | * Debug utility: module event to string | |
518 | * @param e: the module event value. | |
519 | * @return descriptive string. | |
520 | */ | |
521 | const char* strmodulevent(enum module_ev e); | |
522 | ||
523 | #endif /* UTIL_MODULE_H */ |