2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 10:10:06 +00:00

remove contrib/sdb

removed the SDB databases in contrib/sdb as they hadn't been
maintained in some time, and were no longer able to link to named
without modification.  also:

- cleaned up contrib/README, which still referred to contrib
  subdirectores that were removed already, and linked to an obsolete URL.
- removed references to sdb in doc/misc/roadmap and doc/misc/sdb.
This commit is contained in:
Evan Hunt 2019-02-08 16:47:46 -08:00
parent d27f41cb7f
commit c79e2f12fe
29 changed files with 17 additions and 4414 deletions

View File

@ -1,62 +1,39 @@
This directory contains contributed scripts, tools, libraries, and other
useful accessories to BIND 9. Contrib software is not supported by ISC,
but reported bugs will be fixed as time permits.
This directory contains scripts, tools, and other useful accessories to
BIND 9. Contrib software is not supported by ISC, but reported bugs will
be fixed as time permits.
- scripts/
Assorted useful scripts, including 'nanny' which monitors
named and restarts it in the event of a crash, 'zone-edit'
which enables editing of a dynamic zone, and others
which enables editing of a dynamic zone, and others.
- dane/
mkdane.sh generates TLSA records for use with DNS-based
Authentication of Named Entities (DANE)
Authentication of Named Entities (DANE).
- dnspriv/
Sample configuration for setting up a DNS-over-TLS server
using BIND with Nginx as a TLS proxy
using BIND with Nginx as a TLS proxy.
- kasp/
Scripts for converting key and signature policies from OpenDNSSEC
KASP format to the policy.conf format used by dnssec-keymgr.
- dlz/modules
Dynamically linkable DLZ modules that can be configured into
named at runtime, enabling access to external data sources including
LDAP, MySQL, Berkeley DB, perl scripts, etc
LDAP, MySQL, Berkeley DB, perl scripts, etc.
- dlz/drivers
Old-style DLZ drivers that can be linked into named at compile
time. (These are no longer actively maintained and are expected
to be deprecated eventually.)
to be removed eventually.)
- sdb/
SDB drivers: another mechanism for accessing external data
sources. (These are no longer actively maintained and are
expected to be deprecated eventually.)
External tools:
- https://gitlab.isc.org/isc-projects/queryperf
A DNS query performance testing tool
- https://gitlab.isc.org/isc-projects/perftcpdns
A performance testing tool for DNS over TCP
- https://gitlab.isc.org/isc-projects/dnsperf
DNS server performance testing tools, like 'queryperf' but more
advanced: 'dnsperf' focuses on authoritative server performance
and 'resperf' on recursive server performance. The patch that
adds support for EDNS Client Subnet has been applied to the
git repository.
Formerly, there was more software included in this directory, but we
have removed it in favour of using canonical upstream locations. You
can find the links to the nslint, query-loc and zkt, and other software
we find useful but do not necessarily support, at:
https://www.isc.org/community/tools/
Some links to useful software and other resources related to BIND 9 and
DNS can be found at https://www.isc.org/dns-tools-and-resources.

View File

@ -1,37 +0,0 @@
(Message trash:37216)
Date: Wed, 15 May 2002 20:44:45 +0100
To: <bind-workers@isc.org>
From: Nuno Miguel Rodrigues <nmr@co.sapo.pt>
Subject: Berkeley DB BIND9 SDB
Replied: Thu, 16 May 2002 11:47:35 +1000
Replied: Nuno Miguel Rodrigues <nmr@co.sapo.pt>
Return-Path: <bind-workers-bounce@isc.org>
X-X-Sender: <nmr@angelina.sl.pt>
MIME-Version: 1.0
X-ecartis-version: Ecartis v1.0.0
Sender: bind-workers-bounce@isc.org
Errors-To: bind-workers-bounce@isc.org
X-original-sender: nmr@co.sapo.pt
Precedence: bulk
X-list: bind-workers
Status:
Hello all,
I'm making available a BIND9 SDB using Berkeley DB 4.0.
You can get it at http://www.dhis.org/~nmr/bind9_berkeleydb_sdb-1.0.tar
Thanks,
--
Nuno M. Rodrigues <nmr@co.sapo.pt>

View File

@ -1,234 +0,0 @@
/*
* Copyright (C) 2002 Nuno M. Rodrigues.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND NUNO M. RODRIGUES
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* BIND 9.1.x simple database driver
* implementation, using Berkeley DB.
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <isc/file.h>
#include <isc/log.h>
#include <isc/lib.h>
#include <isc/mem.h>
#include <isc/region.h>
#include <isc/result.h>
#include <isc/types.h>
#include <isc/util.h>
#include <dns/sdb.h>
#include <dns/log.h>
#include <dns/lib.h>
#include <dns/ttl.h>
#include <named/bdb.h>
#include <named/globals.h>
#include <named/config.h>
#include <db.h>
#define DRIVERNAME "bdb"
static dns_sdbimplementation_t *bdb_imp;
static isc_result_t
bdb_create(const char *zone, int argc, char **argv,
void *unused, void **dbdata)
{
int ret;
UNUSED(zone);
UNUSED(unused);
if (argc < 1)
return ISC_R_FAILURE; /* database path must be given */
if (db_create((DB **)dbdata, NULL, 0) != 0) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_SDB, ISC_LOG_CRITICAL,
"db_create");
return ISC_R_FAILURE;
}
if (isc_file_exists(*argv) != true) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_SDB, ISC_LOG_CRITICAL,
"isc_file_exists: %s", *argv);
return ISC_R_FAILURE;
}
if ((ret = (*(DB **)dbdata)->open(*(DB **)dbdata, *argv, NULL, DB_HASH,
DB_RDONLY, 0)) != 0) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_SDB, ISC_LOG_CRITICAL,
"DB->open: %s",
db_strerror(ret));
return ISC_R_FAILURE;
}
return ISC_R_SUCCESS;
}
static isc_result_t
#ifdef DNS_CLIENTINFO_VERSION
bdb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *l, dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo)
#else
bdb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *l)
#endif /* DNS_CLIENTINFO_VERSION */
{
int ret;
char *type, *rdata;
dns_ttl_t ttl;
isc_consttextregion_t ttltext;
DBC *c;
DBT key, data;
char *last;
UNUSED(zone);
#ifdef DNS_CLIENTINFO_VERSION
UNUSED(methods);
UNUSED(clientinfo);
#endif /* DNS_CLIENTINFO_VERSION */
if ((ret = ((DB *)dbdata)->cursor((DB *)dbdata, NULL, &c, 0)) != 0) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
"DB->cursor: %s",
db_strerror(ret));
return ISC_R_FAILURE;
}
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
(const char *)key.data = name;
key.size = strlen(name);
ret = c->c_get(c, &key, &data, DB_SET);
while (ret == 0) {
((char *)key.data)[key.size] = 0;
((char *)data.data)[data.size] = 0;
ttltext.base = strtok_r((char *)data.data, " ", &last);
ttltext.length = strlen(ttltext.base);
dns_ttl_fromtext((isc_textregion_t *)&ttltext, &ttl);
type = strtok_r(NULL, " ", &last);
rdata = type + strlen(type) + 1;
if (dns_sdb_putrr(l, type, ttl, rdata) != ISC_R_SUCCESS) {
isc_log_write(dns_lctx,
DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
"dns_sdb_putrr");
return ISC_R_FAILURE;
}
ret = c->c_get(c, &key, &data, DB_NEXT_DUP);
}
c->c_close(c);
return ISC_R_SUCCESS;
}
static isc_result_t
bdb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *n)
{
int ret;
char *type, *rdata;
dns_ttl_t ttl;
isc_consttextregion_t ttltext;
DBC *c;
DBT key, data;
UNUSED(zone);
if ((ret = ((DB *)dbdata)->cursor((DB *)dbdata, NULL, &c, 0)) != 0) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
"DB->cursor: %s",
db_strerror(ret));
return ISC_R_FAILURE;
}
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
while (c->c_get(c, &key, &data, DB_NEXT) == 0) {
char *last;
((char *)key.data)[key.size] = 0;
((char *)data.data)[data.size] = 0;
ttltext.base = strtok_r((char *)data.data, " ", &last);
ttltext.length = strlen(ttltext.base);
dns_ttl_fromtext((isc_textregion_t *)&ttltext, &ttl);
type = strtok_r(NULL, " ", &last);
rdata = type + strlen(type) + 1;
if (dns_sdb_putnamedrr(n, key.data, type, ttl, rdata) !=
ISC_R_SUCCESS) {
isc_log_write(dns_lctx,
DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
"dns_sdb_putnamedrr");
return ISC_R_FAILURE;
}
}
c->c_close(c);
return ISC_R_SUCCESS;
}
static isc_result_t
bdb_destroy(const char *zone, void *unused, void **dbdata)
{
UNUSED(zone);
UNUSED(unused);
(*(DB **)dbdata)->close(*(DB **)dbdata, 0);
return ISC_R_SUCCESS;
}
isc_result_t
bdb_init(void)
{
static dns_sdbmethods_t bdb_methods = {
bdb_lookup,
NULL,
bdb_allnodes,
bdb_create,
bdb_destroy,
NULL /* lookup2 */
};
return dns_sdb_register(DRIVERNAME, &bdb_methods, NULL, 0, ns_g_mctx,
&bdb_imp);
}
void
bdb_clear(void)
{
if (bdb_imp != NULL)
dns_sdb_unregister(&bdb_imp);
}

View File

@ -1,30 +0,0 @@
/*
* Copyright (C) 2002 Nuno M. Rodrigues.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND NUNO M. RODRIGUES
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef BDB_H
#define BDB_H 1
#include <isc/types.h>
/*
* Prototypes.
*/
isc_result_t bdb_init(void);
void bdb_clear(void);
#endif /* BDB_H */

View File

@ -1,187 +0,0 @@
/*
* Copyright (C) 2002 Nuno M. Rodrigues.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND NUNO M. RODRIGUES
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <isc/mem.h>
#include <isc/result.h>
#include <isc/types.h>
#include <isc/util.h>
#include <dns/db.h>
#include <dns/dbiterator.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
#include <dns/rdatatype.h>
#include <dns/ttl.h>
#include <dns/types.h>
#include <db.h>
#define MAX_RDATATEXT 63 + 4 + 65535 + 2 /* ttl + type + rdata + sep */
/*
* Returns a valid 'DB' handle.
*
* Requires:
* 'file' is a valid non-existant path.
*/
DB *
bdb_init(const char *file)
{
DB *db;
REQUIRE(db_create(&db, NULL, 0) == 0);
REQUIRE(db->set_flags(db, DB_DUP) == 0);
REQUIRE(db->open(db, file, NULL, DB_HASH, DB_CREATE | DB_EXCL, 0) == 0);
return db;
}
/*
* Puts resource record data on 'db'.
*/
isc_result_t
bdb_putrdata(DB *db, dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
{
static DBT key, data;
isc_buffer_t keybuf, databuf;
char nametext[DNS_NAME_MAXTEXT];
char rdatatext[MAX_RDATATEXT];
isc_buffer_init(&keybuf, nametext, DNS_NAME_MAXTEXT);
dns_name_totext(name, true, &keybuf);
key.data = isc_buffer_base(&keybuf);
key.size = isc_buffer_usedlength(&keybuf);
isc_buffer_init(&databuf, rdatatext, MAX_RDATATEXT);
dns_ttl_totext(ttl, false, true, &databuf);
*(char *)isc_buffer_used(&databuf) = ' ';
isc_buffer_add(&databuf, 1);
dns_rdatatype_totext(rdata->type, &databuf); /* XXX private data */
*(char *)isc_buffer_used(&databuf) = ' ';
isc_buffer_add(&databuf, 1);
dns_rdata_totext(rdata, NULL, &databuf);
data.data = isc_buffer_base(&databuf);
data.size = isc_buffer_usedlength(&databuf);
REQUIRE(db->put(db, NULL, &key, &data, 0) == 0);
return ISC_R_SUCCESS;
}
isc_result_t
bdb_destroy(DB *db)
{
return (db->close(db, 0) == 0) ? ISC_R_SUCCESS : ISC_R_FAILURE;
}
void
usage(const char *prog)
{
fprintf(stderr, "Usage: %s <origin> <zonefile> <db>\n", prog);
exit(1);
}
int
main(int argc, char *argv[])
{
isc_mem_t *mctx = NULL;
isc_buffer_t b;
int n;
dns_fixedname_t origin, name;
dns_db_t *db = NULL;
dns_dbiterator_t *dbiter = NULL;
isc_result_t res;
dns_dbnode_t *node = NULL;
dns_rdataset_t rdataset;
dns_rdatasetiter_t *rdatasetiter = NULL;
dns_rdata_t rdata;
DB *bdb;
if (argc != 4) usage(*argv);
REQUIRE(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
n = strlen(argv[1]);
isc_buffer_init(&b, argv[1], n);
isc_buffer_add(&b, n);
dns_fixedname_init(&origin);
REQUIRE(dns_name_fromtext(dns_fixedname_name(&origin), &b, dns_rootname,
0, NULL) == ISC_R_SUCCESS);
REQUIRE(dns_db_create(mctx, "rbt", dns_fixedname_name(&origin),
dns_dbtype_zone, dns_rdataclass_in, 0, NULL,
&db) == ISC_R_SUCCESS);
REQUIRE(dns_db_load(db, argv[2], dns_masterformat_text, 0)
== ISC_R_SUCCESS);
REQUIRE(dns_db_createiterator(db, 0, &dbiter) == ISC_R_SUCCESS);
dns_rdataset_init(&rdataset);
dns_rdata_init(&rdata);
dns_fixedname_init(&name);
bdb = bdb_init(argv[3]);
for (res = dns_dbiterator_first(dbiter); res == ISC_R_SUCCESS;
res = dns_dbiterator_next(dbiter)) {
dns_dbiterator_current(dbiter, &node, dns_fixedname_name(&name));
REQUIRE(dns_db_allrdatasets(db, node, NULL, 0, &rdatasetiter)
== ISC_R_SUCCESS);
for (res = dns_rdatasetiter_first(rdatasetiter);
res == ISC_R_SUCCESS;
res = dns_rdatasetiter_next(rdatasetiter)) {
dns_rdatasetiter_current(rdatasetiter, &rdataset);
res = dns_rdataset_first(&rdataset);
while (res == ISC_R_SUCCESS) {
dns_rdataset_current(&rdataset, &rdata);
REQUIRE(bdb_putrdata(bdb,
dns_fixedname_name(&name),
rdataset.ttl, &rdata)
== ISC_R_SUCCESS);
dns_rdata_reset(&rdata);
res = dns_rdataset_next(&rdataset);
}
dns_rdataset_disassociate(&rdataset);
}
dns_rdatasetiter_destroy(&rdatasetiter);
dns_db_detachnode(db, &node);
}
dns_dbiterator_destroy(&dbiter);
REQUIRE(bdb_destroy(bdb) == ISC_R_SUCCESS);
return 0;
}

View File

@ -1,200 +0,0 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*
* A simple database driver that returns basic information about
* files and directories in the Unix file system as DNS data.
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/result.h>
#include <isc/util.h>
#include <dns/sdb.h>
#include <named/globals.h>
#include "dirdb.h"
static dns_sdbimplementation_t *dirdb = NULL;
#define CHECK(op) \
do { result = (op); \
if (result != ISC_R_SUCCESS) return (result); \
} while (0)
#define CHECKN(op) \
do { n = (op); \
if (n < 0) return (ISC_R_FAILURE); \
} while (0)
/*
* This database operates on relative names.
*
* Any name will be interpreted as a pathname offset from the directory
* specified in the configuration file.
*/
#ifdef DNS_CLIENTINFO_VERSION
static isc_result_t
dirdb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo)
#else
static isc_result_t
dirdb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup)
#endif /* DNS_CLIENTINFO_VERSION */
{
char filename[255];
char filename2[255];
char buf[1024];
struct stat statbuf;
isc_result_t result;
int n;
UNUSED(zone);
UNUSED(dbdata);
#ifdef DNS_CLIENTINFO_VERSION
UNUSED(methods);
UNUSED(clientinfo);
#endif /* DNS_CLIENTINFO_VERSION */
if (strcmp(name, "@") == 0)
snprintf(filename, sizeof(filename), "%s", (char *)dbdata);
else
snprintf(filename, sizeof(filename), "%s/%s",
(char *)dbdata, name);
CHECKN(lstat(filename, &statbuf));
if (S_ISDIR(statbuf.st_mode))
CHECK(dns_sdb_putrr(lookup, "txt", 3600, "dir"));
else if (S_ISCHR(statbuf.st_mode) || S_ISBLK(statbuf.st_mode)) {
CHECKN(snprintf(buf, sizeof(buf),
"\"%sdev\" \"major %d\" \"minor %d\"",
S_ISCHR(statbuf.st_mode) ? "chr" : "blk",
major(statbuf.st_rdev),
minor(statbuf.st_rdev)));
CHECK(dns_sdb_putrr(lookup, "txt", 3600, buf));
} else if (S_ISFIFO(statbuf.st_mode))
CHECK(dns_sdb_putrr(lookup, "txt", 3600, "pipe"));
else if (S_ISSOCK(statbuf.st_mode))
CHECK(dns_sdb_putrr(lookup, "txt", 3600, "socket"));
else if (S_ISLNK(statbuf.st_mode)) {
CHECKN(readlink(filename, filename2, sizeof(filename2) - 1));
buf[n] = 0;
CHECKN(snprintf(buf, sizeof(buf), "\"symlink\" \"%s\"",
filename2));
CHECK(dns_sdb_putrr(lookup, "txt", 3600, buf));
} else if (!S_ISREG(statbuf.st_mode))
CHECK(dns_sdb_putrr(lookup, "txt", 3600, "unknown"));
else {
CHECKN(snprintf(buf, sizeof(buf), "\"file\" \"size = %u\"",
(unsigned int)statbuf.st_size));
CHECK(dns_sdb_putrr(lookup, "txt", 3600, buf));
}
return (ISC_R_SUCCESS);
}
/*
* lookup () does not return SOA or NS records, so authority() must be defined.
*/
static isc_result_t
dirdb_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
isc_result_t result;
UNUSED(zone);
UNUSED(dbdata);
result = dns_sdb_putsoa(lookup, "ns", "hostmaster", 0);
INSIST(result == ISC_R_SUCCESS);
result = dns_sdb_putrr(lookup, "ns", 86400, "ns1");
INSIST(result == ISC_R_SUCCESS);
result = dns_sdb_putrr(lookup, "ns", 86400, "ns2");
INSIST(result == ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
}
/*
* Each database stores the top-level directory as the dbdata opaque
* object. The create() function allocates it. argv[0] holds the top
* level directory.
*/
static isc_result_t
dirdb_create(const char *zone, int argc, char **argv,
void *driverdata, void **dbdata)
{
UNUSED(zone);
UNUSED(driverdata);
if (argc < 1)
return (ISC_R_FAILURE);
*dbdata = isc_mem_strdup((isc_mem_t *)driverdata, argv[0]);
if (*dbdata == NULL)
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
}
/*
* The destroy() function frees the memory allocated by create().
*/
static void
dirdb_destroy(const char *zone, void *driverdata, void **dbdata) {
UNUSED(zone);
UNUSED(driverdata);
isc_mem_free((isc_mem_t *)driverdata, *dbdata);
}
/*
* This zone does not support zone transfer, so allnodes() is NULL.
*/
static dns_sdbmethods_t dirdb_methods = {
dirdb_lookup,
dirdb_authority,
NULL, /* allnodes */
dirdb_create,
dirdb_destroy,
NULL /* lookup2 */
};
/*
* Wrapper around dns_sdb_register(). Note that the first ns_g_mctx is
* being passed as the "driverdata" parameter, so that will it will be
* passed to create() and destroy().
*/
isc_result_t
dirdb_init(void) {
unsigned int flags;
flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA |
DNS_SDBFLAG_THREADSAFE;
return (dns_sdb_register("dir", &dirdb_methods, ns_g_mctx, flags,
ns_g_mctx, &dirdb));
}
/*
* Wrapper around dns_sdb_unregister().
*/
void
dirdb_clear(void) {
if (dirdb != NULL)
dns_sdb_unregister(&dirdb);
}

