unbound: util/module.h File Reference

unbound 0.1

Data Structures | Macros | Typedefs | Enumerations | Functions
module.h File Reference

This file contains the interface for DNS handling modules. More...

`#include "util/storage/lruhash.h"`
`#include "util/data/msgreply.h"`
`#include "util/data/msgparse.h"`

## Data Structures
struct | errinf_strlist
struct | edns_known_option
| Known edns option. More...
struct | inplace_cb
| Inplace callback list of registered routines to be called. More...
struct | module_env
| Module environment. More...
struct | sock_list
| Linked list of sockaddrs May be allocated such that only 'len' bytes of addr exist for the structure. More...
struct | serve_expired_data
| Struct to hold relevant data for serve expired. More...
struct | module_qstate
| Module state, per query. More...
struct | module_func_block
| Module functionality block. More...

## Macros
#define | MAX_MODULE 16
| Maximum number of modules in operation.
#define | MAX_KNOWN_EDNS_OPTS 256
| Maximum number of known edns options.

## Typedefs
typedef int | inplace_cb_reply_func_type(struct query_info *qinfo, struct module_qstate *qstate, struct reply_info *rep, int rcode, struct edns_data *edns, struct edns_option **opt_list_out, struct comm_reply *repinfo, struct regional *region, struct timeval *start_time, int id, void *callback)
| Inplace callback function called before replying.
typedef int | inplace_cb_query_func_type(struct query_info *qinfo, uint16_t flags, struct module_qstate *qstate, struct sockaddr_storage *addr, socklen_t addrlen, uint8_t *zone, size_t zonelen, struct regional *region, int id, void *callback)
| Inplace callback function called before sending the query to a nameserver.
typedef int | inplace_cb_edns_back_parsed_func_type(struct module_qstate *qstate, int id, void *cb_args)
| Inplace callback function called after parsing edns on query reply.
typedef int | inplace_cb_query_response_func_type(struct module_qstate *qstate, struct dns_msg *response, int id, void *cb_args)
| Inplace callback function called after parsing query response.
typedef struct dns_msg * | serve_expired_lookup_func_type(struct module_qstate *qstate, struct query_info *lookup_qinfo)
| Function called when looking for (expired) cached answers during the serve expired logic.

## Enumerations
enum | inplace_cb_list_type { inplace_cb_reply = 0 , inplace_cb_reply_cache , inplace_cb_reply_local , inplace_cb_reply_servfail , inplace_cb_query , inplace_cb_query_response , inplace_cb_edns_back_parsed , inplace_cb_types_total }
enum | module_ext_state { module_state_initial = 0 , module_wait_reply , module_wait_module , module_restart_next , module_wait_subquery , module_error , module_finished }
| External visible states of the module state machine Modules may also have an internal state. More...
enum | module_ev { module_event_new = 0 , module_event_pass , module_event_reply , module_event_noreply , module_event_capsfail , module_event_moddone , module_event_error }
| Events that happen to modules, that start or wakeup modules. More...

