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:
parent
d27f41cb7f
commit
c79e2f12fe
@ -1,62 +1,39 @@
|
|||||||
This directory contains contributed scripts, tools, libraries, and other
|
This directory contains scripts, tools, and other useful accessories to
|
||||||
useful accessories to BIND 9. Contrib software is not supported by ISC,
|
BIND 9. Contrib software is not supported by ISC, but reported bugs will
|
||||||
but reported bugs will be fixed as time permits.
|
be fixed as time permits.
|
||||||
|
|
||||||
- scripts/
|
- scripts/
|
||||||
|
|
||||||
Assorted useful scripts, including 'nanny' which monitors
|
Assorted useful scripts, including 'nanny' which monitors
|
||||||
named and restarts it in the event of a crash, 'zone-edit'
|
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/
|
- dane/
|
||||||
|
|
||||||
mkdane.sh generates TLSA records for use with DNS-based
|
mkdane.sh generates TLSA records for use with DNS-based
|
||||||
Authentication of Named Entities (DANE)
|
Authentication of Named Entities (DANE).
|
||||||
|
|
||||||
- dnspriv/
|
- dnspriv/
|
||||||
|
|
||||||
Sample configuration for setting up a DNS-over-TLS server
|
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
|
- dlz/modules
|
||||||
|
|
||||||
Dynamically linkable DLZ modules that can be configured into
|
Dynamically linkable DLZ modules that can be configured into
|
||||||
named at runtime, enabling access to external data sources including
|
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
|
- dlz/drivers
|
||||||
|
|
||||||
Old-style DLZ drivers that can be linked into named at compile
|
Old-style DLZ drivers that can be linked into named at compile
|
||||||
time. (These are no longer actively maintained and are expected
|
time. (These are no longer actively maintained and are expected
|
||||||
to be deprecated eventually.)
|
to be removed eventually.)
|
||||||
|
|
||||||
- sdb/
|
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.
|
||||||
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/
|
|
||||||
|
@ -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>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
@ -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 */
|
|
@ -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;
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
|
|
@ -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
|
|
@ -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
|
|
@ -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>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
#include <isc/types.h>
|
|
||||||
|
|
||||||
isc_result_t ldapdb_init(void);
|
|
||||||
|
|
||||||
void ldapdb_clear(void);
|
|
||||||
|
|
@ -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>
|
|
||||||
|
|
@ -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 ");}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
@ -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'.
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
|
|
@ -18,7 +18,7 @@ lib/dns The DNS library
|
|||||||
resolver.c The "full resolver" (performs recursive lookups)
|
resolver.c The "full resolver" (performs recursive lookups)
|
||||||
validator.c The DNSSEC validator
|
validator.c The DNSSEC validator
|
||||||
db.c The database interface
|
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
|
rbtdb.c The red-black tree database
|
||||||
lib/dns/rdata Routines for handling the various RR types
|
lib/dns/rdata Routines for handling the various RR types
|
||||||
lib/dns/sec Cryptographic libraries for DNSSEC
|
lib/dns/sec Cryptographic libraries for DNSSEC
|
||||||
@ -36,7 +36,6 @@ doc/arm The BIND 9 Administrator Reference Manual
|
|||||||
doc/man Man pages
|
doc/man Man pages
|
||||||
contrib Contributed and other auxiliary code
|
contrib Contributed and other auxiliary code
|
||||||
contrib/idn/mdnkit The multilingual domain name evaluation kit
|
contrib/idn/mdnkit The multilingual domain name evaluation kit
|
||||||
contrib/sdb Sample drivers for the simple database interface
|
|
||||||
make Makefile fragments, used by configure
|
make Makefile fragments, used by configure
|
||||||
|
|
||||||
The library interfaces are mainly documented in the form of comments
|
The library interfaces are mainly documented in the form of comments
|
||||||
|
167
doc/misc/sdb
167
doc/misc/sdb
@ -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.
|
|
||||||
|
|
@ -1413,31 +1413,6 @@
|
|||||||
./contrib/scripts/named-bootconf.sh SH.PORTION 1999,2000,2001,2004,2006,2007,2012,2014,2016,2018,2019
|
./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/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/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-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.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
|
./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/redirect.zoneopt X 2018,2019
|
||||||
./doc/misc/rfc-compliance TXT.BRIEF 2001,2004,2015,2016,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/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/slave.zoneopt X 2018,2019
|
||||||
./doc/misc/sort-options.pl PERL 2007,2012,2016,2018,2019
|
./doc/misc/sort-options.pl PERL 2007,2012,2016,2018,2019
|
||||||
./doc/misc/static-stub.zoneopt X 2018,2019
|
./doc/misc/static-stub.zoneopt X 2018,2019
|
||||||
|
Loading…
x
Reference in New Issue
Block a user