View File

@ -1,18 +0,0 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <isc/types.h>
isc_result_t dirdb_init(void);
void dirdb_clear(void);

View File

@ -1,83 +0,0 @@
This is the INSTALL file for 1.0-beta. See
http://www.venaas.no/ldap/bind-sdb/ for updates or other information.
BUILDING
You need the source for BIND 9.1.0 or newer (for zone transfers you
will need at least 9.1.1rc3 due to a bug). Basically you need to follow
the instructions in doc/misc/sdb, if my instructions don't make sense,
please have a look at those as well.
Copy ldapdb.c to bin/named and ldapdb.h to bin/named/include in the
source tree.
Next alter bin/named/Makefile.in. Add ldapdb.@O@ to DBDRIVER_OBJS and
ldapdb.c to DBDRIVER_SRCS. You also need to add something like
-I/usr/local/include to DBDRIVER_INCLUDES and
-L/usr/local/lib -lldap -llber -lresolv to DBDRIVER_LIBS
depending on what LDAP library you have and where you installed it.
Finally you need to edit bin/named/main.c. Below where it says
"#include "xxdb.h"", add the line "#include <ldapdb.h>". Below where
it says "xxdb_init();" add the line "ldapdb_init();", and finally
below where it says "xxdb_clear();", add "ldapdb_clear();".
Now you should hopefully be able to build as usual; first configure
and then make. If you get an error message about ldap_memfree() not
being defined, you're probably using an LDAP library with the
interface defined in RFC 1823. To build, uncomment the "#define
LDAPDB_RFC1823API" line near the top of ldapdb.c.
Also, if you're using an LDAPv2 only server, you need to change
the line "#define LDAPDB_LDAP_VERSION 3" in ldapdb.c. Simply
replace 3 with 2. Instead of editing the file, you may define
LDAPDB_LDAP_VERSION yourself.
If you want to use TLS, you need to uncommed the #define LDAPDB_TLS"
line near the top of ldapdb.c.
CONFIGURING
Before you do any configuring of LDAP stuff, please try to configure
and start bind as usual to see if things work.
To do anything useful, you need to store a zone in some LDAP server.
You must use a schema called dNSZone. Note that it relies on some
attribute definitions in the Cosine schema, so that must be included
as well. The Cosine schema probably comes with your LDAP server. You
can find dNSZone and further details on how to store the data in your
LDAP server at http://www.venaas.no/ldap/bind-sdb/
To make BIND use a zone stored in LDAP, you will have to put something
like this in named.conf:
zone "venaas.com" {
type master;
database "ldap ldap://158.38.160.245/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no 172800";
};
When doing lookups BIND will do a sub-tree search below the base in the
URL. The number 172800 is the TTL which will be used for all entries that
haven't got the dNSTTL attribute. It is also possible to add a filter to
the URL, say "ldap://host/base???(o=internal)".
Version 1.0 also has support for simple LDAP bind, that is, binding to
LDAP using plain text authentication. The bind dn and password is coded
into the URL as extensions, according to RFC 2255. If you want simple
bind with say dn "cn=Manager,dc=venaas,dc=no" and password "secret", the
URL will be something like this:
ldap://158.38.160.245/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no????!bindname=cn=Manager%2cdc=venaas%2cdc=no,!x-bindpw=secret
This URL may also include a filter part if you need it. Note that in
the bind dn, "," is hex-escaped as "%2c". This is necessary since ","
is the separator between the extension elements. The "!" in front of
"bindname" and "x-bindpw" can be omitted if you prefer. "x-bindpw" is
not standardized, but it's used by several other LDAP applications. See
RFC 2255 for details.
Finally, if you enabled TLS when compiling, you can also use TLS if
you like. To do this you use the extension "x-tls", e.g.
ldap://158.38.160.245/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no????!bindname=cn=Manager%2cdc=venaas%2cdc=no,!x-bindpw=secret,x-tls
Stig Venaas <venaas@uninett.no> 2004-08-15

View File

@ -1,48 +0,0 @@
This is an attempt at an LDAP back-end for BIND 9 using the new simplified
database interface "sdb". This is release 1.0-beta and should be pretty
stable. Note that since version 0.4 a new schema is used. It is not
backwards compatible with versions before 0.4.
1.0-beta fixes a large memory leak. An extension x-tls for enabling TLS
has been added.
1.0-alpha uses LDAPv3 by default and also supports LDAP simple bind. That
is, one can use plain text password for authentication. The bind dn and
password is coded into the URL using extensions bindname and x-bindpw
per RFC 2255.
In 0.9 the code has been cleaned up a bit and should be slightly faster
than previous versions. It also fixes an error with zone transfers (AXFR)
and entries with multiple relativeDomainName values. The problem was
that it would only use the first value in the result. There's no need
to upgrade unless you use such entries.
0.8 uses asynchronous LDAP search which should give better performance.
Thanks to Ashley Burston for providing patch. Another new feature is
allowing filters in URLs. The syntax is as in RFC 2255. Few people will
need this, but if you have say an internal and external version of the
same zone, you could stick say o=internal and o=external into different
entries, and specify for instance ldap://host/base???(o=internal)
Some error logging has also been added.
0.7 allows space and other characters to be used in URLs by use of %-quoting.
For instance space can be written as %20. It also fixes a problem with some
servers and/or APIs that do not preserve attribute casing.
0.6 fixes some memory leaks present in older versions unless compiled with
the RFC 1823 API.
The big changes in 0.5 are thread support and improved connection handling.
Multiple threads can now access the back-end simultaneously, and rather than
having one connection per zone, there is now one connection per thread per
LDAP server. This should help people with multiple CPUs and people with a
huge number of zones. One final change is support for literal IPv6 addresses
in LDAP URLs. At least OpenLDAP 2 has IPv6 support, so if you use OpenLDAP 2
libraries and server, you got all you need.
If you have bug reports, fixes, comments, questions or whatever, please
contact me. See also http://www.venaas.no/ldap/bind-sdb/ for information.
See INSTALL for how to build, install and use.
Stig Venaas <venaas@uninett.no> 2004-08-15

View File

@ -1,17 +0,0 @@
INSTALLATION
To Compile zone2ldap from contrib/sdb directory:
gcc -g `../../../isc-config.sh --cflags isc dns` -c zone2ldap.c
gcc -g -o zone2ldap zone2ldap.o `../../../isc-config.sh --libs isc dns` -lldap -llber -lresolv
USAGE:
See zone2ldap.1
BUGS:
Jeff McNeil <jeff@snapcase.g-rock.net>

View File