## Functions
const char * | strextstate (enum module_ext_state s)
| Debug utility: module external qstate to string.
const char * | strmodulevent (enum module_ev e)
| Debug utility: module event to string.
void | errinf (struct module_qstate *qstate, const char *str)
| Append text to the error info for validation.
void | errinf_ede (struct module_qstate *qstate, const char *str, sldns_ede_code reason_bogus)
void | errinf_origin (struct module_qstate *qstate, struct sock_list *origin)
| Append text to error info: from 1.2.3.4.
void | errinf_rrset (struct module_qstate *qstate, struct ub_packed_rrset_key *rr)
| Append text to error info: for RRset name type class.
void | errinf_dname (struct module_qstate *qstate, const char *str, uint8_t *dname)
| Append text to error info: str dname.
char * | errinf_to_str_bogus (struct module_qstate *qstate, struct regional *region)
| Create error info in string.
sldns_ede_code | errinf_to_reason_bogus (struct module_qstate *qstate)
| Check the sldns_ede_code of the qstate->errinf.
char * | errinf_to_str_servfail (struct module_qstate *qstate)
| Create error info in string.
char * | errinf_to_str_misc (struct module_qstate *qstate)
| Create error info in string.
int | edns_known_options_init (struct module_env *env)
| Initialize the edns known options by allocating the required space.
void | edns_known_options_delete (struct module_env *env)
| Free the allocated space for the known edns options.
int | edns_register_option (uint16_t opt_code, int bypass_cache_stage, int no_aggregation, struct module_env *env)
| Register a known edns option.
int | inplace_cb_register (void *cb, enum inplace_cb_list_type type, void *cbarg, struct module_env *env, int id)
| Register an inplace callback function.
void | inplace_cb_delete (struct module_env *env, enum inplace_cb_list_type type, int id)
| Delete callback for specified type and module id.
void | inplace_cb_lists_delete (struct module_env *env)
| Delete all the inplace callback linked lists.
struct edns_known_option * | edns_option_is_known (uint16_t opt_code, struct module_env *env)
| Check if an edns option is known.
int | edns_bypass_cache_stage (struct edns_option *list, struct module_env *env)
| Check if an edns option needs to bypass the reply from cache stage.
int | unique_mesh_state (struct edns_option *list, struct module_env *env)
| Check if an unique mesh state is required.
void | log_edns_known_options (enum verbosity_value level, struct module_env *env)
| Log the known edns options.
void | copy_state_to_super (struct module_qstate *qstate, int id, struct module_qstate *super)
| Copy state that may have happened in the subquery and is always relevant to the super.

## Detailed Description

This file contains the interface for DNS handling modules.

The module interface uses the DNS modules as state machines. The state machines are activated in sequence to operate on queries. Once they are done, the reply is passed back. In the usual setup the mesh is the caller of the state machines and once things are done sends replies and invokes result callbacks.

The module provides a number of functions, listed in the module_func_block. The module is inited and destroyed and memory usage queries, for the module as a whole, for entire-module state (such as a cache). And per-query functions are called, operate to move the state machine and cleanup of the per-query state.

Most per-query state should simply be allocated in the query region. This is destroyed at the end of the query.

The module environment contains services and information and caches shared by the modules and the rest of the system. It also contains function pointers for module-specific tasks (like sending queries).

*** Example module calls for a normal query

In this example, the query does not need recursion, all the other data can be found in the cache. This makes the example shorter.

At the start of the program the iterator module is initialised. The iterator module sets up its global state, such as donotquery lists and private address trees.

A query comes in, and a mesh entry is created for it. The mesh starts the resolution process. The validator module is the first in the list of modules, and it is started on this new query. The operate() function is called. The validator decides it needs not do anything yet until there is a result and returns wait_module, that causes the next module in the list to be started.

The next module is the iterator. It is started on the passed query and decides to perform a lookup. For this simple example, the delegation point information is available, and all the iterator wants to do is send a UDP query. The iterator uses env.send_query() to send the query. Then the iterator suspends (returns from the operate call).

When the UDP reply comes back (and on errors and timeouts), the operate function is called for the query, on the iterator module, with the event that there is a reply. The iterator decides that this is enough, the work is done. It returns the value finished from the operate call, which causes the previous module to be started.

The previous module, the validator module, is started with the event that the iterator module is done. The validator decides to validate the query. Once it is done (which could take recursive lookups, but in this example no recursive lookups are needed), it returns from the operate function with finished.

There is no previous module from the validator module, and the mesh takes this to mean that the query is finally done. The mesh invokes callbacks and sends packets to queriers.

If other modules had been waiting (recursively) on the answer to this query, then the mesh will tell them about it. It calls the inform_super routine on all the waiting modules, and once that is done it calls all of them with the operate() call. During inform_super the query that is done still exists and information can be copied from it (but the module should not really re-entry codepoints and services). During the operate call the modules can use stored state to continue operation with the results. (network buffers are used to contain the answer packet during the inform_super phase, but after that the network buffers will be cleared of their contents so that other tasks can be performed).

*** Example module calls for recursion

