This driver allows you to use Berkeley DB as a database for storage of DNS data. It has been tested on Windows 2K and Redhat Linux 8.0. The driver should build properly on any UN*X system that BIND & Berkeley DB support. Be sure to specify --with-dlz-bdb when running configure so that the Berkeley DB driver is built with BIND. Actually, both the original BDB driver and the BDBHPT driver are built when --with-dlz-bdb is specified. By default, DLZ and its drivers are not built. When you specify a DLZ driver, the DLZ core is automatically built too.
BE SURE TO READ THE SPECIAL BUILD INSTRUCTIONS FOR THE BDB DRIVERS!
instead of this driver in production systems!
The Berkeley DB itself (not this driver) has a bug which can cause applications using the Berkeley DB's Concurrent Data Store capability and performing joins to deadlock. The bug has been brought to the attention of Sleepycat, the makers of Berkeley DB. As a result, performing large numbers of updates to the database while it is also being used by Bind to answer DNS queries may deadlock the database, causing Bind to stop answering queries. When a fix is available from Sleepycat for the Berkeley DB, this driver will no longer suffer from this issue.
The BDBHPT driver does not perform ANY joins and therefore is not subject to this deadlock bug in the Berkeley DB. Also, the BDBHPT driver provides much higher performance than the original BDB driver. The original BDB driver is still useful for understanding and experimenting in DLZ and is much easier to setup than the BDBHPT driver.
The Berkeley DB driver was built to be as flexible as possible, but it is not as flexible as the PostgreSQL, MySQL or file system drivers because of how Berkeley DB works.
Below is a sample of a proper dlz_bdb_driver configuration. This configuration segment would be contained in BIND's config (named.conf) file. It is explained more below. When you are setting up your own Berkeley DB driver be sure to pass the following parameters to BIND "-g -d 1". The first "-g" tells BIND to write all log messages to stdout instead of a log file. The second parameter "-d 1" sets BIND's debug level to 1. The Berkely DB driver will output additional information when the debug level is set to at least 1. This can be very helpful while you are setting up the driver. The additional information will be output only when BIND is trying to answer DNS queries, not when BIND loads. Run a few sample DNS queries in order to see the output.
dlz "bdb zone" { database "bdb /dns-root dnsdata.db"; }; |
The first line: dlz "bdb zone" {
This line tells BIND we want to use a DLZ driver. The word "dlz" is a new BIND keyword added by the DLZ patch. The next section "bdb zone" is the label for this configuration segment. It is used in any error messages BIND displays while parsing its config file. The last piece "{" starts the DLZ configuration section in BIND's config file.
The second line: database "bdb /dns-root dnsdata.db";
This line is indented just to make it easier to read the configuration file. The keyword "database" is the only parameter that can be specified in a DLZ configuration segment. It is required. The double quote (") begins the command line that is passed to the DLZ driver--in this case, the Berkeley DB driver. The command line could be broken over many lines but is not necessary here. The next piece is the word "bdb". This is the official name of the DLZ Berkeley DB driver. We are telling BIND that we want to use the Berkeley DB driver. The word "bdb" is located at argv[0]. I.E. This is the command line array passed to the driver, and the driver name must always be at argv[0]; it is not optional.
Next is "/dns-root". It should NOT have a "/" at the end. This is the directory path where the Berkeley DB environment is stored. The Berkeley DB driver operates in "concurrent data store" (CDS) mode, not in the old style "DBM" mode, and thus requires a Berkeley DB environment. For more information about "concurrent data store" operation of the Berkeley DB, see the documentation provided with that software package.
Basically, CDS allows the database to be "read" by one or more applications simultaneously, and also allows the database to be updated or "written" to simultaneously by another application. Only one application may make updates to the database at a time. The Berkeley DB takes care of all synchronization and locking. Because of this, it may appear that multiple applications are writing to the database simultaneously, but that is not the case. One application will make its updates, and then the other application will. Depending upon how the application is written, the updates from the two programs may actually be inter-weaved. One program makes an update, then the second, then the first again, etc. In order for the Berkeley DB to handle locking properly, all applications which access the database must use the same environement and use the correct Berkeley API's to access the database environment BEFORE attempting to perform any database operations. The Berkeley DB driver, and the supplied utility (dlzbdb) both make use of the Berkeley environment properly. Look at the source code of both to see how to properly access the Berkeley envionment and database.
The next item "dnsdata.db" is the path and name of the database file to store the dns data in. This "path" is relative to the environment path. So, using the configuration as we have it here will create a file called "dnsdata.db" in the path "/dns-root" for a full path of "/dns-root/dnsdata.db". You can also use absolute paths for the database file path and name if you don't want the database file stored in the same folder as, or relative to the Berkeley DB environment. I highly recommend that you place the database file in the same folder as the database environment just for ease of administration.
The last characters on the command line are "; These characters complete and close the command line and are part of BIND's standard configuration file syntax.
Third line: };
This closes the DLZ configuration section in BIND's config file. It is part of BIND's standard configuration file syntax.
How the Berkeley DB driver works:The Berkeley database file actually has 4 "databases" in it. Berkeley DB and "DBM" / "NDBM" / "GDBM" style databases are only simple key = value databases. That is to say that each database can only store a key, and the corresponding value for that key. In order to perform more complex query operations using multiple keys, you need to use multiple key = value databases and combine them together in some way. This is easiest with the Berkeley DB as it provides API's to do this, so we don't have to do it all manually (We still do a lot of it manually). The four databases in the database file are:
dns_data | The DNS data. The key is meaningless. It is only used as a means to identify this particular data record. The key is used to lookup this particular data record by other index databases. |
dns_zone | The zone index for the DNS data. The key is a zone name, the value is a "dns_data" key. Multiple matching keys (zone names) are allowed. This database is used to narrow results to a particular zone. Usually used in combination with "dns_host". |
dns_host | The host index for the DNS data. The key is a hose name, the value is a "dns_data" key. Multiple matching keys (host names) are allowed. This database is used to narrow results to a particular host. Usually used in combination with "dns_zone". | dns_client |
The lookup database for zone transfers. This databases keys
are zone names, and the values are IP addresses. Multiple
matching keys are allowed. Multiple matching IP addresses are
allowed. Only one unique zone & IP address are allowed. I.E
You may have:
|
Data in the "dns_data" value field must be specified in the following order. Only a single space " " must be between each field, and records of DNS type TXT should include any necessary quoting. Any un-needed fields should be ignored.
Order | Name | Data Type | Description |
---|---|---|---|
1 | zone | string | DNS zone |
2 | host | string | DNS host name |
3 | type | string | DNS data type |
4 | ttl | string (num) | Time to live (string must convert to number) |
5 | mx_priority | string (num) | MX Priority (only for MX DNS types) |
6 | data | string | IP address / Host name / Full domain name |
7 | primary_ns | string | Primary name server SOA record (SOA ONLY) | 8 | resp_person | string | Responsible person SOA record (SOA ONLY) |
9 | serial | string (num) | Serial # for SOA record (SOA ONLY) |
10 | refresh | string (num) | Refresh timefor SOA record (SOA ONLY) |
11 | retry | string (num) | Retry time for SOA record (SOA ONLY) |
12 | expire | string (num) | Expire time for SOA record (SOA ONLY) |
13 | minimum | string (num) | Minimum time for SOA record (SOA ONLY) |
Like most other DLZ drivers, the Berkeley DB supports wildcard hostnames using "*" as the wild card, and the character "@" is used as the hostname at the zone apex.
Some examples:
example.com @ SOA 10 ns1.example.com. root.example.com. 2 2800 7200 604800 86400 example.com www A 10 192.168.0.1 example.com mail A 10 192.168.0.2 example.com backup A 10 192.168.0.3 example.com @ MX 10 20 mail example.com @ MX 10 40 backup example.com www MX 10 20 mail example.com www MX 10 40 backup example.com ns1 A 10 192.168.0.4 example.com ns2 A 10 192.168.0.5 example.com @ NS 10 ns1.example.com. example.com @ NS 10 ns2.example.com. example.com @ TXT 10 "This is some sample text. Notice it is inside of quotes" example.com @ TXT 10 "The quotes are required by BIND so that it returns the" example.com @ TXT 10 "string as a single entry. Otherwise it will return each" example.com @ TXT 10 "word as a entry instead of the entire string." example.com @ TXT 10 "This text is actually 8 separate text records. It was" example.com @ TXT 10 "broken up this way to be easier to read. You may" example.com @ TXT 10 "specify long text entries if you want. i.e. this could" example.com @ TXT 10 "have all been one entry if we wanted to do that." example.com * A 10 192.168.0.6 |
Using the dlzbdb utility:
The dlzbdb utility was developed to enable immediate use of the Berkeley DB driver and serve as an example of how to interact with the database. The utility provides only basic operations.
For help at anytime, execute dlzbdb without any command line arguements. The program will display a simple help message showing how to use it.
First you must create a database. The dlzbdb utility can create a database and add records at the same time.
For example:
dlzbdb -n -a "d example.com www A 10 192.168.0.1" /dns-root dnsdata.db |
This command will create a new database and environment if they did not exist. If a database and environment already exist, they will not be created or overwritten. The new record will simply be added to the existing database.
The "-n" option can be used to recreate Berkeley DB environment files if they are missing after performing a Berkeley DB recover operation. If the environment files are gone and the database file is intact, the environment files will be recreated, and no data in the database will have been lost.
The "a" option indicates that we wish to add a new record to the database. The data is contained within the quotes. The first letter "d" indicates that this is DNS data. The rest of the data inside the quotes is the data to be added to the database. Notice it follows the format listed above. The dlzbdb utility is a bit more forgiving in that if there are extra spaces between the fields, it will automatically remove them. To insert text records with quotes, you will need to escape the quotes in the data record by proceeding each quote with a "\" character.
For example:
dlzbdb -a "d example.com www TXT 10 \"this is escaped\"" /dns-root dnsdata.db |
The dlzbdb utility will automatically create the key for the "dns_data" database and add required zone and host entries to the other databases as well.
In order for zone transfers to be performed, a client must be authorized to do zone transfers. This is accomplished by adding an entry to the "dns_client" database. To do this:
dlzbdb -a "c example.com 192.168.0.1" /dns-root dnsdata.db |
This command is very similar to the previous ones. The difference is that instead of a "d" we have a "c" as the first character. This lets dlzbdb know we want to add a client to the zone transfer list. After the "c" character is "example.com"--this is the zone. Following that is "192.168.0.1". This is the IP address of a machine that we will allow to perform zone transfers.
In all the commands shown thus far, the last two parameters are "/dns-root" and "dnsdata.db". The first parameter is the location of the Berkeley DB environment. The last is the relative path & name of the database file. These two parameters are required for any operation with dlzbdb and should always be the last two parameters, in that order.
dlzbdb can also perform "bulk" loads of data. To do that, create a file where each line is one "command". Each command should look exactly as the commands we have listed above. The file may also include c, c++ and shell comments; comments are ignored.
Example file:
d example.com @ SOA 10 ns1.example.com. root.example.com. 2 2800 7200 604800 86400 d example.com www A 10 192.168.0.1 d example.com mail A 10 192.168.0.2 d example.com backup A 10 192.168.0.3 d example.com @ MX 10 20 mail d example.com @ MX 10 40 backup d example.com www MX 10 20 mail d example.com www MX 10 40 backup // This is an example comment. It is ignored. // these are our name servers d example.com ns1 A 10 192.168.0.4 d example.com ns2 A 10 192.168.0.5 d example.com @ NS 10 ns1.example.com. d example.com @ NS 10 ns2.example.com. d example.com @ TXT 10 "This is some sample text." d example.com * A 10 192.168.0.6 c example.com 192.168.0.4 // allow zone transfers to our public DNS servers c example.com 192.128.0.5 |
The Berkeley DB does not allow the use of transactions when operating in CDS mode. So it is not possible to "rollback" the load if an error occurs on one line. Instead, the dlzbdb utility will display an error message indicating any line which could not be loaded. You should then copy that line and any others that failed to load to a new file, repair the errors, and load the new file. This is not the best solution, but it is the only one that works.
The dlzbdb utility also has the ability to list or delete entries in the database, export the entire database in dlzbdb "bulk" format, and can bulk load from a file or stdin. Execute dlzbdb with no parameters to display the help. Those operations should be self explanatory.