@ -1,690 +0,0 @@
/*
* ldapdb.c version 1.0-beta
*
* Copyright (C) 2002, 2004 Stig Venaas
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* Contributors: Jeremy C. McDermond
*/
/*
* If you want to use TLS, uncomment the define below
*/
/* #define LDAPDB_TLS */
/*
* If you are using an old LDAP API uncomment the define below. Only do this
* if you know what you're doing or get compilation errors on ldap_memfree().
* This also forces LDAPv2.
*/
/* #define LDAPDB_RFC1823API */
/* Using LDAPv3 by default, change this if you want v2 */
#ifndef LDAPDB_LDAP_VERSION
#define LDAPDB_LDAP_VERSION 3
#endif
#include <config.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/result.h>
#include <isc/util.h>
#include <isc/thread.h>
#include <dns/sdb.h>
#include <named/globals.h>
#include <named/log.h>
#include <ldap.h>
#include "ldapdb.h"
/*
* A simple database driver for LDAP
*/
/* enough for name with 8 labels of max length */
#define MAXNAMELEN 519
static dns_sdbimplementation_t *ldapdb = NULL;
struct ldapdb_data {
char *hostport;
char *hostname;
int portno;
char *base;
int defaultttl;
char *filterall;
int filteralllen;
char *filterone;
int filteronelen;
char *filtername;
char *bindname;
char *bindpw;
#ifdef LDAPDB_TLS
int tls;
#endif
};
/* used by ldapdb_getconn */
struct ldapdb_entry {
void *index;
size_t size;
void *data;
struct ldapdb_entry *next;
};
static struct ldapdb_entry *ldapdb_find(struct ldapdb_entry *stack,
const void *index, size_t size) {
while (stack != NULL) {
if (stack->size == size && !memcmp(stack->index, index, size))
return stack;
stack = stack->next;
}
return NULL;
}
static void ldapdb_insert(struct ldapdb_entry **stack,
struct ldapdb_entry *item) {
item->next = *stack;
*stack = item;
}
static void ldapdb_lock(int what) {
static isc_mutex_t lock;
switch (what) {
case 0:
isc_mutex_init(&lock);
break;
case 1:
LOCK(&lock);
break;
case -1:
UNLOCK(&lock);
break;
}
}
/* data == NULL means cleanup */
static LDAP **
ldapdb_getconn(struct ldapdb_data *data)
{
static struct ldapdb_entry *allthreadsdata = NULL;
struct ldapdb_entry *threaddata, *conndata;
unsigned long threadid;
if (data == NULL) {
/* cleanup */
/* lock out other threads */
ldapdb_lock(1);
while (allthreadsdata != NULL) {
threaddata = allthreadsdata;
free(threaddata->index);
while (threaddata->data != NULL) {
conndata = threaddata->data;
if (conndata->data != NULL)
ldap_unbind((LDAP *)conndata->data);
threaddata->data = conndata->next;
free(conndata);
}
allthreadsdata = threaddata->next;
free(threaddata);
}
ldapdb_lock(-1);
return (NULL);
}
/* look for connection data for current thread */
threadid = isc_thread_self();
threaddata = ldapdb_find(allthreadsdata, &threadid, sizeof(threadid));
if (threaddata == NULL) {
/* no data for this thread, create empty connection list */
threaddata = malloc(sizeof(*threaddata));
if (threaddata == NULL)
return (NULL);
threaddata->index = malloc(sizeof(threadid));
if (threaddata->index == NULL) {
free(threaddata);
return (NULL);
}
*(unsigned long *)threaddata->index = threadid;
threaddata->size = sizeof(threadid);
threaddata->data = NULL;
/* need to lock out other threads here */
ldapdb_lock(1);
ldapdb_insert(&allthreadsdata, threaddata);
ldapdb_lock(-1);
}
/* threaddata points at the connection list for current thread */
/* look for existing connection to our server */
conndata = ldapdb_find((struct ldapdb_entry *)threaddata->data,
data->hostport, strlen(data->hostport));
if (conndata == NULL) {
/* no connection data structure for this server, create one */
conndata = malloc(sizeof(*conndata));
if (conndata == NULL)
return (NULL);
conndata->index = data->hostport;
conndata->size = strlen(data->hostport);
conndata->data = NULL;
ldapdb_insert((struct ldapdb_entry **)&threaddata->data,
conndata);
}
return (LDAP **)&conndata->data;
}
static void
ldapdb_bind(struct ldapdb_data *data, LDAP **ldp)
{
#ifndef LDAPDB_RFC1823API
const int ver = LDAPDB_LDAP_VERSION;
#endif
if (*ldp != NULL)
ldap_unbind(*ldp);
*ldp = ldap_open(data->hostname, data->portno);
if (*ldp == NULL)
return;
#ifndef LDAPDB_RFC1823API
ldap_set_option(*ldp, LDAP_OPT_PROTOCOL_VERSION, &ver);
#endif
#ifdef LDAPDB_TLS
if (data->tls) {
ldap_start_tls_s(*ldp, NULL, NULL);
}
#endif
if (ldap_simple_bind_s(*ldp, data->bindname, data->bindpw) != LDAP_SUCCESS) {
ldap_unbind(*ldp);
*ldp = NULL;
}
}
#ifdef DNS_CLIENTINFO_VERSION
static isc_result_t
ldapdb_search(const char *zone, const char *name, void *dbdata, void *retdata,
dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
#else
static isc_result_t
ldapdb_search(const char *zone, const char *name, void *dbdata, void *retdata,
void *methods, void *clientinfo)
#endif /* DNS_CLIENTINFO_VERSION */
{
struct ldapdb_data *data = dbdata;
isc_result_t result = ISC_R_NOTFOUND;
LDAP **ldp;
LDAPMessage *res, *e;
char *fltr, *a, **vals = NULL, **names = NULL;
char type[64];
#ifdef LDAPDB_RFC1823API
void *ptr;
#else
BerElement *ptr;
#endif
int i, j, errno, msgid;
UNUSED(methods);
UNUSED(clientinfo);
ldp = ldapdb_getconn(data);
if (ldp == NULL)
return (ISC_R_FAILURE);
if (*ldp == NULL) {
ldapdb_bind(data, ldp);
if (*ldp == NULL) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"LDAP sdb zone '%s': bind failed", zone);
return (ISC_R_FAILURE);
}
}
if (name == NULL) {
fltr = data->filterall;
} else {
if (strlen(name) > MAXNAMELEN) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"LDAP sdb zone '%s': name %s too long", zone, name);
return (ISC_R_FAILURE);
}
sprintf(data->filtername, "%s))", name);
fltr = data->filterone;
}
msgid = ldap_search(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0);
if (msgid == -1) {
ldapdb_bind(data, ldp);
if (*ldp != NULL)
msgid = ldap_search(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0);
}
if (*ldp == NULL || msgid == -1) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"LDAP sdb zone '%s': search failed, filter %s", zone, fltr);
return (ISC_R_FAILURE);
}
/* Get the records one by one as they arrive and return them to bind */
while ((errno = ldap_result(*ldp, msgid, 0, NULL, &res)) != LDAP_RES_SEARCH_RESULT ) {
LDAP *ld = *ldp;
int ttl = data->defaultttl;
/* not supporting continuation references at present */
if (errno != LDAP_RES_SEARCH_ENTRY) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"LDAP sdb zone '%s': ldap_result returned %d", zone, errno);
ldap_msgfree(res);
return (ISC_R_FAILURE);
}
/* only one entry per result message */
e = ldap_first_entry(ld, res);
if (e == NULL) {
ldap_msgfree(res);
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"LDAP sdb zone '%s': ldap_first_entry failed", zone);
return (ISC_R_FAILURE);
}
if (name == NULL) {
names = ldap_get_values(ld, e, "relativeDomainName");
if (names == NULL)
continue;
}
vals = ldap_get_values(ld, e, "dNSTTL");
if (vals != NULL) {
ttl = atoi(vals[0]);
ldap_value_free(vals);
}
for (a = ldap_first_attribute(ld, e, &ptr); a != NULL; a = ldap_next_attribute(ld, e, ptr)) {
char *s;
for (s = a; *s; s++)
*s = toupper(*s);
s = strstr(a, "RECORD");
if ((s == NULL) || (s == a) || (s - a >= (signed int)sizeof(type))) {
#ifndef LDAPDB_RFC1823API
ldap_memfree(a);
#endif
continue;
}
strncpy(type, a, s - a);
type[s - a] = '\0';
vals = ldap_get_values(ld, e, a);
if (vals != NULL) {
for (i = 0; vals[i] != NULL; i++) {
if (name != NULL) {
result = dns_sdb_putrr(retdata, type, ttl, vals[i]);
} else {
for (j = 0; names[j] != NULL; j++) {
result = dns_sdb_putnamedrr(retdata, names[j], type, ttl, vals[i]);
if (result != ISC_R_SUCCESS)
break;
}
}
; if (result != ISC_R_SUCCESS) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"LDAP sdb zone '%s': dns_sdb_put... failed for %s", zone, vals[i]);
ldap_value_free(vals);
#ifndef LDAPDB_RFC1823API
ldap_memfree(a);
if (ptr != NULL)
ber_free(ptr, 0);
#endif
if (name == NULL)
ldap_value_free(names);
ldap_msgfree(res);
return (ISC_R_FAILURE);
}
}
ldap_value_free(vals);
}
#ifndef LDAPDB_RFC1823API
ldap_memfree(a);
#endif
}
#ifndef LDAPDB_RFC1823API
if (ptr != NULL)
ber_free(ptr, 0);
#endif
if (name == NULL)
ldap_value_free(names);
/* free this result */
ldap_msgfree(res);
}
/* free final result */
ldap_msgfree(res);
return (result);
}
/* callback routines */
#ifdef DNS_CLIENTINFO_VERSION
static isc_result_t
ldapdb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo)
{
UNUSED(methods);
UNUSED(clientinfo);
return (ldapdb_search(zone, name, dbdata, lookup, NULL, NULL));
}
#else
static isc_result_t
ldapdb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup)
{
return (ldapdb_search(zone, name, dbdata, lookup, methods,
clientinfo));
}
#endif /* DNS_CLIENTINFO_VERSION */
static isc_result_t
ldapdb_allnodes(const char *zone, void *dbdata,
dns_sdballnodes_t *allnodes)
{
return (ldapdb_search(zone, NULL, dbdata, allnodes, NULL, NULL));
}
static char *
unhex(char *in)
{
static const char hexdigits[] = "0123456789abcdef";
char *p, *s = in;
int d1, d2;
while ((s = strchr(s, '%'))) {
if (!(s[1] && s[2]))
return NULL;
if ((p = strchr(hexdigits, tolower(s[1]))) == NULL)
return NULL;
d1 = p - hexdigits;
if ((p = strchr(hexdigits, tolower(s[2]))) == NULL)
return NULL;
d2 = p - hexdigits;
*s++ = d1 << 4 | d2;
memmove(s, s + 2, strlen(s) - 1);
}
return in;
}
/* returns 0 for ok, -1 for bad syntax, -2 for unknown critical extension */
static int
parseextensions(char *extensions, struct ldapdb_data *data)
{
char *s, *next, *name, *value;
int critical;
while (extensions != NULL) {
s = strchr(extensions, ',');
if (s != NULL) {
*s++ = '\0';
next = s;
} else {
next = NULL;
}
if (*extensions != '\0') {
s = strchr(extensions, '=');
if (s != NULL) {
*s++ = '\0';
value = *s != '\0' ? s : NULL;
} else {
value = NULL;
}
name = extensions;
critical = *name == '!';
if (critical) {
name++;
}
if (*name == '\0') {
return -1;
}
if (!strcasecmp(name, "bindname")) {
data->bindname = value;
} else if (!strcasecmp(name, "x-bindpw")) {
data->bindpw = value;
#ifdef LDAPDB_TLS
} else if (!strcasecmp(name, "x-tls")) {
data->tls = value == NULL || !strcasecmp(value, "true");
#endif
} else if (critical) {
return -2;
}
}
extensions = next;
}
return 0;
}
static void
free_data(struct ldapdb_data *data)
{
if (data->hostport != NULL)
isc_mem_free(ns_g_mctx, data->hostport);
if (data->hostname != NULL)
isc_mem_free(ns_g_mctx, data->hostname);
if (data->filterall != NULL)
isc_mem_put(ns_g_mctx, data->filterall, data->filteralllen);
if (data->filterone != NULL)
isc_mem_put(ns_g_mctx, data->filterone, data->filteronelen);
isc_mem_put(ns_g_mctx, data, sizeof(struct ldapdb_data));
}
static isc_result_t
ldapdb_create(const char *zone, int argc, char **argv,
void *driverdata, void **dbdata)
{
struct ldapdb_data *data;
char *s, *filter = NULL, *extensions = NULL;
int defaultttl;
UNUSED(driverdata);
/* we assume that only one thread will call create at a time */
/* want to do this only once for all instances */
if ((argc < 2)
|| (argv[0] != strstr( argv[0], "ldap://"))
|| ((defaultttl = atoi(argv[1])) < 1))
return (ISC_R_FAILURE);
data = isc_mem_get(ns_g_mctx, sizeof(struct ldapdb_data));
if (data == NULL)
return (ISC_R_NOMEMORY);
memset(data, 0, sizeof(struct ldapdb_data));
data->hostport = isc_mem_strdup(ns_g_mctx, argv[0] + strlen("ldap://"));
if (data->hostport == NULL) {
free_data(data);
return (ISC_R_NOMEMORY);
}
data->defaultttl = defaultttl;
s = strchr(data->hostport, '/');
if (s != NULL) {
*s++ = '\0';
data->base = s;
/* attrs, scope, filter etc? */
s = strchr(s, '?');
if (s != NULL) {
*s++ = '\0';
/* ignore attributes */
s = strchr(s, '?');
if (s != NULL) {
*s++ = '\0';
/* ignore scope */
s = strchr(s, '?');
if (s != NULL) {
*s++ = '\0';
/* filter */
filter = s;
s = strchr(s, '?');
if (s != NULL) {
*s++ = '\0';
/* extensions */
extensions = s;
s = strchr(s, '?');
if (s != NULL) {
*s++ = '\0';
}
if (*extensions == '\0') {
extensions = NULL;
}
}
if (*filter == '\0') {
filter = NULL;
}
}
}
}
if (*data->base == '\0') {
data->base = NULL;
}
}
/* parse extensions */
if (extensions != NULL) {
int err;
err = parseextensions(extensions, data);
if (err < 0) {
/* err should be -1 or -2 */
free_data(data);
if (err == -1) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"LDAP sdb zone '%s': URL: extension syntax error", zone);
} else if (err == -2) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"LDAP sdb zone '%s': URL: unknown critical extension", zone);
}
return (ISC_R_FAILURE);
}
}
if ((data->base != NULL && unhex(data->base) == NULL) ||
(filter != NULL && unhex(filter) == NULL) ||
(data->bindname != NULL && unhex(data->bindname) == NULL) ||
(data->bindpw != NULL && unhex(data->bindpw) == NULL)) {
free_data(data);
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"LDAP sdb zone '%s': URL: bad hex values", zone);
return (ISC_R_FAILURE);
}
/* compute filterall and filterone once and for all */
if (filter == NULL) {
data->filteralllen = strlen(zone) + strlen("(zoneName=)") + 1;
data->filteronelen = strlen(zone) + strlen("(&(zoneName=)(relativeDomainName=))") + MAXNAMELEN + 1;
} else {
data->filteralllen = strlen(filter) + strlen(zone) + strlen("(&(zoneName=))") + 1;
data->filteronelen = strlen(filter) + strlen(zone) + strlen("(&(zoneName=)(relativeDomainName=))") + MAXNAMELEN + 1;
}
data->filterall = isc_mem_get(ns_g_mctx, data->filteralllen);
if (data->filterall == NULL) {
free_data(data);
return (ISC_R_NOMEMORY);
}
data->filterone = isc_mem_get(ns_g_mctx, data->filteronelen);
if (data->filterone == NULL) {
free_data(data);
return (ISC_R_NOMEMORY);
}
if (filter == NULL) {
sprintf(data->filterall, "(zoneName=%s)", zone);
sprintf(data->filterone, "(&(zoneName=%s)(relativeDomainName=", zone);
} else {
sprintf(data->filterall, "(&%s(zoneName=%s))", filter, zone);
sprintf(data->filterone, "(&%s(zoneName=%s)(relativeDomainName=", filter, zone);
}
data->filtername = data->filterone + strlen(data->filterone);
/* support URLs with literal IPv6 addresses */
data->hostname = isc_mem_strdup(ns_g_mctx, data->hostport + (*data->hostport == '[' ? 1 : 0));
if (data->hostname == NULL) {
free_data(data);
return (ISC_R_NOMEMORY);
}
if (*data->hostport == '[' &&
(s = strchr(data->hostname, ']')) != NULL )
*s++ = '\0';
else
s = data->hostname;
s = strchr(s, ':');
if (s != NULL) {
*s++ = '\0';
data->portno = atoi(s);
} else
data->portno = LDAP_PORT;
*dbdata = data;
return (ISC_R_SUCCESS);
}
static void
ldapdb_destroy(const char *zone, void *driverdata, void **dbdata) {
struct ldapdb_data *data = *dbdata;
UNUSED(zone);
UNUSED(driverdata);
free_data(data);
}
static dns_sdbmethods_t ldapdb_methods = {
ldapdb_lookup,
NULL, /* authority */
ldapdb_allnodes,
ldapdb_create,
ldapdb_destroy,
NULL /* lookup2 */
};
/* Wrapper around dns_sdb_register() */
isc_result_t
ldapdb_init(void) {
unsigned int flags =
DNS_SDBFLAG_RELATIVEOWNER |
DNS_SDBFLAG_RELATIVERDATA |
DNS_SDBFLAG_THREADSAFE;
ldapdb_lock(0);
return (dns_sdb_register("ldap", &ldapdb_methods, NULL, flags,
ns_g_mctx, &ldapdb));
}
/* Wrapper around dns_sdb_unregister() */
void
ldapdb_clear(void) {
if (ldapdb != NULL) {
/* clean up thread data */
ldapdb_getconn(NULL);
dns_sdb_unregister(&ldapdb);
}
}

View File

@ -1,6 +0,0 @@
#include <isc/types.h>
isc_result_t ldapdb_init(void);
void ldapdb_clear(void);

View File

@ -1,64 +0,0 @@
.TH zone2ldap 1 "8 March 2001"
.SH NAME
zone2ldap /- Load BIND 9 Zone files into LDAP Directory
.SH SYNOPSIS
zone2ldap [-D Bind DN] [-w Bind Password] [-b Base DN] [-z Zone] [-f Zone File ] [-h Ldap Host] [-cd] [-v]
.SH DESCRIPTION
zone2ldap will parse a complete BIND 9 format DNS zone file, and load
the contents into an LDAP directory, for use with the LDAP sdb back-end.
If the zone already exists, zone2ldap will exit succesfully. If the zone does not exists, or
partially exists, zone2ldap will attempt to add all/missing zone data.
.SS Options
.TP
-b
LDAP Base DN. LDAP systems require a "base dn", which is generally considered the LDAP Directory root.
If the zone you are loading is different from the base, then you will need to tell zone2ldap what your LDAP
base is.
.TP
-v
Print version information, and immediatly exit.
.TP
-f
Zone file. Bind 9.1 compatible zone file, from which zone information will be read.
.TP
-d
Dump debug information to standard out.
.TP
-w
LDAP Bind password, corresponding the the value of "-b".
.TP
-h
LDAP Directory host. This is the hostname of the LDAP system you wish to store zone information on.
An LDAP server should be listening on port 389 of the target system. This may be ommited, and will default
to "localhost".
.TP
-c
This will create the zone portion of the DN you are importing. For instance, if you are creating a domain.com zone,
zone2ldap should first create "dc=domain,dc=com". This is useful if you are creating multiple domains.
.TP
-z
This is the name of the zone specified in the SOA record.
.SH EXAMPLES
Following are brief examples of how to import a zone file into your LDAP DIT.
.SS Loading zone domain.com, with an LDAP Base DN of dc=domain,dc=com
zone2ldap -D dc=root -w secret -h localhost -z domain.com -f domain.com.zone
This will add Resource Records into an ALREADY EXISTING dc=domain,dc=com. The final SOA DN in this case, will be
dc=@,dc=domain,dc=com
.SS Loading customer.com, if your LDAP Base DN is dc=provider,dc=net.
zone2ldap -D dc=root -w secret -h localhost -z customer.com -b dc=provider,dc=net -f customer.com.zone -c
This will create dc=customer,dc=com under dc=provider,dc=net, and add all necessary Resource Records. The final
root DN to the SOA will be dc=@,dc=customer,dc=com,dc=provider,dc=net.
.SH "SEE ALSO"
named(8) ldap(3)
http://www.venaas.no/ldap/bind-sdb/
.SH "BUGS"
Send all bug reports to Jeff McNeil <jeff@snapcase.g-rock.net>
.SH AUTHOR
Jeff McNeil <jeff@snapcase.g-rock.net>