A module is called in operate, and it decides that it wants to perform recursion. That is, it wants the full state-machine-list to operate on a different query. It calls env.attach_sub() to create a new query state. The routine returns the newly created state, and potentially the module can edit the module-states for the newly created query (i.e. pass along some information, like delegation points). The module then suspends, returns from the operate routine.

The mesh meanwhile will have the newly created query (or queries) on a waiting list, and will call operate() on this query (or queries). It starts again at the start of the module list for them. The query (or queries) continue to operate their state machines, until they are done. When they are done the mesh calls inform_super on the module that wanted the recursion. After that the mesh calls operate() on the module that wanted to do the recursion, and during this phase the module could, for example, decide to create more recursions.

If the module decides it no longer wants the recursive information it can call detach_subs. Those queries will still run to completion, potentially filling the cache with information. Inform_super is not called any more.

The iterator module will fetch items from the cache, so a recursion attempt may complete very quickly if the item is in cache. The calling module has to wait for completion or eventual timeout. A recursive query that times out returns a servfail rcode (servfail is also returned for other errors during the lookup).

Results are passed in the qstate, the rcode member is used to pass errors without requiring memory allocation, so that the code can continue in out-of-memory conditions. If the rcode member is 0 (NOERROR) then the dns_msg entry contains a filled out message. This message may also contain an rcode that is nonzero, but in this case additional information (query, additional) can be passed along.

The rcode and dns_msg are used to pass the result from the rightmost module towards the leftmost modules and then towards the user.

If you want to avoid recursion-cycles where queries need other queries that need the first one, use detect_cycle() to see if that will happen.

## Typedef Documentation

## ◆ inplace_cb_reply_func_type

typedef int inplace_cb_reply_func_type(struct query_info *qinfo, struct module_qstate *qstate, struct reply_info *rep, int rcode, struct edns_data *edns, struct edns_option **opt_list_out, struct comm_reply *repinfo, struct regional *region, struct timeval *start_time, int id, void *callback)

Inplace callback function called before replying.

Called as func(qinfo, qstate, rep, rcode, edns, opt_list_out, repinfo, region, id, python_callback) Where: qinfo: the query info. qstate: the module state. NULL when calling before the query reaches the mesh states. rep: reply_info. Could be NULL. rcode: the return code. edns: the edns_data of the reply. When qstate is NULL, it is also used as the edns input. opt_list_out: the edns options list for the reply. repinfo: reply information for a communication point. NULL when calling during the mesh states; the same could be found from qstate->mesh_info->reply_list. region: region to store data. id: module id. python_callback: only used for registering a python callback function.

## ◆ inplace_cb_query_func_type

typedef int inplace_cb_query_func_type(struct query_info *qinfo, uint16_t flags, struct module_qstate *qstate, struct sockaddr_storage *addr, socklen_t addrlen, uint8_t *zone, size_t zonelen, struct regional *region, int id, void *callback)

Inplace callback function called before sending the query to a nameserver.

Called as func(qinfo, flags, qstate, addr, addrlen, zone, zonelen, region, id, python_callback) Where: qinfo: query info. flags: flags of the query. qstate: query state. addr: to which server to send the query. addrlen: length of addr. zone: name of the zone of the delegation point. wireformat dname. This is the delegation point name for which the server is deemed authoritative. zonelen: length of zone. region: region to store data. id: module id. python_callback: only used for registering a python callback function.

## ◆ inplace_cb_edns_back_parsed_func_type

typedef int inplace_cb_edns_back_parsed_func_type(struct module_qstate *qstate, int id, void *cb_args)

Inplace callback function called after parsing edns on query reply.

Called as func(qstate, id, cb_args) Where: qstate: the query state. id: module id. cb_args: argument passed when registering callback.

## ◆ inplace_cb_query_response_func_type

typedef int inplace_cb_query_response_func_type(struct module_qstate *qstate, struct dns_msg *response, int id, void *cb_args)

Inplace callback function called after parsing query response.

Called as func(qstate, response, id, cb_args) Where: qstate: the query state. response: query response. id: module id. cb_args: argument passed when registering callback.

## ◆ serve_expired_lookup_func_type

typedef struct dns_msg * serve_expired_lookup_func_type(struct module_qstate *qstate, struct query_info *lookup_qinfo)

