Project sponsored by
Project hosted on

This driver allows you to use any file system as a database for storage of DNS data. While any file system may be used, either the Reiser or Memory file systems will provide the best performance. Obviously the Memory file system will not provide permanent storage of data. The memory file system should be used as a high speed cache when using other means for permanent storage.

This driver has been tested on Windows 2K and Redhat Linux 7.2. The driver should build properly on any UN*X system that BIND supports. Be sure to specify --with-dlz-filesystem when running configure so that the file system driver is built with BIND. By default DLZ and its drivers are not built. When you specify a DLZ driver the DLZ core is automatically built too.

The file system driver was built to be as flexible as possible, but is not as flexible as the PostgreSQL or MySQL drivers because of how file systems work.

Below is a sample of a proper dlz filesystem 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 file system 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 file system 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 "file system zone" {
       database "filesystem /dns-root/ .dns .xfr 0 ~";
    };

The first line: dlz "file system 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 "file system 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 "filesystem /dns-root/ .dns .xfr 0 ~";

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 filesystem driver. The command line could be broken over many lines, but is not necessary here. The next piece is the word "filesystem". This is the official name of the DLZ filesystem driver. We are telling BIND that we want to use the filesystem driver. The word "filesystem" 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/". This is the directory path where all DNS data is stored. I call it the dns-root. The data root is specified at argv[1] immediately after the "filesystem" driver name, it is not optional. Also, the directory path must always end with a path separator. On Un*x systems this is usually a "/", on Windows systems a "\".

The next item ".dns" is the zone / host path splitter. This will be explained more later in this document. It should always start with a "." and must always be at argv[2], it is not optional.

Similarly ".xfr" is the zone / client path splitter. This will be explained more later. It too should always start with a "." and must always be at argv[3], it is not optional.

A label is the portion of a domain name separated by ".".

For example: www.example.com has 3 labels. Those labels are:

    www
    example
    com

In the file system driver configuration above the number 0 is the maximum label length. When 0 is specified the maximum label length is unlimited. If the maximum label length were 5, labels longer than five characters would be split up. So using the example above "example" would be split into 2 parts. Those parts would be "examp" and "le". How the parts are used will be explained more below. When the maximum label length is anything but 0 an additional entry is needed in the file system for each host in order for zone transfers to operate properly. We will explain this more later. This parameter must always be at argv[4], it is not optional.

The last parameter is "~" this is the data splitter. Its use will be explained later. It must always be at argv[5], it is not optional. This parameter MUST always be only 1 character, and should NOT be any character that you expect to use in your dns data. Never use "." as the data splitter!

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 file system driver works:

The file system driver maps DNS data to file entries. It does this by checking file paths created from a combination of the command line parameters and domain names. The easiest way to understand how this happens is by demonstrating a few examples.

Example 1:

For this example let's use the following configuration:

    dlz "file system zone" {
            database "filesystem /dns-root/ .dns .xfr 0 ~";
    };

When a query for www.example.com comes in BIND will check with the filesystem driver to see if the zone is supported. The file system driver will perform a series of tests to see if the correct file paths exist. If it does, the zone is supported, and BIND is authoritative for the zone. If the path does not exist, it is not supported and BIND is not authoritative for the zone. Follow the sequence below for a better understanding.

Query: www.example.com

First the filesystem driver (FSD) will check for the following path: /dns-root/com/example/www/.dns

As you can see, a combination of data from the DNS query, and the file system configuration are used. The first portion "/dns-root/" is the DNS data root we specified above. "com/example/www" is the DNS query in reverse order by label. The DNS query is reverse so we can take advantage of the hierarchal nature of file systems. I.E. any domain name ending with ".com" will be in the "/dns-root/com" directory. Similarly any domain name ending with "example.com" will be in the "/dns-root/com/example" directory.

Now don't forget, at this stage we are checking to see if the ZONE is supported. SDLZ drivers always look for a zone match by checking the entire domain name first, and then trying again with fewer labels in the zone. We don't have a ZONE called "www.example.com", we have a ZONE called "example.com" with a HOST called "www". So the zone check for a path of "/dns-root/com/example/www/.dns" would fail.