View File

@ -1,762 +0,0 @@
/*
* Copyright (C) 2001 Jeff McNeil <jeff@snapcase.g-rock.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* Change Log
*
* Tue May 1 19:19:54 EDT 2001 - Jeff McNeil
* Update to objectClass code, and add_to_rr_list function
* (I need to rename that) to support the dNSZone schema,
* ditched dNSDomain2 schema support. Version 0.3-ALPHA
*/
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <isc/buffer.h>
#include <isc/hash.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/result.h>
#include <isc/string.h>
#include <dns/db.h>
#include <dns/dbiterator.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
#include <dns/result.h>
#include <dns/rdatatype.h>
#define LDAP_DEPRECATED 1
#include <ldap.h>
#define DNS_OBJECT 6
#define DNS_TOP 2
#define VERSION "0.4-ALPHA"
#define NO_SPEC 0
#define WI_SPEC 1
/* Global Zone Pointer */
char *gbl_zone = NULL;
typedef struct LDAP_INFO
{
char *dn;
LDAPMod **attrs;
struct LDAP_INFO *next;
int attrcnt;
}
ldap_info;
/* usage Info */
void usage ();
/* Add to the ldap dit */
void add_ldap_values (ldap_info * ldinfo);
/* Init an ldap connection */
void init_ldap_conn ();
/* Ldap error checking */
void ldap_result_check (char *msg, char *dn, int err);
/* Put a hostname into a char ** array */
char **hostname_to_dn_list (char *hostname, char *zone, unsigned int flags);
/* Find out how many items are in a char ** array */
int get_attr_list_size (char **tmp);
/* Get a DN */
char *build_dn_from_dc_list (char **dc_list, unsigned int ttl, int flag);
/* Add to RR list */
void add_to_rr_list (char *dn, char *name, char *type, char *data,
unsigned int ttl, unsigned int flags);
/* Error checking */
void isc_result_check (isc_result_t res, char *errorstr);
/* Generate LDIF Format files */
void generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata,
unsigned int ttl);
/* head pointer to the list */
ldap_info *ldap_info_base = NULL;
char *argzone, *ldapbase, *binddn, *bindpw = NULL;
char *ldapsystem = "localhost";
static char *objectClasses[] =
{ "top", "dNSZone", NULL };
static char *topObjectClasses[] = { "top", NULL };
LDAP *conn;
unsigned int debug = 0;
#ifdef DEBUG
debug = 1;
#endif
static void
fatal(const char *msg) {
perror(msg);
if (conn != NULL)
ldap_unbind_s(conn);
exit(1);
}
int
main (int argc, char **argv)
{
isc_mem_t *mctx = NULL;
isc_result_t result;
char *basedn;
ldap_info *tmp;
LDAPMod *base_attrs[2];
LDAPMod base;
isc_buffer_t buff;
char *zonefile;
char fullbasedn[1024];
char *ctmp;
dns_fixedname_t fixedzone, fixedname;
dns_rdataset_t rdataset;
char **dc_list;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdatasetiter_t *riter;
dns_name_t *zone, *name;
dns_db_t *db = NULL;
dns_dbiterator_t *dbit = NULL;
dns_dbnode_t *node;
extern char *optarg;
extern int optind, opterr, optopt;
int create_base = 0;
int topt;
if (argc < 2)
{
usage ();
exit (-1);
}
while ((topt = getopt (argc, argv, "D:w:b:z:f:h:?dcv")) != -1)
{
switch (topt)
{
case 'v':
printf("%s\n", VERSION);
exit(0);
case 'c':
create_base++;
break;
case 'd':
debug++;
break;
case 'D':
binddn = strdup (optarg);
if (binddn == NULL)
fatal("strdup");
break;
case 'w':
bindpw = strdup (optarg);
if (bindpw == NULL)
fatal("strdup");
break;
case 'b':
ldapbase = strdup (optarg);
if (ldapbase == NULL)
fatal("strdup");
break;
case 'z':
argzone = strdup (optarg);
// We wipe argzone all to hell when we parse it for the DN */
gbl_zone = strdup(argzone);
if (argzone == NULL || gbl_zone == NULL)
fatal("strdup");
break;
case 'f':
zonefile = strdup (optarg);
if (zonefile == NULL)
fatal("strdup");
break;
case 'h':
ldapsystem = strdup (optarg);
if (ldapsystem == NULL)
fatal("strdup");
break;
case '?':
default:
usage ();
exit (0);
}
}
if ((argzone == NULL) || (zonefile == NULL))
{
usage ();
exit (-1);
}
if (debug)
printf ("Initializing ISC Routines, parsing zone file\n");
result = isc_mem_create (0, 0, &mctx);
isc_result_check (result, "isc_mem_create");
isc_buffer_init (&buff, argzone, strlen (argzone));
isc_buffer_add (&buff, strlen (argzone));
zone = dns_fixedname_initname(&fixedzone);
result = dns_name_fromtext (zone, &buff, dns_rootname, 0, NULL);
isc_result_check (result, "dns_name_fromtext");
result = dns_db_create (mctx, "rbt", zone, dns_dbtype_zone,
dns_rdataclass_in, 0, NULL, &db);
isc_result_check (result, "dns_db_create");
result = dns_db_load(db, zonefile, dns_masterformat_text, 0);
isc_result_check (result, "Check Zone Syntax: dns_db_load");
result = dns_db_createiterator (db, 0, &dbit);
isc_result_check (result, "dns_db_createiterator");
result = dns_dbiterator_first (dbit);
isc_result_check (result, "dns_dbiterator_first");
name = dns_fixedname_initname(&fixedname);
dns_rdataset_init (&rdataset);
dns_rdata_init (&rdata);
while (result == ISC_R_SUCCESS)
{
node = NULL;
result = dns_dbiterator_current (dbit, &node, name);
if (result == ISC_R_NOMORE)
break;
isc_result_check (result, "dns_dbiterator_current");
riter = NULL;
result = dns_db_allrdatasets (db, node, NULL, 0, &riter);
isc_result_check (result, "dns_db_allrdatasets");
result = dns_rdatasetiter_first (riter);
//isc_result_check(result, "dns_rdatasetiter_first");
while (result == ISC_R_SUCCESS)
{
dns_rdatasetiter_current (riter, &rdataset);
result = dns_rdataset_first (&rdataset);
isc_result_check (result, "dns_rdatasetiter_current");
while (result == ISC_R_SUCCESS)
{
dns_rdataset_current (&rdataset, &rdata);
generate_ldap (name, &rdata, rdataset.ttl);
dns_rdata_reset (&rdata);
result = dns_rdataset_next (&rdataset);
}
dns_rdataset_disassociate (&rdataset);
result = dns_rdatasetiter_next (riter);
}
dns_rdatasetiter_destroy (&riter);
result = dns_dbiterator_next (dbit);
}
/* Initialize the LDAP Connection */
if (debug)
printf ("Initializing LDAP Connection to %s as %s\n", ldapsystem, binddn);
init_ldap_conn ();
if (create_base)
{
if (debug)
printf ("Creating base zone DN %s\n", argzone);
dc_list = hostname_to_dn_list (argzone, argzone, DNS_TOP);
basedn = build_dn_from_dc_list (dc_list, 0, NO_SPEC);
for (ctmp = &basedn[strlen (basedn)]; ctmp >= &basedn[0]; ctmp--)
{
if ((*ctmp == ',') || (ctmp == &basedn[0]))
{
base.mod_op = LDAP_MOD_ADD;
base.mod_type = "objectClass";
base.mod_values = topObjectClasses;
base_attrs[0] = &base;
base_attrs[1] = NULL;
if (ldapbase)
{
if (ctmp != &basedn[0])
sprintf (fullbasedn, "%s,%s", ctmp + 1, ldapbase);
else
sprintf (fullbasedn, "%s,%s", ctmp, ldapbase);
}
else
{
if (ctmp != &basedn[0])
sprintf (fullbasedn, "%s", ctmp + 1);
else
sprintf (fullbasedn, "%s", ctmp);
}
result = ldap_add_s (conn, fullbasedn, base_attrs);
ldap_result_check ("intial ldap_add_s", fullbasedn, result);
}
}
}
else
{
if (debug)
printf ("Skipping zone base dn creation for %s\n", argzone);
}
for (tmp = ldap_info_base; tmp != NULL; tmp = tmp->next)
{
if (debug)
printf ("Adding DN: %s\n", tmp->dn);
add_ldap_values (tmp);
}
if (debug)
printf("Operation Complete.\n");
/* Cleanup */
isc_mem_destroy(&mctx);
if (zonefile)
free(zonefile);
return 0;
}
/* Check the status of an isc_result_t after any isc routines.
* I should probably rename this function, as not to cause any
* confusion with the isc* routines. Will exit on error. */
void
isc_result_check (isc_result_t res, char *errorstr)
{
if (res != ISC_R_SUCCESS)
{
fprintf (stderr, " %s: %s\n", errorstr, isc_result_totext (res));
exit (-1);
}
}
/* Takes DNS information, in bind data structure format, and adds textual
* zone information to the LDAP run queue. */
void
generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata, unsigned int ttl)
{
char name[DNS_NAME_MAXTEXT + 1];
unsigned int len;
char type[20];
char data[2048];
char **dc_list;
char *dn;
isc_buffer_t buff;
isc_result_t result;
isc_buffer_init (&buff, name, sizeof (name));
result = dns_name_totext (dnsname, true, &buff);
isc_result_check (result, "dns_name_totext");
name[isc_buffer_usedlength (&buff)] = 0;
isc_buffer_init (&buff, type, sizeof (type));
result = dns_rdatatype_totext (rdata->type, &buff);
isc_result_check (result, "dns_rdatatype_totext");
type[isc_buffer_usedlength (&buff)] = 0;
isc_buffer_init (&buff, data, sizeof (data));
result = dns_rdata_totext (rdata, NULL, &buff);
isc_result_check (result, "dns_rdata_totext");
data[isc_buffer_usedlength (&buff)] = 0;
dc_list = hostname_to_dn_list (name, argzone, DNS_OBJECT);
len = (get_attr_list_size (dc_list) - 2);
dn = build_dn_from_dc_list (dc_list, ttl, WI_SPEC);
if (debug)
printf ("Adding %s (%s %s) to run queue list.\n", dn, type, data);
add_to_rr_list (dn, dc_list[len], type, data, ttl, DNS_OBJECT);
}
/* Locate an item in the Run queue linked list, by DN. Used by functions
* which add items to the run queue.
*/
ldap_info *
locate_by_dn (char *dn)
{
ldap_info *tmp;
for (tmp = ldap_info_base; tmp != (ldap_info *) NULL; tmp = tmp->next)
{
if (!strncmp (tmp->dn, dn, strlen (dn)))
return tmp;
}
return (ldap_info *) NULL;
}
/* Take textual zone data, and add to the LDAP Run queue. This works like so:
* If locate_by_dn does not return, alloc a new ldap_info structure, and then
* calloc a LDAPMod array, fill in the default "everyone needs this" information,
* including object classes and dc's. If it locate_by_dn does return, then we'll
* realloc for more LDAPMod structs, and appened the new data. If an LDAPMod exists
* for the parameter we're adding, then we'll realloc the mod_values array, and
* add the new value to the existing LDAPMod. Finnaly, it assures linkage exists
* within the Run queue linked ilst*/
void
add_to_rr_list (char *dn, char *name, char *type,
char *data, unsigned int ttl, unsigned int flags)
{
int i;
int x;
ldap_info *tmp;
int attrlist;
char ldap_type_buffer[128];
char charttl[64];
if ((tmp = locate_by_dn (dn)) == NULL)
{
/* There wasn't one already there, so we need to allocate a new one,
* and stick it on the list */
tmp = (ldap_info *) malloc (sizeof (ldap_info));
if (tmp == (ldap_info *) NULL)
fatal("malloc");
tmp->dn = strdup (dn);
if (tmp->dn == NULL)
fatal("strdup");
tmp->attrs = (LDAPMod **) calloc (sizeof (LDAPMod *), flags);
if (tmp->attrs == (LDAPMod **) NULL)
fatal("calloc");
for (i = 0; i < flags; i++)
{
tmp->attrs[i] = (LDAPMod *) malloc (sizeof (LDAPMod));
if (tmp->attrs[i] == (LDAPMod *) NULL)
fatal("malloc");
}
tmp->attrs[0]->mod_op = LDAP_MOD_ADD;
tmp->attrs[0]->mod_type = "objectClass";
if (flags == DNS_OBJECT)
tmp->attrs[0]->mod_values = objectClasses;
else
{
tmp->attrs[0]->mod_values = topObjectClasses;
tmp->attrs[1] = NULL;
tmp->attrcnt = 2;
tmp->next = ldap_info_base;
ldap_info_base = tmp;
return;
}
tmp->attrs[1]->mod_op = LDAP_MOD_ADD;
tmp->attrs[1]->mod_type = "relativeDomainName";
tmp->attrs[1]->mod_values = (char **) calloc (sizeof (char *), 2);
if (tmp->attrs[1]->mod_values == (char **)NULL)
fatal("calloc");
tmp->attrs[1]->mod_values[0] = strdup (name);
tmp->attrs[1]->mod_values[2] = NULL;
if (tmp->attrs[1]->mod_values[0] == NULL)
fatal("strdup");
sprintf (ldap_type_buffer, "%sRecord", type);
tmp->attrs[2]->mod_op = LDAP_MOD_ADD;
tmp->attrs[2]->mod_type = strdup (ldap_type_buffer);
tmp->attrs[2]->mod_values = (char **) calloc (sizeof (char *), 2);
if (tmp->attrs[2]->mod_type == NULL ||
tmp->attrs[2]->mod_values == (char **)NULL)
fatal("strdup/calloc");
tmp->attrs[2]->mod_values[0] = strdup (data);
tmp->attrs[2]->mod_values[1] = NULL;
if (tmp->attrs[2]->mod_values[0] == NULL)
fatal("strdup");
tmp->attrs[3]->mod_op = LDAP_MOD_ADD;
tmp->attrs[3]->mod_type = "dNSTTL";
tmp->attrs[3]->mod_values = (char **) calloc (sizeof (char *), 2);
if (tmp->attrs[3]->mod_values == (char **)NULL)
fatal("calloc");
sprintf (charttl, "%d", ttl);
tmp->attrs[3]->mod_values[0] = strdup (charttl);
tmp->attrs[3]->mod_values[1] = NULL;
if (tmp->attrs[3]->mod_values[0] == NULL)
fatal("strdup");
tmp->attrs[4]->mod_op = LDAP_MOD_ADD;
tmp->attrs[4]->mod_type = "zoneName";
tmp->attrs[4]->mod_values = (char **)calloc(sizeof(char *), 2);
if (tmp->attrs[4]->mod_values == (char **)NULL)
fatal("calloc");
tmp->attrs[4]->mod_values[0] = gbl_zone;
tmp->attrs[4]->mod_values[1] = NULL;
tmp->attrs[5] = NULL;
tmp->attrcnt = flags;
tmp->next = ldap_info_base;
ldap_info_base = tmp;
}
else
{
for (i = 0; tmp->attrs[i] != NULL; i++)
{
sprintf (ldap_type_buffer, "%sRecord", type);
if (!strncmp
(ldap_type_buffer, tmp->attrs[i]->mod_type,
strlen (tmp->attrs[i]->mod_type)))
{
attrlist = get_attr_list_size (tmp->attrs[i]->mod_values);
tmp->attrs[i]->mod_values =
(char **) realloc (tmp->attrs[i]->mod_values,
sizeof (char *) * (attrlist + 1));
if (tmp->attrs[i]->mod_values == (char **) NULL)
fatal("realloc");
for (x = 0; tmp->attrs[i]->mod_values[x] != NULL; x++);
tmp->attrs[i]->mod_values[x] = strdup (data);
if (tmp->attrs[i]->mod_values[x] == NULL)
fatal("strdup");
tmp->attrs[i]->mod_values[x + 1] = NULL;
return;
}
}
tmp->attrs =
(LDAPMod **) realloc (tmp->attrs,
sizeof (LDAPMod) * ++(tmp->attrcnt));
if (tmp->attrs == NULL)
fatal("realloc");
for (x = 0; tmp->attrs[x] != NULL; x++);
tmp->attrs[x] = (LDAPMod *) malloc (sizeof (LDAPMod));
if (tmp->attrs[x] == NULL)
fatal("malloc");
tmp->attrs[x]->mod_op = LDAP_MOD_ADD;
tmp->attrs[x]->mod_type = strdup (ldap_type_buffer);
tmp->attrs[x]->mod_values = (char **) calloc (sizeof (char *), 2);
if (tmp->attrs[x]->mod_type == NULL ||
tmp->attrs[x]->mod_values == (char **)NULL)
fatal("strdup/calloc");
tmp->attrs[x]->mod_values[0] = strdup (data);
if (tmp->attrs[x]->mod_values[0] == NULL)
fatal("strdup");
tmp->attrs[x]->mod_values[1] = NULL;
tmp->attrs[x + 1] = NULL;
}
}
/* Size of a mod_values list, plus the terminating NULL field. */
int
get_attr_list_size (char **tmp)
{
int i = 0;
char **ftmp = tmp;
while (*ftmp != NULL)
{
i++;
ftmp++;
}
return ++i;
}
/* take a hostname, and split it into a char ** of the dc parts,
* example, we have www.domain.com, this function will return:
* array[0] = com, array[1] = domain, array[2] = www. */
char **
hostname_to_dn_list (char *hostname, char *zone, unsigned int flags)
{
char *tmp;
static char *dn_buffer[64];
int i = 0;
char *zname;
char *hnamebuff;
zname = strdup (hostname);
if (zname == NULL)
fatal("strdup");
if (flags == DNS_OBJECT)
{
if (strlen (zname) != strlen (zone))
{
tmp = &zname[strlen (zname) - strlen (zone)];
*--tmp = '\0';
hnamebuff = strdup (zname);
if (hnamebuff == NULL)
fatal("strdup");
zname = ++tmp;
}
else
hnamebuff = "@";
}
else
{
zname = zone;
hnamebuff = NULL;
}
for (tmp = strrchr (zname, '.'); tmp != (char *) 0;
tmp = strrchr (zname, '.'))
{
*tmp++ = '\0';
dn_buffer[i++] = tmp;
}
dn_buffer[i++] = zname;
dn_buffer[i++] = hnamebuff;
dn_buffer[i] = NULL;
return dn_buffer;
}
/* build an sdb compatible LDAP DN from a "dc_list" (char **).
* will append dNSTTL information to each RR Record, with the
* exception of "@"/SOA. */
char *
build_dn_from_dc_list (char **dc_list, unsigned int ttl, int flag)
{
int size;
int x;
static char dn[1024];
char tmp[128];
bzero (tmp, sizeof (tmp));
bzero (dn, sizeof (dn));
size = get_attr_list_size (dc_list);
for (x = size - 2; x > 0; x--)
{
if (flag == WI_SPEC)
{
if (x == (size - 2) && (strncmp (dc_list[x], "@", 1) == 0) && (ttl))
sprintf (tmp, "relativeDomainName=%s + dNSTTL=%d,", dc_list[x], ttl);
else if (x == (size - 2))
sprintf(tmp, "relativeDomainName=%s,",dc_list[x]);
else
sprintf(tmp,"dc=%s,", dc_list[x]);
}
else
{
sprintf(tmp, "dc=%s,", dc_list[x]);
}
strlcat (dn, tmp, sizeof (dn));
}
sprintf (tmp, "dc=%s", dc_list[0]);
strlcat (dn, tmp, sizeof (dn));
fflush(NULL);
return dn;
}
/* Initialize LDAP Conn */
void
init_ldap_conn ()
{
int result;
conn = ldap_open (ldapsystem, LDAP_PORT);
if (conn == NULL)
{
fprintf (stderr, "Error opening Ldap connection: %s\n",
strerror (errno));
exit (-1);
}
result = ldap_simple_bind_s (conn, binddn, bindpw);
ldap_result_check ("ldap_simple_bind_s", "LDAP Bind", result);
}
/* Like isc_result_check, only for LDAP */
void
ldap_result_check (char *msg, char *dn, int err)
{
if ((err != LDAP_SUCCESS) && (err != LDAP_ALREADY_EXISTS))
{
fprintf(stderr, "Error while adding %s (%s):\n",
dn, msg);
ldap_perror (conn, dn);
ldap_unbind_s (conn);
exit (-1);
}
}
/* For running the ldap_info run queue. */
void
add_ldap_values (ldap_info * ldinfo)
{
int result;
char dnbuffer[1024];
if (ldapbase != NULL)
sprintf (dnbuffer, "%s,%s", ldinfo->dn, ldapbase);
else
sprintf (dnbuffer, "%s", ldinfo->dn);
result = ldap_add_s (conn, dnbuffer, ldinfo->attrs);
ldap_result_check ("ldap_add_s", dnbuffer, result);
}
/* name says it all */
void
usage ()
{
fprintf (stderr,
"zone2ldap -D [BIND DN] -w [BIND PASSWORD] -b [BASE DN] -z [ZONE] -f [ZONE FILE] -h [LDAP HOST] "
"[-c Create LDAP Base structure][-d Debug Output (lots !)] \n ");}