Function called when looking for (expired) cached answers during the serve expired logic.

Called as func(qstate, lookup_qinfo) Where: qstate: the query state. lookup_qinfo: the qinfo to lookup for.

## Enumeration Type Documentation

## ◆ module_ext_state

enum module_ext_state

External visible states of the module state machine Modules may also have an internal state.

Modules are supposed to run to completion or until blocked.

Enumerator
module_state_initial | initial state - new query
module_wait_reply | waiting for reply to outgoing network query
module_wait_module | module is waiting for another module
module_restart_next | module is waiting for another module; that other is restarted
module_wait_subquery | module is waiting for sub-query
module_error | module could not finish the query
module_finished | module is finished with query

## ◆ module_ev

enum module_ev

Events that happen to modules, that start or wakeup modules.

Enumerator
module_event_new | new query
module_event_pass | query passed by other module
module_event_reply | reply inbound from server
module_event_noreply | no reply, timeout or other error
module_event_capsfail | reply is there, but capitalisation check failed
module_event_moddone | next module is done, and its reply is awaiting you
module_event_error | error

## Function Documentation

## ◆ strextstate()

const char * strextstate | ( | enum module_ext_state | s | ) |

Debug utility: module external qstate to string.

Parameters

  s | the state value.

Returns
  descriptive string.

References module_error, module_finished, module_restart_next, module_state_initial, module_wait_module, module_wait_reply, and module_wait_subquery.

Referenced by dns64_operate(), get_mesh_status(), ipset_operate(), iter_operate(), mesh_run(), and val_operate().

## ◆ strmodulevent()

const char * strmodulevent | ( | enum module_ev | e | ) |

Debug utility: module event to string.

Parameters

  e | the module event value.

Returns
  descriptive string.

References module_event_capsfail, module_event_error, module_event_moddone, module_event_new, module_event_noreply, module_event_pass, and module_event_reply.

Referenced by dns64_operate(), ipset_operate(), iter_operate(), pymod::setTTL(), pymod_thread::setTTL(), and val_operate().

## ◆ errinf()

void errinf | ( | struct module_qstate * | qstate,
|  | const char * | str )

Append text to the error info for validation.

Parameters

  qstate | query state.
  str | copied into query region and appended. Failures to allocate are logged.

Referenced by auth_zone_delegpt(), ds_response_to_ke(), errinf_dname(), errinf_origin(), errinf_reply(), errinf_rrset(), iter_operate(), prime_stub(), process_response(), processCollectClass(), processDSNSResponse(), processFinished(), processInit(), processInitRequest(), processInitRequest2(), processLastResort(), processPrimeResponse(), processQueryResponse(), processQueryTargets(), processValidate(), validate_msg_signatures(), and validate_suspend_setup_timer().

## ◆ errinf_origin()

void errinf_origin | ( | struct module_qstate * | qstate,
|  | struct sock_list * | origin )

Append text to error info: from 1.2.3.4.

Parameters

  qstate | query state.
  origin | sock list with origin of trouble. Every element added. If NULL: nothing is added. if 0len element: 'from cache' is added.

References sock_list::addr, addr_to_str(), module_env::cfg, module_qstate::env, errinf(), sock_list::len, config_file::log_servfail, sock_list::next, and config_file::val_log_level.

Referenced by process_dnskey_response(), process_ds_response(), process_prime_response(), processFindKey(), processValidate(), and validate_msg_signatures().

## ◆ errinf_rrset()

void errinf_rrset | ( | struct module_qstate * | qstate,
|  | struct ub_packed_rrset_key * | rr )

Append text to error info: for RRset name type class.

Parameters

  qstate | query state.
  rr | rrset_key.

References module_env::cfg, packed_rrset_key::dname, dname_str(), module_qstate::env, errinf(), LDNS_MAX_DOMAINLEN, config_file::log_servfail, ub_packed_rrset_key::rk, packed_rrset_key::rrset_class, sldns_wire2str_class_buf(), sldns_wire2str_type_buf(), packed_rrset_key::type, and config_file::val_log_level.

Referenced by validate_msg_signatures().

