I've recently started trialling DLZ backed by OpenLDAP. One thing I needed to do because I couldn't find anything already available was create a script to convert some rather large Bind zone files to LDIF for import into my LDAP tree.
I thought someone else may benefit from it so I've posted the text of the script below - maybe someone with access can add it to the downloads page.
The LDAP schema for DLZ is not prescribed so no script will suit all users but the one I have begun with uses the published dlz.schema and follows its recommended usage pretty closely. I've used awk in an attempt to make it accessible everywhere and fairly
easy for an unfamiliar user to modify to accommodate their own schema.
It doesn't deal with every possible scenario but I hope it will be a good starting point for someone trying to set up an LDAP backed Bind server using DLZ.
If your zone file doesn't contain the zone suffix as the first field of the SOA or in an ORIGIN statement prior to the SOA you will need to pass it as the value of the "zone" variable on the command line invocation.
Similarly the "base" variable is also required. The last argument is the name of the zone file. The script will always add a ou=dns below the base.
will create its LDIF output in foo.bar.com.db.ldif.
#######################################################################################
#!/usr/bin/env awk -f
function firstFieldMatching(pattern, start) {
matched = 0;
for (i = start; i <= NF; i++) {
if ($i ~ pattern) {
matched = 1;
break;
}
}
return matched ? i : -1;
}
function ldifWrite(attribute, value) {
if ( value != "" ) printf("%s: %s\n", attribute, value) >>outfile;
}
function getNextRecordID(h, id) {
id = hosts[h];
if ( id == "" ) {
id = 0;
ldifWrite("dn", sprintf("dlzHostName=%s,dlzZoneName=%s,ou=dns,%s", h, zone, base));
ldifWrite("objectClass", "dlzHost");
ldifWrite("dlzHostName", h);
print "\n" >>outfile;
}
hosts[h] = id + 1;
return id;
}
function addZone() {
ldifWrite("dn", sprintf("dlzZoneName=%s,ou=dns,%s", zone, base));
ldifWrite("objectClass", "dlzZone");
ldifWrite("dlzZoneName", zone);
print "\n" >>outfile;
}
function addRecord(r, id) {
id = getNextRecordID(host);
ldifWrite("dn", sprintf("dlzType=%s,dlzHostName=%s,dlzZoneName=%s,ou=dns,%s", r["type"], host, zone, base));
ldifWrite("objectClass", r["class"]);
ldifWrite("dlzRecordID", id);
ldifWrite("dlzHostName", host);
ldifWrite("dlzType", r["type"]);
ldifWrite("dlzSerial", r["serial"]);
ldifWrite("dlzRefresh", r["refresh"]);
ldifWrite("dlzRetry", r["retry"]);
ldifWrite("dlzExpire", r["expire"]);
ldifWrite("dlzMinimum", r["minimum"]);
ldifWrite("dlzAdminEmail", r["adminEmail"]);
ldifWrite("dlzPrimaryns", r["originHost"]);
ldifWrite("dlzIPAddr", r["ip"]);
ldifWrite("dlzPreference", r["preference"]);
ldifWrite("dlzData", r["data"]);
ldifWrite("dlzTTL", r["ttl"] ? r["ttl"] : ttl);
print "\n" >>outfile;
}
BEGIN {
FS = "[ \t]+"
subdomain = "";
ttl = 3600;
zone_regex = "";
}
END {
close(outfile);
}
{
delete record;
if ( outfile == "" ) {
outfile = sprintf("%s.ldif", FILENAME);
print "" > outfile;
}
}
# TTL
/^[ \t]*\$TTL[ \t]+[0-9]+[ \t]*$/ {
ttl = $2
next;
}
# ORIGIN
/^[ \t]*\$ORIGIN[ \t]+[a-zA-Z0-9\.\-]+\.[ \t]*$/ {
origin = tolower($2);
if (origin == zone) host = " <at> ";
#printf("# ORIGIN: %s\n", origin);
subdomain = origin;
sub(zone_regex, "", subdomain);
if ( length(subdomain) > 0 ) subdomain = sprintf(".%s", substr(subdomain, 1, length(subdomain) - 1));
#printf("# subdomain: %s\n", subdomain);
next;
}
# SOA
/^[ \t]*[a-zA-Z0-9\.\- <at> ]+[ \t]+IN[ \t]+SOA[ \t]+[a-zA-Z0-9\.\-]+[ \t]+[a-zA-Z0-9\.\-]+[ \t]+\([ \t]*$/ {
if ( $1 != " <at> ") {
zone = tolower($1);
} else {
if ( origin ) zone = origin;
}
addZone();
host = " <at> ";
zone_regex = sprintf("%s.", zone);
gsub("
\\.", "
\\.", zone_regex);
record["type"] = "soa";
record["class"] = "dlzSOARecord";
record["originHost"] = tolower($4);
record["adminEmail"] = tolower($5);
getline; record["serial"] = $2;
getline; record["refresh"] = $2;
getline; record["retry"] = $2;
getline; record["expire"] = $2;
getline; record["minimum"] = $2;
addRecord(record);
next;
}
# NS
/^([ \t]*( <at> |[a-zA-Z0-9\.\-]+))?([ \t]+IN)?[ \t]+NS[ \t]+(([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})|([a-zA-Z0-9\.\-]+))[ \t]*$/ {
record["data"] = tolower($NF);
record["type"] = "ns";
record["class"] = "dlzNSRecord";
addRecord(record);
next;
}
# MX
/^([ \t]*( <at> |[a-zA-Z0-9\.\-]+))?([ \t]+IN)?[ \t]+MX[ \t]+[0-9]+[ \t]+(([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})|([a-zA-Z0-9\.\-]+))[ \t]*$/ {
record["data"] = tolower($NF);
record["type"] = "mx";
record["class"] = "dlzMXRecord";
record["preference"] = $(NF - 1);
addRecord(record);
next;
}
# A
/^(([a-zA-Z0-9\.\-]+)| <at> |\*)?([ \t]+IN)?[ \t]+A[ \t]+([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})[ \t]*$/ {
if (NF == 4) {
record["ip"] = $4;
} else if (NF == 3) {
record["ip"] = $3;
} else {
record["ip"] = $2;
}
if ($1 ~ /^(IN|A|[ \t]*)$/ ) {
host = " <at> ";
} else {
host = sprintf("%s%s", tolower($1), subdomain);
}
record["type"] = "a";
record["class"] = "dlzARecord";
addRecord(record);
next;
}
#CNAME
/^[ \t]*([a-zA-Z0-9\.\-]+)([ \t]+IN)?[ \t]+CNAME[ \t]+([a-zA-Z0-9\.\-]+)[ \t]*$/ {
host = sprintf("%s%s", tolower($1), subdomain);
data = tolower($3);
if ( substr(data, length(data), 1) != "." ) data = sprintf("%s%s", data, subdomain);
record["type"] = "cname";
record["class"] = "dlzCNameRecord";
record["data"] = data;
addRecord(record);
next;
}
#TXT
/^[ \t]*([a-zA-Z0-9\.\-\_]+)([ \t]+IN)?[ \t]+TXT[ \t]+"[^"]+"[ \t]*$/ {
host = sprintf("%s%s", tolower($1), subdomain);
if (NF == 4) {
record["data"] = $4;
} else if (NF == 3) {
record["data"] = $3;
}
record["type"] = "txt";
record["class"] = "dlzTextRecord";
addRecord(record);
next;
}
# PTR
/^[ \t]*[0-9]{1,3}(\.[0-9]{1,3}){0,2}([ \t]+IN)?[ \t]+PTR[ \t]+[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)+\.[ \t]*$/ {
if (NF == 4) {
record["data"] = tolower($4);
} else if (NF == 3) {
record["data"] = tolower($3);
}
host = $1;
record["type"] = "ptr";
record["class"] = "dlzPTRRecord";
addRecord(record);
next;
}
#SRV
/^[ \t]*([a-zA-Z0-9\.\-\_]+)([ \t]+[0-9]+)?([ \t]+IN)?[ \t]+SRV[ \t]+[0-9]+[ \t]+[0-9]+[ \t]+[0-9]+[ \t]+[a-zA-Z0-9\.\-]+[ \t]*$/ {
host = sprintf("%s%s", tolower($1), subdomain);
if ($2 ~ /^[0-9]+$/) {
record["ttl"] = $2;
}
for (i = firstFieldMatching("SRV", 2) + 1; i <= NF; i++) {
record["data"] = record["data"] ? record["data"]" "$i : $i;
}
record["data"] = "\""record["data"]"\"";
record["type"] = "srv";
record["class"] = "dlzGenericRecord";
addRecord(record);
next;
}
This email (including any attachments) is confidential and may be privileged. If you have received it in error, please notify the sender by return email and delete this message from your system. Any unauthorised use
or dissemination of this message in whole or in part is strictly prohibited. Please note that emails are susceptible to change and we will not be liable for the improper or incomplete transmission of the information contained in this communication nor for
any delay in its receipt or damage to your system. We do not guarantee that the integrity of this communication has been maintained nor that this communication is free of viruses, interceptions or interference.