View File

@ -1,353 +0,0 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pgsql/libpq-fe.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/result.h>
#include <isc/util.h>
#include <dns/sdb.h>
#include <dns/result.h>
#include <named/globals.h>
#include "pgsqldb.h"
/*
* A simple database driver that interfaces to a PostgreSQL database. This
* is not complete, and not designed for general use. It opens one
* connection to the database per zone, which is inefficient. It also may
* not handle quoting correctly.
*
* The table must contain the fields "name", "rdtype", and "rdata", and
* is expected to contain a properly constructed zone. The program "zonetodb"
* creates such a table.
*/
static dns_sdbimplementation_t *pgsqldb = NULL;
struct dbinfo {
PGconn *conn;
char *database;
char *table;
char *host;
char *user;
char *passwd;
};
static void
pgsqldb_destroy(const char *zone, void *driverdata, void **dbdata);
/*
* Canonicalize a string before writing it to the database.
* "dest" must be an array of at least size 2*strlen(source) + 1.
*/
static void
quotestring(const char *source, char *dest) {
while (*source != 0) {
if (*source == '\'')
*dest++ = '\'';
/* SQL doesn't treat \ as special, but PostgreSQL does */
else if (*source == '\\')
*dest++ = '\\';
*dest++ = *source++;
}
*dest++ = 0;
}
/*
* Connect to the database.
*/
static isc_result_t
db_connect(struct dbinfo *dbi) {
dbi->conn = PQsetdbLogin(dbi->host, NULL, NULL, NULL, dbi->database,
dbi->user, dbi->passwd);
if (PQstatus(dbi->conn) == CONNECTION_OK)
return (ISC_R_SUCCESS);
else
return (ISC_R_FAILURE);
}
/*
* Check to see if the connection is still valid. If not, attempt to
* reconnect.
*/
static isc_result_t
maybe_reconnect(struct dbinfo *dbi) {
if (PQstatus(dbi->conn) == CONNECTION_OK)
return (ISC_R_SUCCESS);
return (db_connect(dbi));
}
/*
* This database operates on absolute names.
*
* Queries are converted into SQL queries and issued synchronously. Errors
* are handled really badly.
*/
#ifdef DNS_CLIENTINFO_VERSION
static isc_result_t
pgsqldb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo)
#else
static isc_result_t
pgsqldb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup)
#endif /* DNS_CLIENTINFO_VERSION */
{
isc_result_t result;
struct dbinfo *dbi = dbdata;
PGresult *res;
char str[1500];
char *canonname;
int i;
UNUSED(zone);
#ifdef DNS_CLIENTINFO_VERSION
UNUSED(methods);
UNUSED(clientinfo);
#endif /* DNS_CLIENTINFO_VERSION */
canonname = isc_mem_get(ns_g_mctx, strlen(name) * 2 + 1);
if (canonname == NULL)
return (ISC_R_NOMEMORY);
quotestring(name, canonname);
snprintf(str, sizeof(str),
"SELECT TTL,RDTYPE,RDATA FROM \"%s\" WHERE "
"lower(NAME) = lower('%s')", dbi->table, canonname);
isc_mem_put(ns_g_mctx, canonname, strlen(name) * 2 + 1);
result = maybe_reconnect(dbi);
if (result != ISC_R_SUCCESS)
return (result);
res = PQexec(dbi->conn, str);
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) {
PQclear(res);
return (ISC_R_FAILURE);
}
if (PQntuples(res) == 0) {
PQclear(res);
return (ISC_R_NOTFOUND);
}
for (i = 0; i < PQntuples(res); i++) {
char *ttlstr = PQgetvalue(res, i, 0);
char *type = PQgetvalue(res, i, 1);
char *data = PQgetvalue(res, i, 2);
dns_ttl_t ttl;
char *endp;
ttl = strtol(ttlstr, &endp, 10);
if (*endp != '\0') {
PQclear(res);
return (DNS_R_BADTTL);
}
result = dns_sdb_putrr(lookup, type, ttl, data);
if (result != ISC_R_SUCCESS) {
PQclear(res);
return (ISC_R_FAILURE);
}
}
PQclear(res);
return (ISC_R_SUCCESS);
}
/*
* Issue an SQL query to return all nodes in the database and fill the
* allnodes structure.
*/
static isc_result_t
pgsqldb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *allnodes) {
struct dbinfo *dbi = dbdata;
PGresult *res;
isc_result_t result;
char str[1500];
int i;
UNUSED(zone);
snprintf(str, sizeof(str),
"SELECT TTL,NAME,RDTYPE,RDATA FROM \"%s\" ORDER BY NAME",
dbi->table);
result = maybe_reconnect(dbi);
if (result != ISC_R_SUCCESS)
return (result);
res = PQexec(dbi->conn, str);
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ) {
PQclear(res);
return (ISC_R_FAILURE);
}
if (PQntuples(res) == 0) {
PQclear(res);
return (ISC_R_NOTFOUND);
}
for (i = 0; i < PQntuples(res); i++) {
char *ttlstr = PQgetvalue(res, i, 0);
char *name = PQgetvalue(res, i, 1);
char *type = PQgetvalue(res, i, 2);
char *data = PQgetvalue(res, i, 3);
dns_ttl_t ttl;
char *endp;
ttl = strtol(ttlstr, &endp, 10);
if (*endp != '\0') {
PQclear(res);
return (DNS_R_BADTTL);
}
result = dns_sdb_putnamedrr(allnodes, name, type, ttl, data);
if (result != ISC_R_SUCCESS) {
PQclear(res);
return (ISC_R_FAILURE);
}
}
PQclear(res);
return (ISC_R_SUCCESS);
}
/*
* Create a connection to the database and save any necessary information
* in dbdata.
*
* argv[0] is the name of the database
* argv[1] is the name of the table
* argv[2] (if present) is the name of the host to connect to
* argv[3] (if present) is the name of the user to connect as
* argv[4] (if present) is the name of the password to connect with
*/
static isc_result_t
pgsqldb_create(const char *zone, int argc, char **argv,
void *driverdata, void **dbdata)
{
struct dbinfo *dbi;
isc_result_t result;
UNUSED(zone);
UNUSED(driverdata);
if (argc < 2)
return (ISC_R_FAILURE);
dbi = isc_mem_get(ns_g_mctx, sizeof(struct dbinfo));
if (dbi == NULL)
return (ISC_R_NOMEMORY);
dbi->conn = NULL;
dbi->database = NULL;
dbi->table = NULL;
dbi->host = NULL;
dbi->user = NULL;
dbi->passwd = NULL;
#define STRDUP_OR_FAIL(target, source) \
do { \
target = isc_mem_strdup(ns_g_mctx, source); \
if (target == NULL) { \
result = ISC_R_NOMEMORY; \
goto cleanup; \
} \
} while (0);
STRDUP_OR_FAIL(dbi->database, argv[0]);
STRDUP_OR_FAIL(dbi->table, argv[1]);
if (argc > 2)
STRDUP_OR_FAIL(dbi->host, argv[2]);
if (argc > 3)
STRDUP_OR_FAIL(dbi->user, argv[3]);
if (argc > 4)
STRDUP_OR_FAIL(dbi->passwd, argv[4]);
result = db_connect(dbi);
if (result != ISC_R_SUCCESS)
goto cleanup;
*dbdata = dbi;
return (ISC_R_SUCCESS);
cleanup:
pgsqldb_destroy(zone, driverdata, (void **)&dbi);
return (result);
}
/*
* Close the connection to the database.
*/
static void
pgsqldb_destroy(const char *zone, void *driverdata, void **dbdata) {
struct dbinfo *dbi = *dbdata;
UNUSED(zone);
UNUSED(driverdata);
if (dbi->conn != NULL)
PQfinish(dbi->conn);
if (dbi->database != NULL)
isc_mem_free(ns_g_mctx, dbi->database);
if (dbi->table != NULL)
isc_mem_free(ns_g_mctx, dbi->table);
if (dbi->host != NULL)
isc_mem_free(ns_g_mctx, dbi->host);
if (dbi->user != NULL)
isc_mem_free(ns_g_mctx, dbi->user);
if (dbi->passwd != NULL)
isc_mem_free(ns_g_mctx, dbi->passwd);
if (dbi->database != NULL)
isc_mem_free(ns_g_mctx, dbi->database);
isc_mem_put(ns_g_mctx, dbi, sizeof(struct dbinfo));
}
/*
* Since the SQL database corresponds to a zone, the authority data should
* be returned by the lookup() function. Therefore the authority() function
* is NULL.
*/
static dns_sdbmethods_t pgsqldb_methods = {
pgsqldb_lookup,
NULL, /* authority */
pgsqldb_allnodes,
pgsqldb_create,
pgsqldb_destroy,
NULL /* lookup2 */
};
/*
* Wrapper around dns_sdb_register().
*/
isc_result_t
pgsqldb_init(void) {
unsigned int flags;
flags = 0;
return (dns_sdb_register("pgsql", &pgsqldb_methods, NULL, flags,
ns_g_mctx, &pgsqldb));
}
/*
* Wrapper around dns_sdb_unregister().
*/
void
pgsqldb_clear(void) {
if (pgsqldb != NULL)
dns_sdb_unregister(&pgsqldb);
}

