Modules and hooks
Add support for externally loaded modules to hook into query-response processing.
Requirements
- Implement an pluggable interface to add a module that would access and possibly modify the query-response processing
- The modules would be using versioned API
- The modules could be dynamically loaded or statically compiled in
- Only C modules would be supported in 1st phase
- More programming languages could be added later (Rust, Go, Lua)
- There would be a multiple entry points as the query-response gets processed by BIND
- Before reading any data from the socket
- After reading DNS message from the socket
- Before entering view
- After entering view
- Before ACL
- After ACL
- (Authoritative) Before reading the zone data
- (Authoritative) After reading the zone data
- (Recursive) Before sending each recursive query
- (Recursive) After receiving each recursive query
- Before sending a reply to a socket
- After sending a reply to a socket
- Before stats are produced (finalized?)
- On module load
- On module unload
- RNDC should probably also include multiple entry points, so module can add new commands, extend/modify existing command, and/or modify the processing of existing commands.
- The module should have access to most context data related to query, parent query, subqueries, answer and internal state
- The module should be able to specify its entry points from within the module
- The module should be able to specify module dependencies and load order for each entry point
- It must be possible to load multiple instances of a single module
Technical Specification
- Plugin API will be specified, there are number of other projects that utilize loadable dynamic and/or static plugins
- Apache
- Kea
- PHP
- SASL
- The API needs to use opaque pointers and the API should be kept as stable as possible
- ...
Sample Configuration Syntax
acl exempt { 10.53.0.7; };
options {
directory "/etc/bind";
recursion yes;
dnssec-validation auto;
};
hooks {
path "/usr/local/lib:/etc/hooks:";
query rebound.so; // no options; use default settings
query filter-aaaa.so {
filter-on-v4 yes;
filter-on-v6 no;
};
query rpz.so {
response-policy {
zone "policy1"; // note this is defined outside the hooks block
zone "policy2";
} qname-wait-recurse no
nsdname-enable yes
nsip-enable yes;
};
};
query rrl.so {
responses-per-second 10;
all-per-second 50;
slip 3;
exempt-clients {
exempt; // note this is defined outside the hooks block
};
};
};
zone policy1 {
type master;
file "policy1.db";
};
zone policy2 {
type slave;
masters { 10.53.0.1; };
file "policy2.db";
};
Notes on Configuration
- Initially, hook modules will probably be limited to query processing, but there could also be hooks, for example, for update, notify, or xfr. This is why "query" is specified for each hook module above. This is probably not strictly necessary - the names of the modules should be sufficient to disambiguate them - but it may be necessary for query modules to be initialized differently from update modules. It should in any case help with readability for the user.
- Just as with
zone
, ahooks
block can be at the top level ofnamed.conf
or it can be underview
. A server with multiple views cannot have a global-levelhooks
block. - The configuration options are passed to hooks as bracketed_text (same as with
dyndb
anddnsrps
). The hook module itself will parse the options. This means thenamed
parser doesn't have to understand the module's configuration syntax. A pointer to the parser context must be provided to the module at initialization time so it can reference names that are defined elsewhere (such as theexempt
ACL in the above sample). - Hook modules will need to share an address space with
named
and be initialized with pointers to the view, zone table, server context, etc. - Hook modules will specify their own entry/callback points. In other words, it would not be necessary for the user to specify that filter-aaaa taps in at the "pre-response" entry point; it can do that by itself.
- If more than one hook uses the same entry/callback point, the order in which they are listed in
hooks
sets priority. (In the above example, rebound would precede filter-aaaa.) We can add syntax to override default priorities for certain entry points if that turns out to be necessary.
Edited by Ray Bellis