Next the driver will check the file system for the following path: /dns-root/com/example/.dns

This test would succeed. Next the file system driver would attempt to get a directory listing of "/dns-root/com/example/.dns/www". Now you can see why we need the "zone / host path splitter". This allows the driver to know that the path "/dns-root/com/example/.dns/www" is for the HOST "www" in the ZONE "example.com". Without the ".dns" in the path the driver would have no way of figuring this out. I recommend that your "zone / host path splitter" start with a "." because the file system driver will prevent any zone or host name from starting with a ".".

Next the driver would loop through the directory listing parsing FILE NAMES to get DNS data. Let me state this again so it is clear. THE FILE SYSTEM DRIVER USES FILE NAMES FOR DNS DATA NOT THE CONTENTS OF THE FILE! THE FILES CAN BE ZERO LENGTH.

The file names have DNS data contained within them. File names with spaces are difficult to deal with. So instead the file system driver allows the use of a "data splitter" character. When the file name is parsed, the "data splitter" character is used to separate each data field in the file name.

Some examples:

    A~86400~22.22.22.22     "A" record with ttl of 86400 IP address of 22.22.22.22

    SOA~10~ns1.example.com.~root.ns1.example.com.~2~28800~7200~604800~86400

    "SOA" record
    ttl of 10
    primary name server "ns1.example.com"
    responsible person "root.ns1.example.com"
    serial number 2
    refresh 28800
    retry 7200
    expire 604800
    minimum 86400

Data in a file name must be specified in the following order. Notice that this order is the same as the data order for PostgreSQL and MySQL drivers EXCEPT FOR THE FIRST TWO DATA FIELDS. In this driver type is the first field. In the SQL drivers type is the second field, and ttl is the first.

Order | Name | Data Type | Description
--- | --- | --- | ---
1 | type | string | DNS data type
2 | ttl | string (num) | Time to live
3 | host | string | Host name or IP address
4 | mx_priority | string (num) | MX Priority
5 | data | string | IP address / Host name / Full domain name
6 | primary_ns | string | Primary name server for SOA record
7 | resp_person | string | Responsible person for SOA record
8 | serial | string (num) | serial # for SOA record
9 | refresh | string (num) | Refresh time for SOA record
10 | retry | string (num) | Retry time for SOA record
11 | expire | string (num) | Expire time for SOA record
12 | minimum | string (num) | Minimum time for SOA record

The file system driver also supports wildcard hostnames. Usually, "*" is used as the "wild card", but "*" has special meaning in file systems. Instead the file system driver uses the hostname "-" as its wildcard. Like all other DLZ drivers "@" is used as the hostname at the zone apex.

More examples. Below is a list of examples of where DNS data should be held for each host/zone combination using the same DLZ configuration we have been using all along.

Zone Name | Host Name | DNS data path
--- | --- | ---
example.com | www.long | /dns-root/com/example/.dns/long/www
long.example.com | www | /dns-root/com/example/long/.dns/www
example.com | (none) | /dns-root/com/example/.dns/@
example.com | * (wildcard) | /dns-root/com/example/.dns/-

The DLZ driver also supports zone transfer. When looking up clients in the file system the driver makes use of the "zone / client path splitter". Here's how it works. When an client wishes to make a zone transfer BIND will use the driver to check if the client is allowed to. It will use the client's IP address in the lookup as well has the ZONE.

Zone Name | Client IP | Path checked
--- | --- | ---
example.com | 127.0.0.1 | /dns-root/com/example/.xfr/127.0.0.1

A file named 127.0.0.1 must exist in the path /dns-root/com/example/.xfr

The DLZ file system driver is intended to be used with advanced file systems like the Reiser file system. The Reiser file system allows for a large number of directory entries to exist without any degradation of performance. If however you need to use this driver on a file system that cannot support large numbers of directory entries you can request DLZ to parse up the directories more. This is the purpose of the max label length parameter. If a label exceeds the allowed length it will be split up.

Let's try a new configuration

    dlz "file system zone" {
            database "filesystem /dns-root/ .dns .xfr 5 ~";
    };

Notice that this configuration is the same as last time, except we have changed the max label length to 5.

Some examples:

