How modules work?

Hi.

I'm traversing through code. But it's still unclean for me how modules work. Can you give a short description of the design? Is it easy to add an own one?

Sergey Matveychuk wrote:

Hi.

I'm traversing through code. But it's still unclean for me how modules work. Can you give a short description of the design? Is it easy to add an own one?

Hi Sergey,

Modules process the queries from the clients, the results are cached. There are two modules now, they are run from the 'mesh' called by the 'worker'. A module is a state machine, and is activated by events such as the initial query event, and subsequent authority-server-reply events, or subquery-done events. A module has access to the module environment (module.h) as the thread-specific and global resources it can access (the caches and some function callbacks to accomplish tasks such as create new queries and send packets to servers).

The design makes modules separate from the rest of the code, but unbound as now has been specifically written for the modules it has now. What sort of module do you want to write?

Basically a new module sits best at the start of the module list; it sees new queries; passes them to the next module for handling; and can then post process the results when the next module is done and provides an answer.

For example the validator module sits in front of the iterator module. The validator sees the initial query that needs processing, but does nothing with queries but pass them to the iterator. Then when the iterator is done, and has a reply, the validator is woken up again. The validator then starts to validate the response (possibly creating sub-queries for additional information). The results from the validator are stored in the cache (it updates the 'security' variable of the result that the iterator already stored in the cache). Then the validator returns its answer. Since it is the first module; the module runner mesh takes this as a clue to send that reply to the DNS clients waiting for this query result.

The code for modules is now cleanly in the validator/ and iterator/ directories. The worker/ knows about what modules exist and loads the modules into the query runner mesh.

Does this answer your question? There is plenty of doxygen documentation as well, and also I can recommend running unbound in very high verbosity on a simple query and reading through the logs.

Best regards,
   Wouter

Hi Wouter,

Wouter Wijngaards wrote:

The design makes modules separate from the rest of the code, but unbound as now has been specifically written for the modules it has now. What sort of module do you want to write?

We need some balancing with DNS. I'm looking how to implement it without writing an own DNS server.

The code for modules is now cleanly in the validator/ and iterator/ directories. The worker/ knows about what modules exist and loads the modules into the query runner mesh.

And cache implemented not as a module?

Does this answer your question? There is plenty of doxygen documentation as well, and also I can recommend running unbound in very high verbosity on a simple query and reading through the logs.

Yes, thanks. It's a good start point for me.

BTW, anyway we plan to try unbound as high loaded cached dns for our company instead of bind.
And I've made a port for FreeBSD - dns/unbound.

Sergey Matveychuk wrote:

We need some balancing with DNS. I'm looking how to implement it without writing an own DNS server.

Adding a module may work for that. I would like unbound to be easily extensible, however, I did not want to bloat with useless features. If the design can be improved to help module incorporation, I would like to help.

And cache implemented not as a module?

No. The caches are accessible from the module_environment struct. The caches can be read or written by modules.

This is necessary for things like getting and setting lameness by the iterator, or keeping track of timeouts.

Yes, thanks. It's a good start point for me.

Cool.

BTW, anyway we plan to try unbound as high loaded cached dns for our company instead of bind.
And I've made a port for FreeBSD - dns/unbound.

Wow! Thanks!

Best regards,
   Wouter