View File

@ -1,18 +0,0 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <isc/types.h>
isc_result_t pgsqldb_init(void);
void pgsqldb_clear(void);

View File

@ -1,273 +0,0 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <stdlib.h>
#include <string.h>
#include <isc/buffer.h>
#include <isc/hash.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/result.h>
#include <dns/db.h>
#include <dns/dbiterator.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
#include <dns/rdatatype.h>
#include <dns/result.h>
#include <pgsql/libpq-fe.h>
/*
* Generate a PostgreSQL table from a zone.
*
* This is compiled this with something like the following (assuming bind9 has
* been installed):
*
* gcc -g `isc-config.sh --cflags isc dns` -c zonetodb.c
* gcc -g -o zonetodb zonetodb.o `isc-config.sh --libs isc dns` -lpq
*/
PGconn *conn = NULL;
char *dbname, *dbtable;
char str[10240];
void
closeandexit(int status) {
if (conn != NULL)
PQfinish(conn);
exit(status);
}
void
check_result(isc_result_t result, const char *message) {
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "%s: %s\n", message,
isc_result_totext(result));
closeandexit(1);
}
}
/*
* Canonicalize a string before writing it to the database.
* "dest" must be an array of at least size 2*strlen(source) + 1.
*/
static void
quotestring(const unsigned char *source, unsigned char *dest) {
while (*source != 0) {
if (*source == '\'')
*dest++ = '\'';
else if (*source == '\\')
*dest++ = '\\';
*dest++ = *source++;
}
*dest++ = 0;
}
void
addrdata(dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) {
unsigned char namearray[DNS_NAME_MAXTEXT + 1];
unsigned char canonnamearray[2 * DNS_NAME_MAXTEXT + 1];
unsigned char typearray[20];
unsigned char canontypearray[40];
unsigned char dataarray[2048];
unsigned char canondataarray[4096];
isc_buffer_t b;
isc_result_t result;
PGresult *res;
isc_buffer_init(&b, namearray, sizeof(namearray) - 1);
result = dns_name_totext(name, true, &b);
check_result(result, "dns_name_totext");
namearray[isc_buffer_usedlength(&b)] = 0;
quotestring((const unsigned char *)namearray, canonnamearray);
isc_buffer_init(&b, typearray, sizeof(typearray) - 1);
result = dns_rdatatype_totext(rdata->type, &b);
check_result(result, "dns_rdatatype_totext");
typearray[isc_buffer_usedlength(&b)] = 0;
quotestring((const unsigned char *)typearray, canontypearray);
isc_buffer_init(&b, dataarray, sizeof(dataarray) - 1);
result = dns_rdata_totext(rdata, NULL, &b);
check_result(result, "dns_rdata_totext");
dataarray[isc_buffer_usedlength(&b)] = 0;
quotestring((const unsigned char *)dataarray, canondataarray);
snprintf(str, sizeof(str),
"INSERT INTO %s (NAME, TTL, RDTYPE, RDATA)"
" VALUES ('%s', %d, '%s', '%s')",
dbtable, canonnamearray, ttl, canontypearray, canondataarray);
printf("%s\n", str);
res = PQexec(conn, str);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "INSERT INTO command failed: %s\n",
PQresultErrorMessage(res));
PQclear(res);
closeandexit(1);
}
PQclear(res);
}
int
main(int argc, char **argv) {
char *porigin, *zonefile;
dns_fixedname_t forigin, fname;
dns_name_t *origin, *name;
dns_db_t *db = NULL;
dns_dbiterator_t *dbiter;
dns_dbnode_t *node;
dns_rdatasetiter_t *rdsiter;
dns_rdataset_t rdataset;
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_mem_t *mctx = NULL;
isc_buffer_t b;
isc_result_t result;
PGresult *res;
if (argc != 5) {
printf("usage: %s origin file dbname dbtable\n", argv[0]);
printf("Note that dbname must be an existing database.\n");
exit(1);
}
porigin = argv[1];
zonefile = argv[2];
dbname = argv[3];
dbtable = argv[4];
dns_result_register();
mctx = NULL;
result = isc_mem_create(0, 0, &mctx);
check_result(result, "isc_mem_create");
isc_buffer_init(&b, porigin, strlen(porigin));
isc_buffer_add(&b, strlen(porigin));
origin = dns_fixedname_initname(&forigin);
result = dns_name_fromtext(origin, &b, dns_rootname, 0, NULL);
check_result(result, "dns_name_fromtext");
db = NULL;
result = dns_db_create(mctx, "rbt", origin, dns_dbtype_zone,
dns_rdataclass_in, 0, NULL, &db);
check_result(result, "dns_db_create");
result = dns_db_load(db, zonefile, dns_masterformat_text, 0);
if (result == DNS_R_SEENINCLUDE)
result = ISC_R_SUCCESS;
check_result(result, "dns_db_load");
printf("Connecting to '%s'\n", dbname);
conn = PQsetdb(NULL, NULL, NULL, NULL, dbname);
if (PQstatus(conn) == CONNECTION_BAD) {
fprintf(stderr, "Connection to database '%s' failed: %s\n",
dbname, PQerrorMessage(conn));
closeandexit(1);
}
snprintf(str, sizeof(str),
"DROP TABLE %s", dbtable);
printf("%s\n", str);
res = PQexec(conn, str);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
fprintf(stderr, "DROP TABLE command failed: %s\n",
PQresultErrorMessage(res));
PQclear(res);
snprintf(str, sizeof(str), "BEGIN");
printf("%s\n", str);
res = PQexec(conn, str);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "BEGIN command failed: %s\n",
PQresultErrorMessage(res));
PQclear(res);
closeandexit(1);
}
PQclear(res);
snprintf(str, sizeof(str),
"CREATE TABLE %s "
"(NAME TEXT, TTL INTEGER, RDTYPE TEXT, RDATA TEXT)",
dbtable);
printf("%s\n", str);
res = PQexec(conn, str);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "CREATE TABLE command failed: %s\n",
PQresultErrorMessage(res));
PQclear(res);
closeandexit(1);
}
PQclear(res);
dbiter = NULL;
result = dns_db_createiterator(db, 0, &dbiter);
check_result(result, "dns_db_createiterator()");
result = dns_dbiterator_first(dbiter);
check_result(result, "dns_dbiterator_first");
name = dns_fixedname_initname(&fname);
dns_rdataset_init(&rdataset);
dns_rdata_init(&rdata);
while (result == ISC_R_SUCCESS) {
node = NULL;
result = dns_dbiterator_current(dbiter, &node, name);
if (result == ISC_R_NOMORE)
break;
check_result(result, "dns_dbiterator_current");
rdsiter = NULL;
result = dns_db_allrdatasets(db, node, NULL, 0, &rdsiter);
check_result(result, "dns_db_allrdatasets");
result = dns_rdatasetiter_first(rdsiter);
while (result == ISC_R_SUCCESS) {
dns_rdatasetiter_current(rdsiter, &rdataset);
result = dns_rdataset_first(&rdataset);
check_result(result, "dns_rdataset_first");
while (result == ISC_R_SUCCESS) {
dns_rdataset_current(&rdataset, &rdata);
addrdata(name, rdataset.ttl, &rdata);
dns_rdata_reset(&rdata);
result = dns_rdataset_next(&rdataset);
}
dns_rdataset_disassociate(&rdataset);
result = dns_rdatasetiter_next(rdsiter);
}
dns_rdatasetiter_destroy(&rdsiter);
dns_db_detachnode(db, &node);
result = dns_dbiterator_next(dbiter);
}
snprintf(str, sizeof(str), "COMMIT TRANSACTION");
printf("%s\n", str);
res = PQexec(conn, str);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "COMMIT command failed: %s\n",
PQresultErrorMessage(res));
PQclear(res);
closeandexit(1);
}
PQclear(res);
dns_dbiterator_destroy(&dbiter);
dns_db_detach(&db);
isc_mem_destroy(&mctx);
closeandexit(0);
exit(0);
}

View File

@ -1,67 +0,0 @@
SQLite BIND SDB driver
The SQLite BIND SDB "driver" is intended as an alternative both to the
pgsqldb and dirdb drivers, for situations that would like the management
simplicity and convenience of single filesystem files, with the additional
capability of SQL databases. It is also intended as an alternative to
the standard dynamic DNS update capability in bind, which effectively
requires use of DNSSEC keys for authorization and is limited to 'nsupdate'
for updates. An sqlite database, by contrast, uses and requires only
normal filesystem permissions, and may be updated however a typical SQLite
database might be updated, e.g., via a web service with an SQLite backend.
This driver is not considered suitable for very high volume public
nameserver use, while likely useful for smaller private nameserver
applications, whether or not in a production environment. It should
generally be suitable wherever SQLite is preferable over larger database
engines, and not suitable where SQLite is not preferable.
Usage:
o Use the named_sdb process ( put ENABLE_SDB=yes in /etc/sysconfig/named )
o Edit your named.conf to contain a database zone, eg.:
zone "mydomain.net." IN {
type master;
database "sqlite /etc/named.d/mydomain.db mydomain";
# ^- DB file ^-Table
};
o Create the database zone table
The table must contain the columns "name", "rdtype", and "rdata", and
is expected to contain a properly constructed zone. The program
"zone2sqlite" creates such a table.
zone2sqlite usage:
zone2sqlite origin zonefile dbfile dbtable
where
origin : zone origin, eg "mydomain.net."
zonefile : master zone database file, eg. mydomain.net.zone
dbfile : name of SQLite database file
dbtable : name of table in database
---
# mydomain.net.zone:
$TTL 1H
@ SOA localhost. root.localhost. ( 1
3H
1H
1W
1H )
NS localhost.
host1 A 192.168.2.1
host2 A 192.168.2.2
host3 A 192.168.2.3
host4 A 192.168.2.4
host5 A 192.168.2.5
host6 A 192.168.2.6
host7 A 192.168.2.7
---
# zone2sqlite mydomain.net. mydomain.net.zone mydomain.net.db mydomain
will create/update the 'mydomain' table in database file 'mydomain.net.db'.

View File

@ -1,325 +0,0 @@
/*
* Copyright (C) 2007, 2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sqlite3.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/result.h>
#include <isc/util.h>
#include <dns/sdb.h>
#include <dns/result.h>
#include <named/globals.h>
#include "sqlitedb.h"
/*
* A simple database driver that interfaces to a SQLite database.
*
* The table must contain the fields "name", "rdtype", and "rdata", and
* is expected to contain a properly constructed zone. The program "zonetodb"
* creates such a table.
*/
static dns_sdbimplementation_t *sqlitedb = NULL;
typedef struct _dbinfo {
sqlite3 *db;
char *filename;
char *table;
} dbinfo_t;
static isc_result_t
db_connect(dbinfo_t *dbi)
{
if (sqlite3_open(dbi->filename, &dbi->db) == SQLITE_OK) {
return (ISC_R_SUCCESS);
} else {
/* a connection is returned even if the open fails */
sqlite3_close(dbi->db);
dbi->db = NULL;
return (ISC_R_FAILURE);
}
}
typedef struct _lookup_parm_t {
int i;
dns_sdblookup_t *lookup;
isc_result_t result;
} lookup_parm_t;
static int
sqlitedb_lookup_cb(void *p, int cc, char **cv, char **cn)
{
lookup_parm_t *parm = p;
dns_ttl_t ttl;
char *endp;
/* FIXME - check these(num/names); I'm assuming a mapping for now */
char *ttlstr = cv[0];
char *type = cv[1];
char *data = cv[2];
UNUSED(cc);
UNUSED(cn);
ttl = strtol(ttlstr, &endp, 10);
if (*endp) {
parm->result = DNS_R_BADTTL;
return 1;
}
parm->result = dns_sdb_putrr(parm->lookup, type, ttl, data);
if (parm->result != ISC_R_SUCCESS)
return 1;
(parm->i)++;
return 0;
}
#ifdef DNS_CLIENTINFO_VERSION
static isc_result_t
sqlitedb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo)
#else
static isc_result_t
sqlitedb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup)
#endif /* DNS_CLIENTINFO_VERSION */
/*
* synchronous absolute name lookup
*/
{
dbinfo_t *dbi = (dbinfo_t *) dbdata;
char *sql;
lookup_parm_t parm = { 0, lookup, ISC_R_SUCCESS };
char *errmsg = NULL;
int result;
UNUSED(zone);
#ifdef DNS_CLIENTINFO_VERSION
UNUSED(methods);
UNUSED(clientinfo);
#endif /* DNS_CLIENTINFO_VERSION */
sql = sqlite3_mprintf(
"SELECT TTL,RDTYPE,RDATA FROM \"%q\" WHERE "
"lower(NAME) = lower('%q')",
dbi->table, name);
result = sqlite3_exec(dbi->db, sql,
&sqlitedb_lookup_cb, &parm,
&errmsg);
sqlite3_free(sql);
if (result != SQLITE_OK)
return (ISC_R_FAILURE);
if (parm.i == 0)
return (ISC_R_NOTFOUND);
return (ISC_R_SUCCESS);
}
typedef struct _allnodes_parm_t {
int i;
dns_sdballnodes_t *allnodes;
isc_result_t result;
} allnodes_parm_t;
static int
sqlitedb_allnodes_cb(void *p, int cc, char **cv, char **cn)
{
allnodes_parm_t *parm = p;
dns_ttl_t ttl;
char *endp;
/* FIXME - check these(num/names); I'm assuming a mapping for now */
char *ttlstr = cv[0];
char *name = cv[1];
char *type = cv[2];
char *data = cv[3];
UNUSED(cc);
UNUSED(cn);
ttl = strtol(ttlstr, &endp, 10);
if (*endp) {
parm->result = DNS_R_BADTTL;
return 1;
}
parm->result = dns_sdb_putnamedrr(parm->allnodes, name, type, ttl, data);
if (parm->result != ISC_R_SUCCESS)
return 1;
(parm->i)++;
return 0;
}
static isc_result_t
sqlitedb_allnodes(const char *zone,
void *dbdata,
dns_sdballnodes_t *allnodes)
{
dbinfo_t *dbi = (dbinfo_t *) dbdata;
char *sql;
allnodes_parm_t parm = { 0, allnodes, ISC_R_SUCCESS };
char *errmsg = NULL;
int result;
UNUSED(zone);
sql = sqlite3_mprintf(
"SELECT TTL,NAME,RDTYPE,RDATA FROM \"%q\" ORDER BY NAME",
dbi->table);
result = sqlite3_exec(dbi->db, sql,
&sqlitedb_allnodes_cb, &parm,
&errmsg);
sqlite3_free(sql);
if (result != SQLITE_OK)
return (ISC_R_FAILURE);
if (parm.i == 0)
return (ISC_R_NOTFOUND);
return (ISC_R_SUCCESS);
}
static void
sqlitedb_destroy(const char *zone, void *driverdata, void **dbdata)
{
dbinfo_t *dbi = *dbdata;
UNUSED(zone);
UNUSED(driverdata);
if (dbi->db != NULL)
sqlite3_close(dbi->db);
if (dbi->table != NULL)
isc_mem_free(ns_g_mctx, dbi->table);
if (dbi->filename != NULL)
isc_mem_free(ns_g_mctx, dbi->filename);
isc_mem_put(ns_g_mctx, dbi, sizeof(dbinfo_t));
}
#define STRDUP_OR_FAIL(target, source) \
do { \
target = isc_mem_strdup(ns_g_mctx, source); \
if (target == NULL) { \
result = ISC_R_NOMEMORY; \
goto cleanup; \
} \
} while (0);
/*
* Create a connection to the database and save any necessary information
* in dbdata.
*
* argv[0] is the name of the database file
* argv[1] is the name of the table
*/
static isc_result_t
sqlitedb_create(const char *zone,
int argc, char **argv,
void *driverdata, void **dbdata)
{
dbinfo_t *dbi;
isc_result_t result;
UNUSED(zone);
UNUSED(driverdata);
if (argc < 2)
return (ISC_R_FAILURE);
dbi = isc_mem_get(ns_g_mctx, sizeof(dbinfo_t));
if (dbi == NULL)
return (ISC_R_NOMEMORY);
dbi->db = NULL;
dbi->filename = NULL;
dbi->table = NULL;
STRDUP_OR_FAIL(dbi->filename, argv[0]);
STRDUP_OR_FAIL(dbi->table, argv[1]);
result = db_connect(dbi);
if (result != ISC_R_SUCCESS)
goto cleanup;
*dbdata = dbi;
return (ISC_R_SUCCESS);
cleanup:
sqlitedb_destroy(zone, driverdata, (void **)&dbi);
return (result);
}
/*
* Since the SQL database corresponds to a zone, the authority data should
* be returned by the lookup() function. Therefore the authority() function
* is NULL.
*/
static dns_sdbmethods_t sqlitedb_methods = {
sqlitedb_lookup,
NULL, /* authority */
sqlitedb_allnodes,
sqlitedb_create,
sqlitedb_destroy,
NULL /* lookup2 */
};
/*
* Wrapper around dns_sdb_register().
*/
isc_result_t
sqlitedb_init(void)
{
unsigned int flags;
flags = 0;
return (dns_sdb_register("sqlite", &sqlitedb_methods, NULL, flags,
ns_g_mctx, &sqlitedb));
}
/*
* Wrapper around dns_sdb_unregister().
*/
void
sqlitedb_clear(void)
{
if (sqlitedb != NULL)
dns_sdb_unregister(&sqlitedb);
}