Zone Name | Host Name | DNS data path
--- | --- | ---
example.com | www | /dns-root/com/examp/le/.dns/www
example.com | www.long | /dns-root/com/examp/le/.dns/long/www
example.com | (none) | /dns-root/com/example/.dns/@
example.com | www.reallylong | /dns-root/com/examp/le/.dns/reall/ylong/www

Notice how example was split into "examp/le".

Some zone transfer examples:

Zone Name | Client IP | Path checked
--- | --- | ---
example.com | 127.0.0.1 | /dns-root/com/examp/le/.xfr/127.0.0.1

VERY IMPORTANT!!!! When the max label length is NOT 0 the file system driver needs additional help to know what the hostname is for zone transfers. So, when you use a max label length other than 0 you should also place a file called ".host~hostname" in your DNS data directory.

Examples:

Zone Name | Host Name | Host Name Entry
--- | --- | ---
example.com | www | /dns-root/com/examp/le/.dns/www/.host~www
long.example.com | www.long | /dns-root/com/examp/le/.dns/long/www/.host~www.long
example.com | www.reallylong | /dns-root/com/examp/le/.dns/reall/ylong/www/.host~www.reallylong

Here's a complete example:

Configuration:

    dlz "file system zone" {
            database "filesystem /dns-root/ .dns .xfr 0 ~";
    };

File system view:

    $ ls -RA --format=single-column dns-root
    dns-root:
    com

    dns-root/com:
    example

    dns-root/com/example:
    .dns
    .xfr

    dns-root/com/example/.dns:
    -
    @
    www

    dns-root/com/example/.dns/-:
    A~86400~1.2.3.4

    dns-root/com/example/.dns/@:
    SOA~10~ns1~root.ns1~2~28800~7200~604800~86400

    dns-root/com/example/.dns/www:
    A~86400~77.88.99.10

    dns-root/com/example/.xfr:
    10.10.10.1
    127.0.0.1

Using this data:

zone transfers from 10.10.10.1 and 127.0.0.1 would succeed. A query for www would return an "A" record with a ttl of 86400 and IP of 77.88.99.10. A query for any other host name in the zone "example.com" would return an "A" record with a ttl of 86400 and an IP address of 1.2.3.4. The SOA record has a ttl of 10 primary name server "ns1.example.com" responsible person "root.ns1.example.com" serial number: 2 refresh: 28800 retry: 7200 expire: 604800 minimum: 86400.

Another example:

Configuration:

    dlz "file system zone" {
            database "filesystem /dns-root/ .dns .xfr 5 ~";
    };

File system view:

    $ ls -RA --format=single-column dns-root
    dns-root:
    com

    dns-root/com:
    examp

    dns-root/com/examp:
    le

    dns-root/com/examp/le:
    .dns
    .xfr

    dns-root/com/examp/le/.dns:
    -
    @
    reall
    www

    dns-root/com/examp/le/.dns/-:
    .host~-
    A~86400~1.2.3.4

    dns-root/com/examp/le/.dns/@:
    .host~@
    SOA~10~ns1~root.ns1~2~28800~7200~604800~86400

    dns-root/com/examp/le/.dns/reall:
    ylong

    dns-root/com/examp/le/.dns/reall/ylong:
    www

    dns-root/com/examp/le/.dns/reall/ylong/www:
    .host~www.reallylong
    A~86400~9.8.7.6

    dns-root/com/examp/le/.dns/www:
    .host~www
    A~86400~77.88.99.10

    dns-root/com/examp/le/.xfr:
    10.10.10.1
    127.0.0.1

Using this data, all previous answers to DNS queries would be answered in the same way. I've added another hostname to the listing above. "www.reallylong" Notice how the hostname is split up because of the max label lenth. Also notice how each directory with a complete hostname has an entry ".host~hostname". For "www.reallylong" this is ".host~www.reallylong". This information is required when max label length is not 0 so that zone transfers will work properly.

It may be confusing at first to understand how to properly create the directory structure for the file system driver. Read the docs over a few times. Read the docs for DLZ itself, and even for some of the other drivers. Once you have things will make more sense. Also, try things out. It's rather hard to explain how to use the file system driver. But once you start using it you will see how easy it is to use it.