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
|
||||
useful accessories to BIND 9. Contrib software is not supported by ISC,
|
||||
but reported bugs will be fixed as time permits.
|
||||
This directory contains scripts, tools, and other useful accessories to
|
||||
BIND 9. Contrib software is not supported by ISC, but reported bugs will
|
||||
be fixed as time permits.
|
||||
|
||||
- scripts/
|
||||
|
||||
Assorted useful scripts, including 'nanny' which monitors
|
||||
named and restarts it in the event of a crash, 'zone-edit'
|
||||
which enables editing of a dynamic zone, and others
|
||||
which enables editing of a dynamic zone, and others.
|
||||
|
||||
- dane/
|
||||
|
||||
mkdane.sh generates TLSA records for use with DNS-based
|
||||
Authentication of Named Entities (DANE)
|
||||
Authentication of Named Entities (DANE).
|
||||
|
||||
- dnspriv/
|
||||
|
||||
Sample configuration for setting up a DNS-over-TLS server
|
||||
using BIND with Nginx as a TLS proxy
|
||||
using BIND with Nginx as a TLS proxy.
|
||||
|
||||
- kasp/
|
||||
|
||||
Scripts for converting key and signature policies from OpenDNSSEC
|
||||
KASP format to the policy.conf format used by dnssec-keymgr.
|
||||
|
||||
- dlz/modules
|
||||
|
||||
Dynamically linkable DLZ modules that can be configured into
|
||||
named at runtime, enabling access to external data sources including
|
||||
LDAP, MySQL, Berkeley DB, perl scripts, etc
|
||||
LDAP, MySQL, Berkeley DB, perl scripts, etc.
|
||||
|
||||
- dlz/drivers
|
||||
|
||||
Old-style DLZ drivers that can be linked into named at compile
|
||||
time. (These are no longer actively maintained and are expected
|
||||
to be deprecated eventually.)
|
||||
to be removed eventually.)
|
||||
|
||||
- sdb/
|
||||
|
||||
SDB drivers: another mechanism for accessing external data
|
||||
sources. (These are no longer actively maintained and are
|
||||
expected to be deprecated eventually.)
|
||||
|
||||
External tools:
|
||||
|
||||
- https://gitlab.isc.org/isc-projects/queryperf
|
||||
|
||||
A DNS query performance testing tool
|
||||
|
||||
- https://gitlab.isc.org/isc-projects/perftcpdns
|
||||
|
||||
A performance testing tool for DNS over TCP
|
||||
|
||||
- https://gitlab.isc.org/isc-projects/dnsperf
|
||||
|
||||
DNS server performance testing tools, like 'queryperf' but more
|
||||
advanced: 'dnsperf' focuses on authoritative server performance
|
||||
and 'resperf' on recursive server performance. The patch that
|
||||
adds support for EDNS Client Subnet has been applied to the
|
||||
git repository.
|
||||
|
||||
Formerly, there was more software included in this directory, but we
|
||||
have removed it in favour of using canonical upstream locations. You
|
||||
can find the links to the nslint, query-loc and zkt, and other software
|
||||
we find useful but do not necessarily support, at:
|
||||
|
||||
https://www.isc.org/community/tools/
|
||||
Some links to useful software and other resources related to BIND 9 and
|
||||
DNS can be found at https://www.isc.org/dns-tools-and-resources.
|
||||
|
@ -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)
|
||||
validator.c The DNSSEC validator
|
||||
db.c The database interface
|
||||
sdb.c The simple database interface
|
||||
sdb.c The simple database interface (deprecated)
|
||||
rbtdb.c The red-black tree database
|
||||
lib/dns/rdata Routines for handling the various RR types
|
||||
lib/dns/sec Cryptographic libraries for DNSSEC
|
||||
@ -36,7 +36,6 @@ doc/arm The BIND 9 Administrator Reference Manual
|
||||
doc/man Man pages
|
||||
contrib Contributed and other auxiliary code
|
||||
contrib/idn/mdnkit The multilingual domain name evaluation kit
|
||||
contrib/sdb Sample drivers for the simple database interface
|
||||
make Makefile fragments, used by configure
|
||||
|
||||
The library interfaces are mainly documented in the form of comments
|
||||
|
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/nanny.pl PERL 2000,2001,2004,2007,2012,2014,2016,2018,2019
|
||||
./contrib/scripts/zone-edit.sh.in SH 2010,2012,2014,2016,2018,2019
|
||||
./contrib/sdb/bdb/README X 2002,2018,2019
|
||||
./contrib/sdb/bdb/bdb.c X 2002,2011,2014,2018,2019
|
||||
./contrib/sdb/bdb/bdb.h X 2002,2018,2019
|
||||
./contrib/sdb/bdb/zone2bdb.c X 2002,2008,2009,2018,2019
|
||||
./contrib/sdb/dir/dirdb.c C 2000,2001,2004,2007,2011,2014,2016,2018,2019
|
||||
./contrib/sdb/dir/dirdb.h C 2000,2001,2004,2007,2016,2018,2019
|
||||
./contrib/sdb/ldap/INSTALL.ldap X 2001,2002,2004,2018,2019
|
||||
./contrib/sdb/ldap/README.ldap X 2001,2002,2004,2018,2019
|
||||
./contrib/sdb/ldap/README.zone2ldap X 2001,2015,2018,2019
|
||||
./contrib/sdb/ldap/ldapdb.c X 2001,2002,2003,2004,2011,2014,2018,2019
|
||||
./contrib/sdb/ldap/ldapdb.h X 2001,2018,2019
|
||||
./contrib/sdb/ldap/zone2ldap.1 X 2001,2018,2019
|
||||
./contrib/sdb/ldap/zone2ldap.c X 2001,2005,2008,2009,2011,2015,2016,2018,2019
|
||||
./contrib/sdb/pgsql/pgsqldb.c C 2000,2001,2004,2007,2011,2014,2016,2018,2019
|
||||
./contrib/sdb/pgsql/pgsqldb.h C 2000,2001,2004,2007,2016,2018,2019
|
||||
./contrib/sdb/pgsql/zonetodb.c C 2000,2001,2002,2004,2005,2007,2008,2009,2014,2016,2018,2019
|
||||
./contrib/sdb/sqlite/README.sdb_sqlite X 2007,2018,2019
|
||||
./contrib/sdb/sqlite/sqlitedb.c X 2007,2011,2014,2016,2018,2019
|
||||
./contrib/sdb/sqlite/sqlitedb.h X 2007,2016,2018,2019
|
||||
./contrib/sdb/sqlite/zone2sqlite.c X 2007,2008,2009,2010,2013,2014,2016,2018,2019
|
||||
./contrib/sdb/tcl/lookup.tcl TCL 2000,2001,2004,2007,2012,2016,2018,2019
|
||||
./contrib/sdb/tcl/tcldb.c C 2000,2001,2004,2007,2011,2014,2016,2018,2019
|
||||
./contrib/sdb/tcl/tcldb.h C 2000,2001,2004,2007,2016,2018,2019
|
||||
./contrib/sdb/time/timedb.c C 2000,2001,2004,2007,2011,2014,2016,2018,2019
|
||||
./contrib/sdb/time/timedb.h C 2000,2001,2004,2007,2016,2018,2019
|
||||
./doc/arm/Bv9ARM-book.xml SGML 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019
|
||||
./doc/arm/Bv9ARM.ch01.html X 2000,2001,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019
|
||||
./doc/arm/Bv9ARM.ch02.html X 2000,2001,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019
|
||||
@ -1584,7 +1559,6 @@
|
||||
./doc/misc/redirect.zoneopt X 2018,2019
|
||||
./doc/misc/rfc-compliance TXT.BRIEF 2001,2004,2015,2016,2018,2019
|
||||
./doc/misc/roadmap TXT.BRIEF 2000,2001,2004,2016,2017,2018,2019
|
||||
./doc/misc/sdb TXT.BRIEF 2000,2001,2004,2016,2017,2018,2019
|
||||
./doc/misc/slave.zoneopt X 2018,2019
|
||||
./doc/misc/sort-options.pl PERL 2007,2012,2016,2018,2019
|
||||
./doc/misc/static-stub.zoneopt X 2018,2019
|
||||
|
Loading…
x
Reference in New Issue
Block a user