View File

@ -1,15 +0,0 @@
/*
* Copyright (C) 2000-2002, 2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <isc/types.h>
isc_result_t sqlitedb_init(void);
void sqlitedb_clear(void);

View File

@ -1,288 +0,0 @@
/*
* Copyright (C) 2007, 2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <stdlib.h>
#include <string.h>
#include <isc/buffer.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/result.h>
#include <dns/db.h>
#include <dns/dbiterator.h>
#include <dns/fixedname.h>
#include <isc/hash.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
#include <dns/rdatatype.h>
#include <dns/result.h>
#include <sqlite3.h>
#ifndef UNUSED
#define UNUSED(x) (x) = (x)
#endif
/*
* Generate an SQLite table from a zone.
*/
typedef struct _dbinfo {
sqlite3 *db;
char *filename;
char *table;
} dbinfo_t;
dbinfo_t dbi = { NULL, NULL, NULL };
static void
closeandexit(int status)
{
if (dbi.db) {
sqlite3_close(dbi.db);
dbi.db = NULL;
}
exit(status);
}
static void
check_result(isc_result_t result, const char *message)
{
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "%s: %s\n", message,
isc_result_totext(result));
closeandexit(1);
}
}
static isc_result_t
db_connect(dbinfo_t *dbi)
{
if (sqlite3_open(dbi->filename, &dbi->db) == SQLITE_OK) {
return (ISC_R_SUCCESS);
} else {
/* a connection is returned even if the open fails */
sqlite3_close(dbi->db);
dbi->db = NULL;
return (ISC_R_FAILURE);
}
}
static int
add_rdata_cb(void *parm, int cc, char **cv, char **cn)
{
UNUSED(parm);
UNUSED(cc);
UNUSED(cv);
UNUSED(cn);
return 0;
}
static void
addrdata(dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
{
unsigned char namearray[DNS_NAME_MAXTEXT + 1];
unsigned char typearray[20];
unsigned char dataarray[2048];
isc_buffer_t b;
isc_result_t result;
char *sql;
char *errmsg = NULL;
int res;
isc_buffer_init(&b, namearray, sizeof(namearray) - 1);
result = dns_name_totext(name, true, &b);
check_result(result, "dns_name_totext");
namearray[isc_buffer_usedlength(&b)] = 0;
isc_buffer_init(&b, typearray, sizeof(typearray) - 1);
result = dns_rdatatype_totext(rdata->type, &b);
check_result(result, "dns_rdatatype_totext");
typearray[isc_buffer_usedlength(&b)] = 0;
isc_buffer_init(&b, dataarray, sizeof(dataarray) - 1);
result = dns_rdata_totext(rdata, NULL, &b);
check_result(result, "dns_rdata_totext");
dataarray[isc_buffer_usedlength(&b)] = 0;
sql = sqlite3_mprintf(
"INSERT INTO %Q (NAME, TTL, RDTYPE, RDATA)"
" VALUES ('%q', %d, '%q', '%q') ",
dbi.table,
namearray, ttl, typearray, dataarray);
printf("%s\n", sql);
res = sqlite3_exec(dbi.db, sql, add_rdata_cb, NULL, &errmsg);
sqlite3_free(sql);
if (res != SQLITE_OK) {
fprintf(stderr, "INSERT failed: %s\n", errmsg);
closeandexit(1);
}
}
int
main(int argc, char *argv[])
{
char *sql;
int res;
char *errmsg = NULL;
char *porigin, *zonefile;
dns_fixedname_t forigin, fname;
dns_name_t *origin, *name;
dns_db_t *db = NULL;
dns_dbiterator_t *dbiter;
dns_dbnode_t *node;
dns_rdatasetiter_t *rdsiter;
dns_rdataset_t rdataset;
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_mem_t *mctx = NULL;
isc_buffer_t b;
isc_result_t result;
if (argc != 5) {
printf("usage: %s <zone> <zonefile> <dbfile> <dbtable>\n", argv[0]);
exit(1);
}
porigin = argv[1];
zonefile = argv[2];
dbi.filename = argv[3];
dbi.table = argv[4];
dns_result_register();
result = isc_mem_create(0, 0, &mctx);
check_result(result, "isc_mem_create");
isc_buffer_init(&b, porigin, strlen(porigin));
isc_buffer_add(&b, strlen(porigin));
origin = dns_fixedname_initname(&forigin);
result = dns_name_fromtext(origin, &b, dns_rootname, 0, NULL);
check_result(result, "dns_name_fromtext");
db = NULL;
result = dns_db_create(mctx, "rbt", origin, dns_dbtype_zone,
dns_rdataclass_in, 0, NULL, &db);
check_result(result, "dns_db_create");
result = dns_db_load(db, zonefile, dns_masterformat_text, 0);
if (result == DNS_R_SEENINCLUDE)
result = ISC_R_SUCCESS;
check_result(result, "dns_db_load");
printf("Connecting to '%s'\n", dbi.filename);
if ((result = db_connect(&dbi)) != ISC_R_SUCCESS) {
fprintf(stderr, "Connection to database '%s' failed\n",
dbi.filename);
closeandexit(1);
}
sql = sqlite3_mprintf("DROP TABLE %Q ", dbi.table);
printf("%s\n", sql);
res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg);
sqlite3_free(sql);
#if 0
if (res != SQLITE_OK) {
fprintf(stderr, "DROP TABLE %s failed: %s\n",
dbi.table, errmsg);
}
#endif
#if 0
sql = sqlite3_mprintf(sql, "BEGIN TRANSACTION");
printf("%s\n", sql);
res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg);
sqlite3_free(sql);
if (res != SQLITE_OK) {
fprintf(stderr, "BEGIN TRANSACTION failed: %s\n", errmsg);
closeandexit(1);
}
#endif
sql = sqlite3_mprintf(
"CREATE TABLE %Q "
"(NAME TEXT, TTL INTEGER, RDTYPE TEXT, RDATA TEXT) ",
dbi.table);
printf("%s\n", sql);
res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg);
sqlite3_free(sql);
if (res != SQLITE_OK) {
fprintf(stderr, "CREATE TABLE %s failed: %s\n",
dbi.table, errmsg);
closeandexit(1);
}
dbiter = NULL;
result = dns_db_createiterator(db, 0, &dbiter);
check_result(result, "dns_db_createiterator()");
result = dns_dbiterator_first(dbiter);
check_result(result, "dns_dbiterator_first");
name = dns_fixedname_initname(&fname);
dns_rdataset_init(&rdataset);
dns_rdata_init(&rdata);
while (result == ISC_R_SUCCESS) {
node = NULL;
result = dns_dbiterator_current(dbiter, &node, name);
if (result == ISC_R_NOMORE)
break;
check_result(result, "dns_dbiterator_current");
rdsiter = NULL;
result = dns_db_allrdatasets(db, node, NULL, 0, &rdsiter);
check_result(result, "dns_db_allrdatasets");
result = dns_rdatasetiter_first(rdsiter);
while (result == ISC_R_SUCCESS) {
dns_rdatasetiter_current(rdsiter, &rdataset);
result = dns_rdataset_first(&rdataset);
check_result(result, "dns_rdataset_first");
while (result == ISC_R_SUCCESS) {
dns_rdataset_current(&rdataset, &rdata);
addrdata(name, rdataset.ttl, &rdata);
dns_rdata_reset(&rdata);
result = dns_rdataset_next(&rdataset);
}
dns_rdataset_disassociate(&rdataset);
result = dns_rdatasetiter_next(rdsiter);
}
dns_rdatasetiter_destroy(&rdsiter);
dns_db_detachnode(db, &node);
result = dns_dbiterator_next(dbiter);
}
#if 0
sql = sqlite3_mprintf(sql, "COMMIT TRANSACTION ");
printf("%s\n", sql);
res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg);
sqlite3_free(sql);
if (res != SQLITE_OK) {
fprintf(stderr, "COMMIT TRANSACTION failed: %s\n", errmsg);
closeandexit(1);
}
#endif
dns_dbiterator_destroy(&dbiter);
dns_db_detach(&db);
isc_mem_destroy(&mctx);
closeandexit(0);
exit(0);
}

View File

@ -1,43 +0,0 @@
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
#
# Sample lookup procedure for tcldb
#
# This lookup procedure defines zones with identical SOA, NS, and MX
# records at the apex and a single A record that varies from zone to
# zone at the name "www".
#
# Something like this could be used by a web hosting company to serve
# a number of domains without needing to create a separate master file
# for each domain. Instead, all per-zone data (in this case, a single
# IP address) specified in the named.conf file like this:
#
# zone "a.com." { type master; database "tcl 10.0.0.42"; };
# zone "b.com." { type master; database "tcl 10.0.0.99"; };
#
# Since the tcldb driver doesn't support zone transfers, there should
# be at least two identically configured master servers. In the
# example below, they are assumed to be called ns1.isp.nil and
# ns2.isp.nil.
#
proc lookup {zone name} {
global dbargs
switch -- $name {
@ { return [list \
{SOA 86400 "ns1.isp.nil. hostmaster.isp.nil. \
1 3600 1800 1814400 3600"} \
{NS 86400 "ns1.isp.nil."} \
{NS 86400 "ns2.isp.nil."} \
{MX 86400 "10 mail.isp.nil."} ] }
www { return [list [list A 3600 $dbargs($zone)] ] }
}
return NXDOMAIN
}

View File

@ -1,238 +0,0 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*
* A simple database driver that calls a Tcl procedure to define
* the contents of the DNS namespace. The procedure is loaded
* from the file lookup.tcl; look at the comments there for
* more information.
*/
#include <config.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/result.h>
#include <isc/util.h>
#include <dns/log.h>
#include <dns/sdb.h>
#include <named/globals.h>
#include <tcl.h>
#include <tcldb.h>
#define CHECK(op) \
do { result = (op); \
if (result != ISC_R_SUCCESS) return (result); \
} while (0)
typedef struct tcldb_driver {
isc_mem_t *mctx;
Tcl_Interp *interp;
} tcldb_driver_t;
static tcldb_driver_t *the_driver = NULL;
static dns_sdbimplementation_t *tcldb = NULL;
static isc_result_t
tcldb_driver_create(isc_mem_t *mctx, tcldb_driver_t **driverp) {
int tclres;
isc_result_t result = ISC_R_SUCCESS;
tcldb_driver_t *driver = isc_mem_get(mctx, sizeof(tcldb_driver_t));
if (driver == NULL)
return (ISC_R_NOMEMORY);
driver->mctx = mctx;
driver->interp = Tcl_CreateInterp();
tclres = Tcl_EvalFile(driver->interp, (char *) "lookup.tcl");
if (tclres != TCL_OK) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
"initializing tcldb: "
"loading 'lookup.tcl' failed: %s",
driver->interp->result);
result = ISC_R_FAILURE;
goto cleanup;
}
*driverp = driver;
return (ISC_R_SUCCESS);
cleanup:
isc_mem_put(mctx, driver, sizeof(tcldb_driver_t));
return (result);
}
static void
tcldb_driver_destroy(tcldb_driver_t **driverp) {
tcldb_driver_t *driver = *driverp;
Tcl_DeleteInterp(driver->interp);
isc_mem_put(driver->mctx, driver, sizeof(tcldb_driver_t));
}
/*
* Perform a lookup, by invoking the Tcl procedure "lookup".
*/
#ifdef DNS_CLIENTINFO_VERSION
static isc_result_t
tcldb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo)
#else
static isc_result_t
tcldb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup)
#endif /* DNS_CLIENTINFO_VERSION */
{
isc_result_t result = ISC_R_SUCCESS;
int tclres;
int rrc; /* RR count */
char **rrv; /* RR vector */
int i;
char *cmdv[3];
char *cmd;
#ifdef DNS_CLIENTINFO_VERSION
UNUSED(methods);
UNUSED(clientinfo);
#endif /* DNS_CLIENTINFO_VERSION */
tcldb_driver_t *driver = (tcldb_driver_t *) dbdata;
cmdv[0] = "lookup";
cmdv[1] = zone;
cmdv[2] = name;
cmd = Tcl_Merge(3, cmdv);
tclres = Tcl_Eval(driver->interp, cmd);
Tcl_Free(cmd);
if (tclres != TCL_OK) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
"zone '%s': tcl lookup function failed: %s",
zone, driver->interp->result);
return (ISC_R_FAILURE);
}
if (strcmp(driver->interp->result, "NXDOMAIN") == 0) {
result = ISC_R_NOTFOUND;
goto fail;
}
tclres = Tcl_SplitList(driver->interp, driver->interp->result,
&rrc, &rrv);
if (tclres != TCL_OK)
goto malformed;
for (i = 0; i < rrc; i++) {
isc_result_t tmpres;
int fieldc; /* Field count */
char **fieldv; /* Field vector */
tclres = Tcl_SplitList(driver->interp, rrv[i],
&fieldc, &fieldv);
if (tclres != TCL_OK) {
tmpres = ISC_R_FAILURE;
goto failrr;
}
if (fieldc != 3)
goto malformed;
tmpres = dns_sdb_putrr(lookup, fieldv[0], atoi(fieldv[1]),
fieldv[2]);
Tcl_Free((char *) fieldv);
failrr:
if (tmpres != ISC_R_SUCCESS)
result = tmpres;
}
Tcl_Free((char *) rrv);
if (result == ISC_R_SUCCESS)
return (result);
malformed:
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
"zone '%s': "
"malformed return value from tcl lookup function: %s",
zone, driver->interp->result);
result = ISC_R_FAILURE;
fail:
return (result);
}
/*
* Set up per-zone state. In our case, the database arguments of the
* zone are collected into a Tcl list and assigned to an element of
* the global array "dbargs".
*/
static isc_result_t
tcldb_create(const char *zone, int argc, char **argv,
void *driverdata, void **dbdata)
{
tcldb_driver_t *driver = (tcldb_driver_t *) driverdata;
char *list = Tcl_Merge(argc, argv);
Tcl_SetVar2(driver->interp, (char *) "dbargs", (char *) zone, list, 0);
Tcl_Free(list);
*dbdata = driverdata;
return (ISC_R_SUCCESS);
}
/*
* This driver does not support zone transfer, so allnodes() is NULL.
*/
static dns_sdbmethods_t tcldb_methods = {
tcldb_lookup,
NULL, /* authority */
NULL, /* allnodes */
tcldb_create,
NULL, /* destroy */
NULL /* lookup2 */
};
/*
* Initialize the tcldb driver.
*/
isc_result_t
tcldb_init(void) {
isc_result_t result;
int flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA;
result = tcldb_driver_create(ns_g_mctx, &the_driver);
if (result != ISC_R_SUCCESS)
return (result);
return (dns_sdb_register("tcl", &tcldb_methods, the_driver, flags,
ns_g_mctx, &tcldb));
}
/*
* Wrapper around dns_sdb_unregister().
*/
void
tcldb_clear(void) {
if (tcldb != NULL)
dns_sdb_unregister(&tcldb);
if (the_driver != NULL)
tcldb_driver_destroy(&the_driver);
}