## ◆ errinf_dname()

void errinf_dname | ( | struct module_qstate * | qstate,
|  | const char * | str,
|  | uint8_t * | dname )

Append text to error info: str dname.

Parameters

  qstate | query state.
  str | explanation string
  dname | the dname.

References module_env::cfg, dname_str(), module_qstate::env, errinf(), LDNS_MAX_DOMAINLEN, config_file::log_servfail, errinf_strlist::str, and config_file::val_log_level.

Referenced by process_dnskey_response(), process_ds_response(), process_prime_response(), processDSNSFind(), processInit(), processInitRequest(), processLastResort(), processPrimeResponse(), processQueryResponse(), and processQueryTargets().

## ◆ errinf_to_str_bogus()

char * errinf_to_str_bogus | ( | struct module_qstate * | qstate,
|  | struct regional * | region )

Create error info in string.

For validation failures.

Parameters

  qstate | query state.
  region | the region for the result or NULL for malloced result.

Returns
  string or NULL on malloc failure (already logged). This string is malloced if region is NULL and has to be freed by caller.

References dname_str(), module_qstate::errinf, LDNS_MAX_DOMAINLEN, log_err(), errinf_strlist::next, query_info::qclass, module_qstate::qinfo, query_info::qname, query_info::qtype, regional_strdup(), sldns_wire2str_class_buf(), sldns_wire2str_type_buf(), and errinf_strlist::str.

Referenced by mesh_do_callback(), and processFinished().

## ◆ errinf_to_reason_bogus()

sldns_ede_code errinf_to_reason_bogus | ( | struct module_qstate * | qstate | ) |

Check the sldns_ede_code of the qstate->errinf.

Parameters

  qstate | query state.

Returns
  the latest explicitly set sldns_ede_code or LDNS_EDE_NONE.

References module_qstate::errinf, errinf_strlist::next, and errinf_strlist::reason_bogus.

Referenced by processFinished().

## ◆ errinf_to_str_servfail()

char * errinf_to_str_servfail | ( | struct module_qstate * | qstate | ) |

Create error info in string.

For other servfails.

Parameters

  qstate | query state.

Returns
  string or NULL on malloc failure (already logged).

References dname_str(), module_qstate::errinf, LDNS_MAX_DOMAINLEN, log_err(), errinf_strlist::next, query_info::qclass, module_qstate::qinfo, query_info::qname, query_info::qtype, module_qstate::region, regional_strdup(), sldns_wire2str_class_buf(), sldns_wire2str_type_buf(), and errinf_strlist::str.

Referenced by mesh_query_done().

## ◆ errinf_to_str_misc()

char * errinf_to_str_misc | ( | struct module_qstate * | qstate | ) |

Create error info in string.

For misc failures that are not servfail.

Parameters

  qstate | query state.

Returns
  string or NULL on malloc failure (already logged).

References module_qstate::errinf, log_err(), errinf_strlist::next, module_qstate::region, regional_strdup(), and errinf_strlist::str.

Referenced by ds_response_to_ke(), primeResponseToKE(), process_dnskey_response(), and processFinished().

## ◆ edns_known_options_init()

int edns_known_options_init | ( | struct module_env * | env | ) |

Initialize the edns known options by allocating the required space.

Parameters

  env | the module environment.

Returns
  false on failure (no memory).

References module_env::edns_known_options, and MAX_KNOWN_EDNS_OPTS.

Referenced by check_mod(), daemon_init(), and ub_ctx_create_nopipe().

## ◆ edns_known_options_delete()

void edns_known_options_delete | ( | struct module_env * | env | ) |

Free the allocated space for the known edns options.

Parameters

  env | the module environment.

References module_env::edns_known_options.

Referenced by check_mod(), daemon_delete(), daemon_init(), ub_ctx_create(), ub_ctx_create_nopipe(), and ub_ctx_delete().

## ◆ edns_register_option()

int edns_register_option | ( | uint16_t | opt_code,
|  | int | bypass_cache_stage,
|  | int | no_aggregation,
|  | struct module_env * | env )

Register a known edns option.

Overwrite the flags if it is already registered. Used before creating workers to register known edns options.

