bind-dyndb-ldap is LDAP back-end plugin for BIND that provides an LDAP database and run-time reconfiguration.
The plugin integrates very deeply with BIND. The implementation is based on library which is dynamically loaded into main BIND process during startup.
After initialization, BIND is calling the plugin APIs and the plugin is calling BIND APIs as necessary. Some actions require multiple nested calls between BIND and the plugin using different APIs.
The plugin acts as bridge between two worlds: DNS implemented by BIND vs. LDAP implemented by OpenLDAP libraries. For understanding how the plugin works it is crucial to first understand BIND internals and how to use LDAP using OpenLDAP libraries.
During BIND startup, BIND parses named.conf and loads library containing the plugin. The very first interaction with BIND looks like this:
dyndb_init()
in the plugin library. This creates new
internal ldap_instance_t
of LDAP database.dns_db_register()
in BIND to add name of the
LDAP instance into list of registered databases.ldap_syncrepl_watcher()
thread. There is a
gotcha: This is an ordinary pthread and not BIND task!Following operations are done by the syncrepl thread in cycle:
Beware: Operations done by ldap_syncrepl_watcher()
thread in the
plugin and BIND are running in parallel and need to be carefully
synchronized. Be very careful! ldap_syncrepl_watcher()
thread is
totally separate and does not respect BIND internal threading/task
model.
ldap_sync_init()
to start LDAP
SyncRepl sessions (using OpenLDAP library).ldap_sync_search_entry
, ldap_sync_search_reference
,
ldap_sync_intermediate
, ldap_sync_search_result
in the plugin
code. From BIND’s point of view these calls are completely
asynchronous.ldap_sync_search_entry
callback is called for each LDAP entry.idnsZone
entry). The callback transforms LDAP entry into
BIND internal event structure. The event is sent to event queue to
one of BIND internal tasks. From this point the event follows BIND
synchronization rules.The event queue is managed by BIND. Each event is processed by task determined by event sender. Different tasks are running in parallel, each task processing its event queue. At this point BIND synchronization primitives and task model is in play again. An example of event processing follows:
update_zone()
to process the eventldap_parse_master_zoneentry()
to process DNS master zone
updatecreate_zone()
to create a new DNS zone in BINDzone_sync_apex()
to store data from LDAP into internal
database used by the pluginAt this point the plugin is creating new DNS zone inside BIND. To do
this, the plugin is calling many dns_zone*()
functions from BIND
API. The new zone is associated with LDAP plugin using
dns_zone_setdbtype()
function. (This would not be possible without
calling dns_db_register()
function during plugin initialization.)
Please note that at this point the new DNS zone is not associated with
an BIND database yet. The zone data are stored internally by the plugin
(see plugin function zr_add_zone()
) but not yet exposed to BIND. The
association is done later in a separate event.
refreshDone
= TRUE
. Based on this message, OpenLDAP
libraries call ldap_sync_intermediate()
callback in syncrepl
thread.ldap_sync_intermediate()
in the plugin calls
sync_barrier_wait()
to finalize event processing from refresh
stage. When the synchronization is done, chain of calls following
from sync_finishev_create()
function calls plugin internal
function activate_zones()
.activate_zones()
uses BIND APIs
dns_view_*()
and dns_zone_setview()
to publish the DNS zone
over DNS protocol. After publication, the plugin calls
dns_zone_*()
APIs to load zone data into BIND. BIND function
dns_zone_load()
internally calls BIND function
dns_db_create()
which in turn calls plugin function
ldapdb_associate()
. This way the plugin-internal zone database
gets exposed to BIND and zone data become accessible over DNS.At this point DNS zone is fully functional and DNS operations can be done on it.
dns_view_*()
dns_zt_*()
: determine what zone is affected by the
operation. View and zone table APIs return DNS zone structure.dns_zone_*()
: DNS zone structure internally contains
metadata and DNS database structure.dns_db_*()
: Database API is used to manipulate the
data in the zone database.dns_db_*()
APIs. DB calls are translated to function calls
according to dns_dbmethods_t ldapdb_methods
structure in
tree/src/ldap_driver.c.
For example, dns_db_addrdataset()
API function is redirected to
plugin internal function addrdataset()
.addrdataset()
modifies in-memory
database and also uses OpenLDAP libraries to make the same
modification in LDAP.Keep in mind that modifications to LDAP are watched by the plugin using SyncRepl persist stage. Even changes done by the plugin itself generate change notifications which will be received by the plugin again with some delay!
ldap_sync_search_entry()
callback. This in turn generates event
and triggers usual event processing described above. Keep in mind
that these LDAP events are generated asynchronously so there is risk
of race conditions with other events (e.g. DNS/timed/administrative
operations).dyndb_destroy()
function in the plugin.
It stops the syncrepl thread, de-registers plugin database type from
the database list, and destroys ldap_instance_t
and other
structures.dyndb_destroy()
function does not
affect pending events, i.e. already sent events waiting in the
event queue of various BIND tasks.