View File

@ -1,18 +0,0 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <isc/types.h>
isc_result_t tcldb_init(void);
void tcldb_clear(void);

View File

@ -1,148 +0,0 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*
* A simple database driver that enables the server to return the
* current time in a DNS record.
*/
#include <config.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <isc/print.h>
#include <isc/result.h>
#include <isc/util.h>
#include <dns/sdb.h>
#include <named/globals.h>
#include "timedb.h"
static dns_sdbimplementation_t *timedb = NULL;
/*
* This database operates on relative names.
*
* "time" and "@" return the time in a TXT record.
* "clock" is a CNAME to "time"
* "current" is a DNAME to "@" (try time.current.time)
*/
#ifdef DNS_CLIENTINFO_VERSION
static isc_result_t
timedb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo)
#else
static isc_result_t
timedb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup)
#endif /* DNS_CLIENTINFO_VERSION */
{
isc_result_t result;
UNUSED(zone);
UNUSED(dbdata);
#ifdef DNS_CLIENTINFO_VERSION
UNUSED(methods);
UNUSED(clientinfo);
#endif /* DNS_CLIENTINFO_VERSION */
if (strcmp(name, "@") == 0 || strcmp(name, "time") == 0) {
time_t now = time(NULL);
char buf[100];
int n;
/*
* Call ctime to create the string, put it in quotes, and
* remove the trailing newline.
*/
n = snprintf(buf, sizeof(buf), "\"%s", ctime(&now));
if (n < 0)
return (ISC_R_FAILURE);
buf[n - 1] = '\"';
result = dns_sdb_putrr(lookup, "txt", 1, buf);
if (result != ISC_R_SUCCESS)
return (ISC_R_FAILURE);
} else if (strcmp(name, "clock") == 0) {
result = dns_sdb_putrr(lookup, "cname", 1, "time");
if (result != ISC_R_SUCCESS)
return (ISC_R_FAILURE);
} else if (strcmp(name, "current") == 0) {
result = dns_sdb_putrr(lookup, "dname", 1, "@");
if (result != ISC_R_SUCCESS)
return (ISC_R_FAILURE);
} else
return (ISC_R_NOTFOUND);
return (ISC_R_SUCCESS);
}
/*
* lookup() does not return SOA or NS records, so authority() must be defined.
*/
static isc_result_t
timedb_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
isc_result_t result;
UNUSED(zone);
UNUSED(dbdata);
result = dns_sdb_putsoa(lookup, "localhost.", "root.localhost.", 0);
if (result != ISC_R_SUCCESS)
return (ISC_R_FAILURE);
result = dns_sdb_putrr(lookup, "ns", 86400, "ns1.localdomain.");
if (result != ISC_R_SUCCESS)
return (ISC_R_FAILURE);
result = dns_sdb_putrr(lookup, "ns", 86400, "ns2.localdomain.");
if (result != ISC_R_SUCCESS)
return (ISC_R_FAILURE);
return (ISC_R_SUCCESS);
}
/*
* This zone does not support zone transfer, so allnodes() is NULL. There
* is no database specific data, so create() and destroy() are NULL.
*/
static dns_sdbmethods_t timedb_methods = {
timedb_lookup,
timedb_authority,
NULL, /* allnodes */
NULL, /* create */
NULL, /* destroy */
NULL /* lookup2 */
};
/*
* Wrapper around dns_sdb_register().
*/
isc_result_t
timedb_init(void) {
unsigned int flags;
flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA;
return (dns_sdb_register("time", &timedb_methods, NULL, flags,
ns_g_mctx, &timedb));
}
/*
* Wrapper around dns_sdb_unregister().
*/
void
timedb_clear(void) {
if (timedb != NULL)
dns_sdb_unregister(&timedb);
}

View File

@ -1,18 +0,0 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <isc/types.h>
isc_result_t timedb_init(void);
void timedb_clear(void);

View File

@ -18,7 +18,7 @@ lib/dns The DNS library
resolver.c The "full resolver" (performs recursive lookups)
validator.c The DNSSEC validator
db.c The database interface
sdb.c The simple database interface
sdb.c The simple database interface (deprecated)
rbtdb.c The red-black tree database
lib/dns/rdata Routines for handling the various RR types
lib/dns/sec Cryptographic libraries for DNSSEC
@ -36,7 +36,6 @@ doc/arm The BIND 9 Administrator Reference Manual
doc/man Man pages
contrib Contributed and other auxiliary code
contrib/idn/mdnkit The multilingual domain name evaluation kit
contrib/sdb Sample drivers for the simple database interface
make Makefile fragments, used by configure
The library interfaces are mainly documented in the form of comments

View File

@ -1,167 +0,0 @@
Copyright (C) Internet Systems Consortium, Inc. ("ISC")
See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
Using the BIND 9 Simplified Database Interface
This document describes the care and feeding of the BIND 9 Simplified
Database Interface, which allows you to extend BIND 9 with new ways
of obtaining the data that is published as DNS zones.
The Original BIND 9 Database Interface
BIND 9 has a well-defined "back-end database interface" that makes it
possible to replace the component of the name server responsible for
the storage and retrieval of zone data, called the "database", on a
per-zone basis. The default database is an in-memory, red-black-tree
data structure commonly referred to as "rbtdb", but it is possible to
write drivers to support any number of alternative database
technologies such as in-memory hash tables, application specific
persistent on-disk databases, object databases, or relational
databases.
The original BIND 9 database interface defined in <dns/db.h> is
designed to efficiently support the full set of database functionality
needed by a name server that implements the complete DNS protocols,
including features such as zone transfers, dynamic update, and DNSSEC.
Each of these aspects of name server operations places its own set of
demands on the data store, with the result that the database API is
quite complex and contains operations that are highly specific to the
DNS. For example, data are stored in a binary format, the name space
is tree structured, and sets of data records are conceptually
associated with DNSSEC signature sets. For these reasons, writing a
driver using this interface is a highly nontrivial undertaking.
The Simplified Database Interface
Many BIND users wish to provide access to various data sources through
the DNS, but are not necessarily interested in completely replacing
the in-memory "rbt" database or in supporting features like dynamic
update, DNSSEC, or even zone transfers.
Often, all you want is limited, read-only DNS access to an existing
system. For example, you may have an existing relational database
containing hostname/address mappings and wish to provide forvard and
reverse DNS lookups based on this information. Or perhaps you want to
set up a simple DNS-based load balancing system where the name server
answers queries about a single DNS name with a dynamically changing
set of A records.
BIND 9.1 introduced a new, simplified database interface, or "sdb",
which greatly simplifies the writing of drivers for these kinds of
applications.
The sdb Driver
An sdb driver is an object module, typically written in C, which is
linked into the name server and registers itself with the sdb
subsystem. It provides a set of callback functions, which also serve
to advertise its capabilities. When the name server receives DNS
queries, invokes the callback functions to obtain the data to respond
with.
Unlike the full database interface, the sdb interface represents all
domain names and resource records as ASCII text.
Writing an sdb Driver
When a driver is registered, it specifies its name, a list of callback
functions, and flags.
The flags specify whether the driver wants to use relative domain
names where possible.
The callback functions are as follows. The only one that must be
defined is lookup().
- create(zone, argc, argv, driverdata, dbdata)
Create a database object for "zone".
- destroy(zone, driverdata, dbdata)
Destroy the database object for "zone".
- lookup(zone, name, dbdata, lookup)
Return all the records at the domain name "name".
- authority(zone, dbdata, lookup)
Return the SOA and NS records at the zone apex.
- allnodes(zone, dbdata, allnodes)
Return all data in the zone, for zone transfers.
For more detail about these functions and their parameters, see
bind9/lib/dns/include/dns/sdb.h. For example drivers, see
bind9/contrib/sdb.
Rebuilding the Server
The driver module and header file must be copied to (or linked into)
the bind9/bin/named and bind9/bin/named/include directories
respectively, and must be added to the DBDRIVER_OBJS and DBDRIVER_SRCS
lines in bin/named/Makefile.in (e.g. for the timedb sample sdb driver,
add timedb.c to DBDRIVER_SRCS and timedb.@O@ to DBDRIVER_OBJS). If
the driver needs additional header files or libraries in nonstandard
places, the DBDRIVER_INCLUDES and DBDRIVER_LIBS lines should also be
updated.
Calls to dns_sdb_register() and dns_sdb_unregister() (or wrappers,
e.g. timedb_init() and timedb_clear() for the timedb sample sdb
driver) must be inserted into the server, in bind9/bin/named/main.c.
Registration should be in setup(), before the call to
named_server_create(). Unregistration should be in cleanup(),
after the call to ns_server_destroy(). A #include should be added
corresponding to the driver header file.
You should try doing this with one or more of the sample drivers
before attempting to write a driver of your own.
Configuring the Server
To make a zone use a new database driver, specify a "database" option
in its "zone" statement in named.conf. For example, if the driver
registers itself under the name "acmedb", you might say
zone "foo.com" {
database "acmedb";
};
You can pass arbitrary arguments to the create() function of the
driver by adding any number of whitespace-separated words after the
driver name:
zone "foo.com" {
database "acmedb -mode sql -connect 10.0.0.1";
};
Hints for Driver Writers
- If a driver is generating data on the fly, it probably should
not implement the allnodes() function, since a zone transfer
will not be meaningful. The allnodes() function is more relevant
with data from a database.
- The authority() function is necessary if and only if the lookup()
function will not add SOA and NS records at the zone apex. If
SOA and NS records are provided by the lookup() function,
the authority() function should be NULL.
- When a driver is registered, an opaque object can be provided. This
object is passed into the database create() and destroy() functions.
- When a database is created, an opaque object can be created that
is associated with that database. This object is passed into the
lookup(), authority(), and allnodes() functions, and is
destroyed by the destroy() function.
Future Directions
A future release may support dynamic loading of sdb drivers.

View File

@ -1413,31 +1413,6 @@
./contrib/scripts/named-bootconf.sh SH.PORTION 1999,2000,2001,2004,2006,2007,2012,2014,2016,2018,2019
./contrib/scripts/nanny.pl PERL 2000,2001,2004,2007,2012,2014,2016,2018,2019
./contrib/scripts/zone-edit.sh.in SH 2010,2012,2014,2016,2018,2019
./contrib/sdb/bdb/README X 2002,2018,2019
./contrib/sdb/bdb/bdb.c X 2002,2011,2014,2018,2019
./contrib/sdb/bdb/bdb.h X 2002,2018,2019
./contrib/sdb/bdb/zone2bdb.c X 2002,2008,2009,2018,2019
./contrib/sdb/dir/dirdb.c C 2000,2001,2004,2007,2011,2014,2016,2018,2019
./contrib/sdb/dir/dirdb.h C 2000,2001,2004,2007,2016,2018,2019
./contrib/sdb/ldap/INSTALL.ldap X 2001,2002,2004,2018,2019
./contrib/sdb/ldap/README.ldap X 2001,2002,2004,2018,2019
./contrib/sdb/ldap/README.zone2ldap X 2001,2015,2018,2019
./contrib/sdb/ldap/ldapdb.c X 2001,2002,2003,2004,2011,2014,2018,2019
./contrib/sdb/ldap/ldapdb.h X 2001,2018,2019
./contrib/sdb/ldap/zone2ldap.1 X 2001,2018,2019
./contrib/sdb/ldap/zone2ldap.c X 2001,2005,2008,2009,2011,2015,2016,2018,2019
./contrib/sdb/pgsql/pgsqldb.c C 2000,2001,2004,2007,2011,2014,2016,2018,2019
./contrib/sdb/pgsql/pgsqldb.h C 2000,2001,2004,2007,2016,2018,2019
./contrib/sdb/pgsql/zonetodb.c C 2000,2001,2002,2004,2005,2007,2008,2009,2014,2016,2018,2019
./contrib/sdb/sqlite/README.sdb_sqlite X 2007,2018,2019
./contrib/sdb/sqlite/sqlitedb.c X 2007,2011,2014,2016,2018,2019
./contrib/sdb/sqlite/sqlitedb.h X 2007,2016,2018,2019
./contrib/sdb/sqlite/zone2sqlite.c X 2007,2008,2009,2010,2013,2014,2016,2018,2019
./contrib/sdb/tcl/lookup.tcl TCL 2000,2001,2004,2007,2012,2016,2018,2019
./contrib/sdb/tcl/tcldb.c C 2000,2001,2004,2007,2011,2014,2016,2018,2019
./contrib/sdb/tcl/tcldb.h C 2000,2001,2004,2007,2016,2018,2019
./contrib/sdb/time/timedb.c C 2000,2001,2004,2007,2011,2014,2016,2018,2019
./contrib/sdb/time/timedb.h C 2000,2001,2004,2007,2016,2018,2019
./doc/arm/Bv9ARM-book.xml SGML 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019
./doc/arm/Bv9ARM.ch01.html X 2000,2001,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019
./doc/arm/Bv9ARM.ch02.html X 2000,2001,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019
@ -1584,7 +1559,6 @@
./doc/misc/redirect.zoneopt X 2018,2019
./doc/misc/rfc-compliance TXT.BRIEF 2001,2004,2015,2016,2018,2019
./doc/misc/roadmap TXT.BRIEF 2000,2001,2004,2016,2017,2018,2019
./doc/misc/sdb TXT.BRIEF 2000,2001,2004,2016,2017,2018,2019
./doc/misc/slave.zoneopt X 2018,2019
./doc/misc/sort-options.pl PERL 2007,2012,2016,2018,2019
./doc/misc/static-stub.zoneopt X 2018,2019