Parameters

  opt_code | the edns option code.
  bypass_cache_stage | whether the option interacts with the cache.
  no_aggregation | whether the option implies more specific aggregation.
  env | the module environment.

Returns
  true on success, false on failure (registering more options than allowed or trying to register after the environment is copied to the threads.)

Checking if we are full first is faster but it does not provide the option to change the flags when the array is full. It only impacts unbound initialization, leave it for now.

References edns_known_option::bypass_cache_stage, module_env::edns_known_options, log_err(), MAX_KNOWN_EDNS_OPTS, edns_known_option::no_aggregation, edns_known_option::opt_code, and module_env::worker.

## ◆ inplace_cb_register()

int inplace_cb_register | ( | void * | cb,
|  | enum inplace_cb_list_type | type,
|  | void * | cbarg,
|  | struct module_env * | env,
|  | int | id )

Register an inplace callback function.

Parameters

  cb | pointer to the callback function.
  type | inplace callback type.
  cbarg | argument for the callback function, or NULL.
  env | the module environment.
  id | module id.

Returns
  true on success, false on failure (out of memory or trying to register after the environment is copied to the threads.)

References inplace_cb::cb, inplace_cb::id, log_err(), and module_env::worker.

## ◆ inplace_cb_delete()

void inplace_cb_delete | ( | struct module_env * | env,
|  | enum inplace_cb_list_type | type,
|  | int | id )

Delete callback for specified type and module id.

Parameters

  env | the module environment.
  type | inplace callback type.
  id | module id.

References inplace_cb::id, and inplace_cb::next.

Referenced by pythonmod_deinit().

## ◆ inplace_cb_lists_delete()

void inplace_cb_lists_delete | ( | struct module_env * | env | ) |

Delete all the inplace callback linked lists.

Parameters

  env | the module environment.

## ◆ edns_option_is_known()

struct edns_known_option * edns_option_is_known | ( | uint16_t | opt_code,
|  | struct module_env * | env )

Check if an edns option is known.

Parameters

  opt_code | the edns option code.
  env | the module environment.

Returns
  pointer to registered option if the edns option is known, NULL otherwise.

References module_env::edns_known_options, and edns_known_option::opt_code.

## ◆ edns_bypass_cache_stage()

int edns_bypass_cache_stage | ( | struct edns_option * | list,
|  | struct module_env * | env )

Check if an edns option needs to bypass the reply from cache stage.

Parameters

  list | the edns options.
  env | the module environment.

Returns
  true if an edns option needs to bypass the cache stage, false otherwise.

References edns_known_option::bypass_cache_stage, module_env::edns_known_options, edns_option::next, edns_known_option::opt_code, and edns_option::opt_code.

Referenced by worker_handle_request().

## ◆ unique_mesh_state()

int unique_mesh_state | ( | struct edns_option * | list,
|  | struct module_env * | env )

Check if an unique mesh state is required.

Might be triggered by EDNS option or set for the complete env.

Parameters

  list | the edns options.
  env | the module environment.

Returns
  true if an edns option needs a unique mesh state, false otherwise.

References module_env::edns_known_options, edns_option::next, edns_known_option::no_aggregation, edns_known_option::opt_code, and edns_option::opt_code.

Referenced by mesh_new_callback(), and mesh_new_client().

## ◆ log_edns_known_options()

void log_edns_known_options | ( | enum verbosity_value | level,
|  | struct module_env * | env )

Log the known edns options.

Parameters

  level | the desired verbosity level.
  env | the module environment.

References edns_known_option::bypass_cache_stage, module_env::edns_known_options, edns_known_option::no_aggregation, edns_known_option::opt_code, sldns_wire2str_edns_option_code_print(), verbose(), and verbosity.

Referenced by context_finalize(), and daemon_setup_modules().

## ◆ copy_state_to_super()

void copy_state_to_super | ( | struct module_qstate * | qstate,
|  | int | id,
|  | struct module_qstate * | super )

Copy state that may have happened in the subquery and is always relevant to the super.

Parameters

  qstate | query state that finished.
  id | module id.
  super | the qstate to inform.