Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bf2541ce9 |
@@ -1,195 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2000, 2001 Internet Software Consortium.
|
||||
*
|
||||
* 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 INTERNET SOFTWARE CONSORTIUM
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* $Id: dirdb.c,v 1.9 2001/01/09 21:46:22 bwelling Exp $ */
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static isc_result_t
|
||||
dirdb_lookup(const char *zone, const char *name, void *dbdata,
|
||||
dns_sdblookup_t *lookup)
|
||||
{
|
||||
char filename[255];
|
||||
char filename2[255];
|
||||
char buf[1024];
|
||||
struct stat statbuf;
|
||||
isc_result_t result;
|
||||
int n;
|
||||
|
||||
UNUSED(zone);
|
||||
UNUSED(dbdata);
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
/*
|
||||
* 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,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2000, 2001 Internet Software Consortium.
|
||||
*
|
||||
* 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 INTERNET SOFTWARE CONSORTIUM
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* $Id: dirdb.h,v 1.2 2001/01/09 21:46:23 bwelling Exp $ */
|
||||
|
||||
#include <isc/types.h>
|
||||
|
||||
isc_result_t dirdb_init(void);
|
||||
|
||||
void dirdb_clear(void);
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
This is the INSTALL file for 0.4. 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 doesn't make sense,
|
||||
please have a look at that 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 it.
|
||||
|
||||
|
||||
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.
|
||||
From this release on, 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/
|
||||
|
||||
For an example, have a look at my venaas.com zone. Try a subtree search
|
||||
for objectClass=* at
|
||||
ldap ldap://129.241.20.67/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no
|
||||
|
||||
To use it with BIND, I've added the following to named.conf:
|
||||
zone "venaas.com" {
|
||||
type master;
|
||||
database "ldap ldap://129.241.20.67/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.
|
||||
|
||||
Stig Venaas <venaas@uninett.no> 2001-04-12
|
||||
@@ -1,18 +0,0 @@
|
||||
This is an attempt at an LDAP back-end for BIND 9 using the new simplified
|
||||
database interface "sdb". This is the fifth release (0.5) and is not ready
|
||||
for production use yet. Note that this version (and 0.4) uses a new schema
|
||||
and is not backwards compatible with versions before 0.4. 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> 2001-05-06
|
||||
@@ -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,466 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2001 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.
|
||||
*/
|
||||
|
||||
#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 <ldap.h>
|
||||
#include "ldapdb.h"
|
||||
|
||||
/*
|
||||
* A simple database driver for LDAP. Not production quality yet
|
||||
*/
|
||||
|
||||
static dns_sdbimplementation_t *ldapdb = NULL;
|
||||
|
||||
struct ldapdb_data {
|
||||
char *hostport;
|
||||
char *hostname;
|
||||
int portno;
|
||||
char *base;
|
||||
int defaultttl;
|
||||
};
|
||||
|
||||
/* 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;
|
||||
free(conndata->index);
|
||||
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);
|
||||
(char *)conndata->index = data->hostport;
|
||||
conndata->size = strlen(data->hostport);
|
||||
conndata->data = NULL;
|
||||
ldapdb_insert((struct ldapdb_entry **)&threaddata->data,
|
||||
conndata);
|
||||
}
|
||||
|
||||
return (LDAP **)&conndata->data;
|
||||
}
|
||||
|
||||
/* callback routines */
|
||||
static isc_result_t
|
||||
ldapdb_create(const char *zone, int argc, char **argv,
|
||||
void *driverdata, void **dbdata)
|
||||
{
|
||||
struct ldapdb_data *data;
|
||||
char *s;
|
||||
int defaultttl;
|
||||
|
||||
UNUSED(zone);
|
||||
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);
|
||||
data->hostport = isc_mem_strdup(ns_g_mctx, argv[0] + strlen("ldap://"));
|
||||
if (data->hostport == NULL) {
|
||||
isc_mem_put(ns_g_mctx, data, sizeof(struct ldapdb_data));
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
data->defaultttl = defaultttl;
|
||||
s = strchr(data->hostport, '/');
|
||||
if (s != NULL) {
|
||||
*s++ = '\0';
|
||||
data->base = *s != '\0' ? s : NULL;
|
||||
}
|
||||
|
||||
/* support URLs with literal IPv6 addresses */
|
||||
data->hostname = isc_mem_strdup(ns_g_mctx, data->hostport +
|
||||
(*data->hostport == '[' ? 1 : 0));
|
||||
if (data->hostname == NULL) {
|
||||
isc_mem_free(ns_g_mctx, data->hostport);
|
||||
isc_mem_put(ns_g_mctx, data, sizeof(struct ldapdb_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);
|
||||
|
||||
if (data->hostport != NULL)
|
||||
isc_mem_free(ns_g_mctx, data->hostport);
|
||||
if (data->hostname != NULL)
|
||||
isc_mem_free(ns_g_mctx, data->hostname);
|
||||
isc_mem_put(ns_g_mctx, data, sizeof(struct ldapdb_data));
|
||||
}
|
||||
|
||||
static void
|
||||
ldapdb_bind(struct ldapdb_data *data, LDAP **ldp)
|
||||
{
|
||||
if (*ldp != NULL)
|
||||
ldap_unbind(*ldp);
|
||||
*ldp = ldap_open(data->hostname, data->portno);
|
||||
if (*ldp == NULL)
|
||||
return;
|
||||
if (ldap_simple_bind_s(*ldp, NULL, NULL) != LDAP_SUCCESS) {
|
||||
ldap_unbind(*ldp);
|
||||
*ldp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
ldapdb_lookup(const char *zone, const char *name, void *dbdata,
|
||||
dns_sdblookup_t *lookup)
|
||||
{
|
||||
isc_result_t result = ISC_R_NOTFOUND;
|
||||
struct ldapdb_data *data = dbdata;
|
||||
LDAP **ldp;
|
||||
LDAPMessage *res, *e;
|
||||
char *fltr, *a, **vals;
|
||||
char type[64];
|
||||
BerElement *ptr;
|
||||
int i;
|
||||
|
||||
ldp = ldapdb_getconn(data);
|
||||
if (ldp == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
if (*ldp == NULL) {
|
||||
ldapdb_bind(data, ldp);
|
||||
if (*ldp == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
fltr = isc_mem_get(ns_g_mctx, strlen(zone) + strlen(name) +
|
||||
strlen("(&(zoneName=)(relativeDomainName=))") + 1);
|
||||
if (fltr == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
strcpy(fltr, "(&(zoneName=");
|
||||
strcat(fltr, zone);
|
||||
strcat(fltr, ")(relativeDomainName=");
|
||||
strcat(fltr, name);
|
||||
strcat(fltr, "))");
|
||||
|
||||
if (ldap_search_s(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0,
|
||||
&res) != LDAP_SUCCESS) {
|
||||
ldapdb_bind(data, ldp);
|
||||
if (*ldp != NULL)
|
||||
ldap_search_s(*ldp, data->base, LDAP_SCOPE_SUBTREE,
|
||||
fltr, NULL, 0, &res);
|
||||
}
|
||||
|
||||
isc_mem_put(ns_g_mctx, fltr, strlen(fltr) + 1);
|
||||
|
||||
if (*ldp == NULL)
|
||||
goto exit;
|
||||
|
||||
for (e = ldap_first_entry(*ldp, res); e != NULL;
|
||||
e = ldap_next_entry(*ldp, e)) {
|
||||
LDAP *ld = *ldp;
|
||||
int ttl = data->defaultttl;
|
||||
|
||||
for (a = ldap_first_attribute(ld, e, &ptr); a != NULL;
|
||||
a = ldap_next_attribute(ld, e, ptr)) {
|
||||
if (!strcmp(a, "dNSTTL")) {
|
||||
vals = ldap_get_values(ld, e, a);
|
||||
ttl = atoi(vals[0]);
|
||||
ldap_value_free(vals);
|
||||
ldap_memfree(a);
|
||||
break;
|
||||
}
|
||||
ldap_memfree(a);
|
||||
}
|
||||
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))) {
|
||||
ldap_memfree(a);
|
||||
continue;
|
||||
}
|
||||
strncpy(type, a, s - a);
|
||||
type[s - a] = '\0';
|
||||
vals = ldap_get_values(ld, e, a);
|
||||
for (i=0; vals[i] != NULL; i++) {
|
||||
result = dns_sdb_putrr(lookup, type, ttl,
|
||||
vals[i]);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ldap_value_free(vals);
|
||||
ldap_memfree(a);
|
||||
result = ISC_R_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
ldap_value_free(vals);
|
||||
ldap_memfree(a);
|
||||
}
|
||||
}
|
||||
exit:
|
||||
ldap_msgfree(res);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
ldapdb_allnodes(const char *zone, void *dbdata,
|
||||
dns_sdballnodes_t *allnodes) {
|
||||
isc_result_t result = ISC_R_NOTFOUND;
|
||||
struct ldapdb_data *data = dbdata;
|
||||
LDAP **ldp;
|
||||
LDAPMessage *res, *e;
|
||||
char type[64];
|
||||
char *fltr, *a, **vals;
|
||||
BerElement *ptr;
|
||||
int i;
|
||||
|
||||
ldp = ldapdb_getconn(data);
|
||||
if (ldp == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
if (*ldp == NULL) {
|
||||
ldapdb_bind(data, ldp);
|
||||
if (*ldp == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
fltr = isc_mem_get(ns_g_mctx, strlen(zone) + strlen("(zoneName=)") + 1);
|
||||
if (fltr == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
strcpy(fltr, "(zoneName=");
|
||||
strcat(fltr, zone);
|
||||
strcat(fltr, ")");
|
||||
|
||||
if (ldap_search_s(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0,
|
||||
&res) != LDAP_SUCCESS) {
|
||||
ldapdb_bind(data, ldp);
|
||||
if (*ldp != NULL)
|
||||
ldap_search_s(*ldp, data->base, LDAP_SCOPE_SUBTREE,
|
||||
fltr, NULL, 0, &res);
|
||||
}
|
||||
|
||||
isc_mem_put(ns_g_mctx, fltr, strlen(fltr) + 1);
|
||||
|
||||
for (e = ldap_first_entry(*ldp, res); e != NULL;
|
||||
e = ldap_next_entry(*ldp, e)) {
|
||||
LDAP *ld = *ldp;
|
||||
char *name = NULL;
|
||||
int ttl = data->defaultttl;
|
||||
|
||||
for (a = ldap_first_attribute(ld, e, &ptr); a != NULL;
|
||||
a = ldap_next_attribute(ld, e, ptr)) {
|
||||
if (!strcmp(a, "dNSTTL")) {
|
||||
vals = ldap_get_values(ld, e, a);
|
||||
ttl = atoi(vals[0]);
|
||||
ldap_value_free(vals);
|
||||
} else if (!strcmp(a, "relativeDomainName")) {
|
||||
vals = ldap_get_values(ld, e, a);
|
||||
name = isc_mem_strdup(ns_g_mctx, vals[0]);
|
||||
ldap_value_free(vals);
|
||||
}
|
||||
ldap_memfree(a);
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
continue;
|
||||
|
||||
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))) {
|
||||
ldap_memfree(a);
|
||||
continue;
|
||||
}
|
||||
strncpy(type, a, s - a);
|
||||
type[s - a] = '\0';
|
||||
vals = ldap_get_values(ld, e, a);
|
||||
for (i=0; vals[i] != NULL; i++) {
|
||||
result = dns_sdb_putnamedrr(allnodes, name,
|
||||
type, ttl, vals[i]);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ldap_value_free(vals);
|
||||
ldap_memfree(a);
|
||||
isc_mem_free(ns_g_mctx, name);
|
||||
result = ISC_R_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
ldap_value_free(vals);
|
||||
ldap_memfree(a);
|
||||
}
|
||||
isc_mem_free(ns_g_mctx, name);
|
||||
}
|
||||
|
||||
exit:
|
||||
ldap_msgfree(res);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static dns_sdbmethods_t ldapdb_methods = {
|
||||
ldapdb_lookup,
|
||||
NULL, /* authority */
|
||||
ldapdb_allnodes,
|
||||
ldapdb_create,
|
||||
ldapdb_destroy
|
||||
};
|
||||
|
||||
/* 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,721 +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/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/result.h>
|
||||
#include <dns/rdatatype.h>
|
||||
|
||||
#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
|
||||
|
||||
int
|
||||
main (int *argc, char **argv)
|
||||
{
|
||||
isc_mem_t *isc_ctx = 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 ((int) argc < 2)
|
||||
{
|
||||
usage ();
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
while ((topt = getopt ((int) 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);
|
||||
break;
|
||||
case 'w':
|
||||
bindpw = strdup (optarg);
|
||||
break;
|
||||
case 'b':
|
||||
ldapbase = strdup (optarg);
|
||||
break;
|
||||
case 'z':
|
||||
argzone = strdup (optarg);
|
||||
// We wipe argzone all to hell when we parse it for the DN */
|
||||
gbl_zone = strdup(argzone);
|
||||
break;
|
||||
case 'f':
|
||||
zonefile = strdup (optarg);
|
||||
break;
|
||||
case 'h':
|
||||
ldapsystem = strdup (optarg);
|
||||
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, &isc_ctx);
|
||||
isc_result_check (result, "isc_mem_create");
|
||||
|
||||
isc_buffer_init (&buff, argzone, strlen (argzone));
|
||||
isc_buffer_add (&buff, strlen (argzone));
|
||||
dns_fixedname_init (&fixedzone);
|
||||
zone = dns_fixedname_name (&fixedzone);
|
||||
result = dns_name_fromtext (zone, &buff, dns_rootname, ISC_FALSE, NULL);
|
||||
isc_result_check (result, "dns_name_fromtext");
|
||||
|
||||
result =
|
||||
dns_db_create (isc_ctx, "rbt", zone, dns_dbtype_zone, dns_rdataclass_in,
|
||||
0, NULL, &db);
|
||||
isc_result_check (result, "dns_db_create");
|
||||
|
||||
result = dns_db_load (db, zonefile);
|
||||
isc_result_check (result, "Check Zone Syntax: dns_db_load");
|
||||
|
||||
result = dns_db_createiterator (db, ISC_FALSE, &dbit);
|
||||
isc_result_check (result, "dns_db_createiterator");
|
||||
|
||||
result = dns_dbiterator_first (dbit);
|
||||
isc_result_check (result, "dns_dbiterator_first");
|
||||
|
||||
dns_fixedname_init (&fixedname);
|
||||
name = dns_fixedname_name (&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");
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned char name[DNS_NAME_MAXTEXT + 1];
|
||||
unsigned int len;
|
||||
unsigned char type[20];
|
||||
unsigned 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, ISC_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)
|
||||
{
|
||||
fprintf (stderr, "malloc: %s\n", strerror (errno));
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
tmp->dn = strdup (dn);
|
||||
tmp->attrs = (LDAPMod **) calloc (sizeof (LDAPMod *), flags);
|
||||
if (tmp->attrs == (LDAPMod **) NULL)
|
||||
{
|
||||
fprintf (stderr, "calloc: %s\n", strerror (errno));
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
for (i = 0; i < flags; i++)
|
||||
{
|
||||
tmp->attrs[i] = (LDAPMod *) malloc (sizeof (LDAPMod));
|
||||
if (tmp->attrs[i] == (LDAPMod *) NULL)
|
||||
{
|
||||
fprintf (stderr, "malloc: %s\n", strerror (errno));
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
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)
|
||||
exit(-1);
|
||||
|
||||
tmp->attrs[1]->mod_values[0] = strdup (name);
|
||||
tmp->attrs[1]->mod_values[2] = NULL;
|
||||
|
||||
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_values == (char **)NULL)
|
||||
exit(-1);
|
||||
|
||||
tmp->attrs[2]->mod_values[0] = strdup (data);
|
||||
tmp->attrs[2]->mod_values[1] = NULL;
|
||||
|
||||
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)
|
||||
exit(-1);
|
||||
|
||||
sprintf (charttl, "%d", ttl);
|
||||
tmp->attrs[3]->mod_values[0] = strdup (charttl);
|
||||
tmp->attrs[3]->mod_values[1] = NULL;
|
||||
|
||||
tmp->attrs[4]->mod_op = LDAP_MOD_ADD;
|
||||
tmp->attrs[4]->mod_type = "zoneName";
|
||||
tmp->attrs[4]->mod_values = (char **)calloc(sizeof(char *), 2);
|
||||
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)
|
||||
{
|
||||
fprintf (stderr, "realloc: %s\n", strerror (errno));
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
for (x = 0; tmp->attrs[i]->mod_values[x] != NULL; x++);
|
||||
|
||||
tmp->attrs[i]->mod_values[x] = strdup (data);
|
||||
tmp->attrs[i]->mod_values[x + 1] = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
tmp->attrs =
|
||||
(LDAPMod **) realloc (tmp->attrs,
|
||||
sizeof (LDAPMod) * ++(tmp->attrcnt));
|
||||
if (tmp->attrs == NULL)
|
||||
{
|
||||
fprintf (stderr, "realloc: %s\n", strerror (errno));
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
for (x = 0; tmp->attrs[x] != NULL; x++);
|
||||
tmp->attrs[x] = (LDAPMod *) malloc (sizeof (LDAPMod));
|
||||
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);
|
||||
tmp->attrs[x]->mod_values[0] = strdup (data);
|
||||
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 (flags == DNS_OBJECT)
|
||||
{
|
||||
|
||||
if (strlen (zname) != strlen (zone))
|
||||
{
|
||||
tmp = &zname[strlen (zname) - strlen (zone)];
|
||||
*--tmp = '\0';
|
||||
hnamebuff = strdup (zname);
|
||||
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]);
|
||||
}
|
||||
|
||||
|
||||
strncat (dn, tmp, sizeof (dn) - strlen (dn));
|
||||
}
|
||||
|
||||
sprintf (tmp, "dc=%s", dc_list[0]);
|
||||
strncat (dn, tmp, sizeof (dn) - strlen (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,348 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2000, 2001 Internet Software Consortium.
|
||||
*
|
||||
* 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 INTERNET SOFTWARE CONSORTIUM
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* $Id: pgsqldb.c,v 1.12 2001/02/28 23:42:37 bwelling Exp $ */
|
||||
|
||||
#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.
|
||||
*/
|
||||
static isc_result_t
|
||||
pgsqldb_lookup(const char *zone, const char *name, void *dbdata,
|
||||
dns_sdblookup_t *lookup)
|
||||
{
|
||||
isc_result_t result;
|
||||
struct dbinfo *dbi = dbdata;
|
||||
PGresult *res;
|
||||
char str[1500];
|
||||
char *canonname;
|
||||
int i;
|
||||
|
||||
UNUSED(zone);
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
/*
|
||||
* 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,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2000, 2001 Internet Software Consortium.
|
||||
*
|
||||
* 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 INTERNET SOFTWARE CONSORTIUM
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* $Id: pgsqldb.h,v 1.2 2001/01/09 21:46:27 bwelling Exp $ */
|
||||
|
||||
#include <isc/types.h>
|
||||
|
||||
isc_result_t pgsqldb_init(void);
|
||||
|
||||
void pgsqldb_clear(void);
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
# Copyright (C) 2000, 2001 Internet Software Consortium.
|
||||
#
|
||||
# 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 INTERNET SOFTWARE CONSORTIUM
|
||||
# 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.
|
||||
|
||||
# $Id: lookup.tcl,v 1.7 2001/01/09 21:46:24 bwelling Exp $
|
||||
|
||||
#
|
||||
# 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,232 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2000, 2001 Internet Software Consortium.
|
||||
*
|
||||
* 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 INTERNET SOFTWARE CONSORTIUM
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* $Id: tcldb.c,v 1.7 2001/01/09 21:46:28 bwelling Exp $ */
|
||||
|
||||
/*
|
||||
* 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".
|
||||
*/
|
||||
static isc_result_t
|
||||
tcldb_lookup(const char *zone, const char *name, void *dbdata,
|
||||
dns_sdblookup_t *lookup)
|
||||
{
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
int tclres;
|
||||
int rrc; /* RR count */
|
||||
char **rrv; /* RR vector */
|
||||
int i;
|
||||
char *cmdv[3];
|
||||
char *cmd;
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2000, 2001 Internet Software Consortium.
|
||||
*
|
||||
* 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 INTERNET SOFTWARE CONSORTIUM
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* $Id: tcldb.h,v 1.4 2001/01/09 21:46:29 bwelling Exp $ */
|
||||
|
||||
#include <isc/types.h>
|
||||
|
||||
isc_result_t tcldb_init(void);
|
||||
|
||||
void tcldb_clear(void);
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2000, 2001 Internet Software Consortium.
|
||||
*
|
||||
* 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 INTERNET SOFTWARE CONSORTIUM
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* $Id: timedb.c,v 1.7 2001/01/09 21:46:30 bwelling Exp $ */
|
||||
|
||||
/*
|
||||
* 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)
|
||||
*/
|
||||
static isc_result_t
|
||||
timedb_lookup(const char *zone, const char *name, void *dbdata,
|
||||
dns_sdblookup_t *lookup)
|
||||
{
|
||||
isc_result_t result;
|
||||
|
||||
UNUSED(zone);
|
||||
UNUSED(dbdata);
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2000, 2001 Internet Software Consortium.
|
||||
*
|
||||
* 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 INTERNET SOFTWARE CONSORTIUM
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* $Id: timedb.h,v 1.2 2001/01/09 21:46:31 bwelling Exp $ */
|
||||
|
||||
#include <isc/types.h>
|
||||
|
||||
isc_result_t timedb_init(void);
|
||||
|
||||
void timedb_clear(void);
|
||||
|
||||
@@ -1,430 +0,0 @@
|
||||
|
||||
|
||||
|
||||
IETF DNSOPS working group T. Hardie
|
||||
Internet draft Nominum, Inc
|
||||
Category: Work-in-progress January, 2002
|
||||
|
||||
draft-ietf-dnsop-hardie-shared-root-server-07.txt
|
||||
|
||||
|
||||
Distributing Authoritative Name Servers via Shared Unicast Addresses
|
||||
|
||||
|
||||
|
||||
Status of this memo
|
||||
|
||||
This document is an Internet-Draft and is in full conformance with
|
||||
all provisions of Section 10 of RFC 2026.
|
||||
|
||||
Internet-Drafts are working documents of the Internet Engineering
|
||||
Task Force (IETF), its areas, and its working groups. Note that
|
||||
other groups may also distribute working documents as Internet-
|
||||
Drafts.
|
||||
|
||||
Internet-Drafts are draft documents valid for a maximum of six
|
||||
months and may be updated, replaced, or obsoleted by other
|
||||
documents at any time. It is inappropriate to use Internet-Drafts
|
||||
as reference material or to cite them other than as "work in
|
||||
progress."
|
||||
|
||||
The list of current Internet-Drafts can be accessed at
|
||||
http://www.ietf.org/ietf/1id-abstracts.txt
|
||||
|
||||
To view the list Internet-Draft Shadow Directories, see
|
||||
http://www.ietf.org/shadow.html.
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Copyright (C) The Internet Society 1999. All Rights Reserved.
|
||||
|
||||
Abstract
|
||||
|
||||
This memo describes a set of practices intended to enable an
|
||||
authoritative name server operator to provide access to a single
|
||||
named server in multiple locations. The primary motivation for the
|
||||
development and deployment of these practices is to increase the
|
||||
distribution of DNS servers to previously under-served areas of the
|
||||
network topology and to reduce the latency for DNS query responses
|
||||
in those areas. This document presumes a one-to-one mapping between
|
||||
named authoritative servers and administrative entities (operators).
|
||||
This document contains no guidelines or recommendations for caching
|
||||
name servers. The shared unicast system described here is specific
|
||||
to IPv4; applicability to IPv6 is an area for further study. It
|
||||
should also be noted that the system described here is related to
|
||||
that described in [ANYCAST], but it does not require dedicated
|
||||
address space, routing changes, or the other elements of a full
|
||||
anycast infrastructure which that document describes.
|
||||
|
||||
|
||||
1. Architecture
|
||||
|
||||
1.1 Server Requirements
|
||||
|
||||
Operators of authoritative name servers may wish to refer to
|
||||
[SECONDARY] and [ROOT] for general guidance on appropriate practice
|
||||
for authoritative name servers. In addition to proper configuration
|
||||
as a standard authoritative name server, each of the hosts
|
||||
participating in a shared-unicast system should be configured with
|
||||
two network interfaces. These interfaces may be either two physical
|
||||
interfaces or one physical interface mapped to two logical
|
||||
interfaces. One of the network interfaces should use the IPv4
|
||||
shared unicast address associated with the authoritative name
|
||||
server. The other interface, referred to as the administrative
|
||||
interface below, should use a distinct IPv4 address specific to that
|
||||
host. The host should respond to DNS queries only on the
|
||||
shared-unicast interface. In order to provide the most consistent
|
||||
set of responses from the mesh of anycast hosts, it is good practice
|
||||
to limit responses on that interface to zones for which the host is
|
||||
authoritative.
|
||||
|
||||
|
||||
1.2 Zone file delivery
|
||||
|
||||
In order to minimize the risk of man-in-the-middle attacks, zone
|
||||
files should be delivered to the administrative interface of the
|
||||
servers participating in the mesh. Secure file transfer methods and
|
||||
strong authentication should be used for all transfers. If the hosts
|
||||
in the mesh make their zones available for zone transfer, the administrative
|
||||
interfaces should be used for those transfers as well, in order to avoid
|
||||
the problems with potential routing changes for TCP traffic
|
||||
noted in section 1.5 below.
|
||||
|
||||
1.3 Synchronization
|
||||
|
||||
Authoritative name servers may be loosely or tightly synchronized,
|
||||
depending on the practices set by the operating organization. As
|
||||
noted below in section 3.1.2, lack of synchronization among servers
|
||||
using the same shared unicast address could create problems for some
|
||||
users of this service. In order to minimize that risk, switch-overs
|
||||
from one data set to another data set should be coordinated as much
|
||||
as possible. The use of synchronized clocks on the participating
|
||||
hosts and set times for switch-overs provides a basic level of
|
||||
coordination. A more complete coordination process would involve:
|
||||
|
||||
a) receipt of zones at a distribution host
|
||||
b) confirmation of the integrity of zones received
|
||||
c) distribution of the zones to all of the servers in the
|
||||
mesh
|
||||
d) confirmation of the integrity of the zones at each server
|
||||
e) coordination of the switchover times for the servers in the
|
||||
mesh
|
||||
f) institution of a failure process to ensure that servers that
|
||||
did not receive correct data or could not switchover to the
|
||||
new data ceased to respond to incoming queries until the
|
||||
problem could be resolved.
|
||||
|
||||
Depending on the size of the mesh, the distribution host may also be
|
||||
a participant; for authoritative servers, it may also be the host on
|
||||
which zones are generated.
|
||||
|
||||
This document presumes that the usual DNS failover methods are the
|
||||
only ones used to ensure reachability of the data for clients. It
|
||||
does not advise that the routes be withdrawn in the case of failure;
|
||||
it advises instead the the DNS process shutdown so that servers on
|
||||
other addresses are queried. This recommendation reflects a choice
|
||||
between performance and operational complexity. While it would be
|
||||
possible to have some process withdraw the route for a specific
|
||||
server instance when it is not available, there is considerable
|
||||
operational complexity involved in ensuring that this occurs
|
||||
reliably. Given the existing DNS failover methods, the marginal
|
||||
improvement in performance will not be sufficient to justify
|
||||
the additional complexity for most uses.
|
||||
|
||||
|
||||
1.4 Server Placement
|
||||
|
||||
Though the geographic diversity of server placement helps reduce the
|
||||
effects of service disruptions due to local problems, it is
|
||||
diversity of placement in the network topology which is the driving
|
||||
force behind these distribution practices. Server placement should
|
||||
emphasize that diversity. Ideally, servers should be placed
|
||||
topologically near the points at which the operator exchanges routes
|
||||
and traffic with other networks.
|
||||
|
||||
1.5 Routing
|
||||
|
||||
The organization administering the mesh of servers sharing a unicast
|
||||
address must have an autonomous system number and speak BGP to its
|
||||
peers. To those peers, the organization announces a route to the
|
||||
network containing the shared-unicast address of the name server.
|
||||
The organization's border routers must then deliver the traffic
|
||||
destined for the name server to the nearest instantiation. Routing
|
||||
to the administrative interfaces for the servers can use the normal
|
||||
routing methods for the administering organization.
|
||||
|
||||
One potential problem with using shared unicast addresses is that
|
||||
routers forwarding traffic to them may have more than one available
|
||||
route, and those routes may, in fact, reach different instances of
|
||||
the shared unicast address. Applications like the DNS, whose
|
||||
communication typically consists of independent request-response
|
||||
messages each fitting in a single UDP packet presents no problem.
|
||||
Other applications, in which multiple packets must reach the same
|
||||
endpoint (e.g., TCP) may fail or present unworkable performance
|
||||
characteristics in some circumstances. Split-destination failures
|
||||
may occur when a router does per-packet (or round-robin) load
|
||||
sharing, a topology change occurs that changes the relative metrics
|
||||
of two paths to the same anycast destination, etc.
|
||||
|
||||
Four things mitigate the severity of this problem. The first is
|
||||
that UDP is a fairly high proportion of the query traffic to name
|
||||
servers. The second is that the aim of this proposal is to
|
||||
diversify topological placement; for most users, this means that the
|
||||
coordination of placement will ensure that new instances of a name
|
||||
server will be at a significantly different cost metric from
|
||||
existing instances. Some set of users may end up in the middle, but
|
||||
that should be relatively rare. The third is that per packet load
|
||||
sharing is only one of the possible load sharing mechanisms, and
|
||||
other mechanisms are increasing in popularity.
|
||||
|
||||
Lastly, in the case where the traffic is TCP, per packet load
|
||||
sharing is used, and equal cost routes to different instances of a
|
||||
name server are available, any DNS implementation which measures the
|
||||
performance of servers to select a preferred server will quickly
|
||||
prefer a server for which this problem does not occur. For the DNS
|
||||
failover mechanisms to reliably avoid this problem, however, those
|
||||
using shared unicast distribution mechanisms must take care that all
|
||||
of the servers for a specific zone are not participants in the same
|
||||
shared-unicast mesh. To guard even against the case where multiple
|
||||
meshes have a set of users affected by per packet load sharing along
|
||||
equal cost routes, organizations implementing these practices should
|
||||
always provide at least one authoritative server which is not a
|
||||
participant in any shared unicast mesh. Those deploying
|
||||
shared-unicast meshes should note that any specific host may become
|
||||
unreachable to a client should a server fail, a path fail, or the
|
||||
route to that host be withdrawn. These error conditions are,
|
||||
however, not specific to shared-unicast distributions, but would
|
||||
occur for standard unicast hosts.
|
||||
|
||||
Since ICMP response packets might go to a different member of the
|
||||
mesh than that sending a packet, packets sent with a shared unicast
|
||||
source address should also avoid using path MTU discovery.
|
||||
|
||||
Appendix A. contains an ASCII diagram of a example of a simple
|
||||
implementation of this system. In it, the odd numbered routers
|
||||
deliver traffic to the shared-unicast interface network and filter
|
||||
traffic from the administrative network; the even numbered routers
|
||||
deliver traffic to the administrative network and filter traffic
|
||||
from the shared-unicast network. These are depicted as separate
|
||||
routers for the ease this gives in explanation, but they could
|
||||
easily be separate interfaces on the same router. Similarly, a
|
||||
local NTP source is depicted for synchronization, but the level of
|
||||
synchronization needed would not require that source to be either
|
||||
local or a stratum one NTP server.
|
||||
|
||||
|
||||
2. Administration
|
||||
|
||||
2.1 Points of Contact
|
||||
|
||||
A single point of contact for reporting problems is crucial to the
|
||||
correct administration of this system. If an external user of the
|
||||
system needs to report a problem related to the service, there must
|
||||
be no ambiguity about whom to contact. If internal monitoring does
|
||||
not indicate a problem, the contact may, of course, need to work
|
||||
with the external user to identify which server generated the
|
||||
error.
|
||||
|
||||
|
||||
3. Security Considerations
|
||||
|
||||
As a core piece of Internet infrastructure, authoritative name
|
||||
servers are common targets of attack. The practices outlined here
|
||||
increase the risk of certain kinds of attack and reduce the risk of
|
||||
others.
|
||||
|
||||
3.1 Increased Risks
|
||||
|
||||
3.1.1 Increase in physical servers
|
||||
|
||||
The architecture outlined in this document increases the number of
|
||||
physical servers, which could increase the possibility that a
|
||||
server mis-configuration will occur which allows for a security
|
||||
breach. In general, the entity administering a mesh should ensure
|
||||
that patches and security mechanisms applied to a single member of
|
||||
the mesh are appropriate for and applied to all of the members of a
|
||||
mesh. "Genetic diversity" (code from different code bases) can be
|
||||
a useful security measure in avoiding attacks based on
|
||||
vulnerabilities in a specific code base; in order to ensure
|
||||
consistency of responses from a single named server, however, that
|
||||
diversity should be applied to different shared-unicast meshes or
|
||||
between a mesh and a related unicast authoritative server.
|
||||
|
||||
3.1.2 Data synchronization problems
|
||||
|
||||
The level of systemic synchronization described above should be
|
||||
augmented by synchronization of the data present at each of the
|
||||
servers. While the DNS itself is a loosely coupled system,
|
||||
debugging problems with data in specific zones would be far more
|
||||
difficult if two different servers sharing a single unicast address
|
||||
might return different responses to the same query. For example,
|
||||
if the data associated with www.example.com has changed and the
|
||||
administrators of the domain are testing for the changes at the
|
||||
example.com authoritative name servers, they should not need to
|
||||
check each instance of a named root server. The use of ntp to
|
||||
provide a synchronized time for switch-over eliminates some aspects
|
||||
of this problem, but mechanisms to handle failure during the
|
||||
switchover are required. In particular, a server which cannot make
|
||||
the switchover must not roll-back to a previous version; it must
|
||||
cease to respond to queries so that other servers are queried.
|
||||
|
||||
3.1.3 Distribution risks
|
||||
|
||||
If the mechanism used to distribute zone files among the servers is
|
||||
not well secured, a man-in-the-middle attack could result in the
|
||||
injection of false information. Digital signatures will alleviate
|
||||
this risk, but encrypted transport and tight access lists are a
|
||||
necessary adjunct to them. Since zone files will be distributed to
|
||||
the administrative interfaces of meshed servers, the access control
|
||||
list for distribution of the zone files should include the
|
||||
administrative interface of the server or servers, rather than
|
||||
their shared unicast addresses.
|
||||
|
||||
3.2 Decreased Risks
|
||||
|
||||
The increase in number of physical servers reduces the likelihood
|
||||
that a denial-of-service attack will take out a significant portion
|
||||
of the DNS infrastructure. The increase in servers also reduces
|
||||
the effect of machine crashes, fiber cuts, and localized disasters
|
||||
by reducing the number of users dependent on a specific machine.
|
||||
|
||||
|
||||
4. Full copyright statement
|
||||
|
||||
Copyright (C) The Internet Society 1999. All Rights Reserved.
|
||||
|
||||
This document and translations of it may be copied and furnished to
|
||||
others, and derivative works that comment on or otherwise explain
|
||||
it or assist in its implementation may be prepared, copied,
|
||||
published and distributed, in whole or in part, without restriction
|
||||
of any kind, provided that the above copyright notice and this
|
||||
paragraph are included on all such copies and derivative works.
|
||||
However, this document itself may not be modified in any way, such
|
||||
as by removing the copyright notice or references to the Internet
|
||||
Society or other Internet organizations, except as needed for the
|
||||
purpose of developing Internet standards in which case the
|
||||
procedures for copyrights defined in the Internet Standards process
|
||||
must be followed, or as required to translate it into languages
|
||||
other than English.
|
||||
|
||||
The limited permissions granted above are perpetual and will not be
|
||||
revoked by the Internet Society or its successors or assigns.
|
||||
|
||||
This document and the information contained herein is provided on
|
||||
an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET
|
||||
ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
|
||||
THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
5. Acknowledgments
|
||||
|
||||
Masataka Ohta, Bill Manning, Randy Bush, Chris Yarnell, Ray Plzak,
|
||||
Mark Andrews, Robert Elz, Geoff Houston, Bill Norton, Akira Kato,
|
||||
Suzanne Woolf, Scott Tucker, Bernard Aboba, Casey Ajalat and Gunnar
|
||||
Lindberg all provided input and commentary on this work.
|
||||
|
||||
|
||||
6. References
|
||||
|
||||
[SECONDARY] "Selection and Operation of Secondary Name Servers".
|
||||
R. Elz, R. Bush, S Bradner, M. Patton, BCP0016.
|
||||
|
||||
[ROOT] "Root Name Server Operational Requirements". R. Bush,
|
||||
D. Karrenberg, M. Kosters, R. Plzak, BCP0040.
|
||||
|
||||
[ANYCAST] "Host Anycasting Service". C. Patridge, T. Mendez, W. Milliken,
|
||||
RFC1546.
|
||||
|
||||
|
||||
7. Editor's address
|
||||
|
||||
Ted Hardie
|
||||
Nominum, Inc.
|
||||
950 Charter St.
|
||||
Redwood City, CA 94063
|
||||
Ted.Hardie@nominum.com
|
||||
Tel: 1.650.381.6226
|
||||
|
||||
|
||||
|
||||
|
||||
Appendix A.
|
||||
|
||||
|
||||
|
||||
__________________
|
||||
Peer 1-| |
|
||||
Peer 2-| |
|
||||
Peer 3-| Switch |
|
||||
Transit| | _________ _________
|
||||
etc | |--|Router1|---|----|--------------|Router2|---WAN-|
|
||||
| | --------- | | --------- |
|
||||
| | | | |
|
||||
| | | | |
|
||||
------------------ [NTP] [DNS] |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
__________________ |
|
||||
Peer 1-| | |
|
||||
Peer 2-| | |
|
||||
Peer 3-| Switch | |
|
||||
Transit| | _________ _________ |
|
||||
etc | |--|Router3|---|----|--------------|Router4|---WAN-|
|
||||
| | --------- | | --------- |
|
||||
| | | | |
|
||||
| | | | |
|
||||
------------------ [NTP] [DNS] |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
__________________ |
|
||||
Peer 1-| | |
|
||||
Peer 2-| | |
|
||||
Peer 3-| Switch | |
|
||||
Transit| | _________ _________ |
|
||||
etc | |--|Router5|---|----|--------------|Router6|---WAN-|
|
||||
| | --------- | | --------- |
|
||||
| | | | |
|
||||
| | | | |
|
||||
------------------ [NTP] [DNS] |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
__________________ |
|
||||
Peer 1-| | |
|
||||
Peer 2-| | |
|
||||
Peer 3-| Switch | |
|
||||
Transit| | _________ _________ |
|
||||
etc | |--|Router7|---|----|--------------|Router8|---WAN-|
|
||||
| | --------- | | ---------
|
||||
| | | |
|
||||
| | | |
|
||||
------------------ [NTP] [DNS]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,227 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Network Working Group R. Bush
|
||||
Request for Comments: 3152 RGnet
|
||||
BCP: 49 August 2001
|
||||
Updates: 2874, 2772, 2766, 2553, 1886
|
||||
Category: Best Current Practice
|
||||
|
||||
|
||||
Delegation of IP6.ARPA
|
||||
|
||||
Status of this Memo
|
||||
|
||||
This document specifies an Internet Best Current Practices for the
|
||||
Internet Community, and requests discussion and suggestions for
|
||||
improvements. Distribution of this memo is unlimited.
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Copyright (C) The Internet Society (2001). All Rights Reserved.
|
||||
|
||||
Abstract
|
||||
|
||||
This document discusses the need for delegation of the IP6.ARPA DNS
|
||||
zone, and specifies a plan for the technical operation thereof.
|
||||
|
||||
1. Why IP6.ARPA?
|
||||
|
||||
In the IPv6 address space, there is a need for 'reverse mapping' of
|
||||
addresses to DNS names analogous to that provided by the IN-ADDR.ARPA
|
||||
zone for IPv4.
|
||||
|
||||
The IAB recommended that the ARPA top level domain (the name is now
|
||||
considered an acronym for "Address and Routing Parameters Area") be
|
||||
used for technical infrastructure sub-domains when possible. It is
|
||||
already in use for IPv4 reverse mapping and has been established as
|
||||
the location for E.164 numbering on the Internet [RFC2916 RFC3026].
|
||||
|
||||
IETF consensus was reached that the IP6.ARPA domain be used for
|
||||
address to DNS name mapping for the IPv6 address space [RFC2874].
|
||||
|
||||
2. Obsoleted Usage
|
||||
|
||||
This document deprecates references to IP6.INT in [RFC1886] section
|
||||
2.5, [RFC2553] section 6.2.3, [RFC2766] section 4.1, [RFC2772]
|
||||
section 7.1.c, and [RFC2874] section 2.5.
|
||||
|
||||
In this context, 'deprecate' means that the old usage is not
|
||||
appropriate for new implementations, and IP6.INT will likely be
|
||||
phased out in an orderly fashion.
|
||||
|
||||
|
||||
|
||||
Bush Best Current Practice [Page 1]
|
||||
|
||||
RFC 3152 Delegation of IP6.ARPA August 2001
|
||||
|
||||
|
||||
3. IANA Considerations
|
||||
|
||||
This memo requests that the IANA delegate the IP6.ARPA domain
|
||||
following instructions to be provided by the IAB. Names within this
|
||||
zone are to be further delegated to the regional IP registries in
|
||||
accordance with the delegation of IPv6 address space to those
|
||||
registries. The names allocated should be hierarchic in accordance
|
||||
with the address space assignment.
|
||||
|
||||
4. Security Considerations
|
||||
|
||||
While DNS spoofing of address to name mapping has been exploited in
|
||||
IPv4, delegation of the IP6.ARPA zone creates no new threats to the
|
||||
security of the internet.
|
||||
|
||||
5. References
|
||||
|
||||
[RFC1886] Thomson, S. and C. Huitema, "DNS Extensions to support IP
|
||||
version 6", RFC 1886, December 1995.
|
||||
|
||||
[RFC2553] Gilligan, R., Thomson, S., Bound, J. and W. Stevens,
|
||||
"Basic Socket Interface Extensions for IPv6", RFC 2553,
|
||||
March 1999.
|
||||
|
||||
[RFC2766] Tsirtsis, G. and P. Srisuresh, "Network Address
|
||||
Translation - Protocol Translation (NAT-PT)", RFC 2766,
|
||||
February 2000.
|
||||
|
||||
[RFC2772] Rockell, R. and R. Fink, "6Bone Backbone Routing
|
||||
Guidelines", RFC 2772, February 2000.
|
||||
|
||||
[RFC2874] Crawford, M. and C. Huitema, "DNS Extensions to Support
|
||||
IPv6 Address Aggregation and Renumbering", RFC 2874, July
|
||||
2001.
|
||||
|
||||
[RFC2916] Faltstrom, P., "E.164 number and DNS", RFC 2916,
|
||||
September 2000.
|
||||
|
||||
[RFC3026] Blane, R., "Liaison to IETF/ISOC on ENUM", RFC 3026,
|
||||
January 2001.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Bush Best Current Practice [Page 2]
|
||||
|
||||
RFC 3152 Delegation of IP6.ARPA August 2001
|
||||
|
||||
|
||||
6. Author's Address
|
||||
|
||||
Randy Bush
|
||||
5147 Crystal Springs
|
||||
Bainbridge Island, WA US-98110
|
||||
|
||||
Phone: +1 206 780 0431
|
||||
EMail: randy@psg.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Bush Best Current Practice [Page 3]
|
||||
|
||||
RFC 3152 Delegation of IP6.ARPA August 2001
|
||||
|
||||
|
||||
Full Copyright Statement
|
||||
|
||||
Copyright (C) The Internet Society (2001). All Rights Reserved.
|
||||
|
||||
This document and translations of it may be copied and furnished to
|
||||
others, and derivative works that comment on or otherwise explain it
|
||||
or assist in its implementation may be prepared, copied, published
|
||||
and distributed, in whole or in part, without restriction of any
|
||||
kind, provided that the above copyright notice and this paragraph are
|
||||
included on all such copies and derivative works. However, this
|
||||
document itself may not be modified in any way, such as by removing
|
||||
the copyright notice or references to the Internet Society or other
|
||||
Internet organizations, except as needed for the purpose of
|
||||
developing Internet standards in which case the procedures for
|
||||
copyrights defined in the Internet Standards process must be
|
||||
followed, or as required to translate it into languages other than
|
||||
English.
|
||||
|
||||
The limited permissions granted above are perpetual and will not be
|
||||
revoked by the Internet Society or its successors or assigns.
|
||||
|
||||
This document and the information contained herein is provided on an
|
||||
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
|
||||
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
|
||||
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
|
||||
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
Acknowledgement
|
||||
|
||||
Funding for the RFC Editor function is currently provided by the
|
||||
Internet Society.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Bush Best Current Practice [Page 4]
|
||||
|
||||
@@ -1,339 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Network Working Group D. Conrad
|
||||
Request for Comments: 3225 Nominum, Inc.
|
||||
Category: Standards Track December 2001
|
||||
|
||||
|
||||
Indicating Resolver Support of DNSSEC
|
||||
|
||||
Status of this Memo
|
||||
|
||||
This document specifies an Internet standards track protocol for the
|
||||
Internet community, and requests discussion and suggestions for
|
||||
improvements. Please refer to the current edition of the "Internet
|
||||
Official Protocol Standards" (STD 1) for the standardization state
|
||||
and status of this protocol. Distribution of this memo is unlimited.
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Copyright (C) The Internet Society (2001). All Rights Reserved.
|
||||
|
||||
Abstract
|
||||
|
||||
In order to deploy DNSSEC (Domain Name System Security Extensions)
|
||||
operationally, DNSSEC aware servers should only perform automatic
|
||||
inclusion of DNSSEC RRs when there is an explicit indication that the
|
||||
resolver can understand those RRs. This document proposes the use of
|
||||
a bit in the EDNS0 header to provide that explicit indication and
|
||||
describes the necessary protocol changes to implement that
|
||||
notification.
|
||||
|
||||
1. Introduction
|
||||
|
||||
DNSSEC [RFC2535] has been specified to provide data integrity and
|
||||
authentication to security aware resolvers and applications through
|
||||
the use of cryptographic digital signatures. However, as DNSSEC is
|
||||
deployed, non-DNSSEC-aware clients will likely query DNSSEC-aware
|
||||
servers. In such situations, the DNSSEC-aware server (responding to
|
||||
a request for data in a signed zone) will respond with SIG, KEY,
|
||||
and/or NXT records. For reasons described in the subsequent section,
|
||||
such responses can have significant negative operational impacts for
|
||||
the DNS infrastructure.
|
||||
|
||||
This document discusses a method to avoid these negative impacts,
|
||||
namely DNSSEC-aware servers should only respond with SIG, KEY, and/or
|
||||
NXT RRs when there is an explicit indication from the resolver that
|
||||
it can understand those RRs.
|
||||
|
||||
For the purposes of this document, "DNSSEC security RRs" are
|
||||
considered RRs of type SIG, KEY, or NXT.
|
||||
|
||||
|
||||
|
||||
Conrad Standards Track [Page 1]
|
||||
|
||||
RFC 3225 Indicating Resolver Support of DNSSEC December 2001
|
||||
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in [RFC2119].
|
||||
|
||||
2. Rationale
|
||||
|
||||
Initially, as DNSSEC is deployed, the vast majority of queries will
|
||||
be from resolvers that are not DNSSEC aware and thus do not
|
||||
understand or support the DNSSEC security RRs. When a query from
|
||||
such a resolver is received for a DNSSEC signed zone, the DNSSEC
|
||||
specification indicates the nameserver must respond with the
|
||||
appropriate DNSSEC security RRs. As DNS UDP datagrams are limited to
|
||||
512 bytes [RFC1035], responses including DNSSEC security RRs have a
|
||||
high probability of resulting in a truncated response being returned
|
||||
and the resolver retrying the query using TCP.
|
||||
|
||||
TCP DNS queries result in significant overhead due to connection
|
||||
setup and teardown. Operationally, the impact of these TCP queries
|
||||
will likely be quite detrimental in terms of increased network
|
||||
traffic (typically five packets for a single query/response instead
|
||||
of two), increased latency resulting from the additional round trip
|
||||
times, increased incidences of queries failing due to timeouts, and
|
||||
significantly increased load on nameservers.
|
||||
|
||||
In addition, in preliminary and experimental deployment of DNSSEC,
|
||||
there have been reports of non-DNSSEC aware resolvers being unable to
|
||||
handle responses which contain DNSSEC security RRs, resulting in the
|
||||
resolver failing (in the worst case) or entire responses being
|
||||
ignored (in the better case).
|
||||
|
||||
Given these operational implications, explicitly notifying the
|
||||
nameserver that the client is prepared to receive (if not understand)
|
||||
DNSSEC security RRs would be prudent.
|
||||
|
||||
Client-side support of DNSSEC is assumed to be binary -- either the
|
||||
client is willing to receive all DNSSEC security RRs or it is not
|
||||
willing to accept any. As such, a single bit is sufficient to
|
||||
indicate client-side DNSSEC support. As effective use of DNSSEC
|
||||
implies the need of EDNS0 [RFC2671], bits in the "classic" (non-EDNS
|
||||
enhanced DNS header) are scarce, and there may be situations in which
|
||||
non-compliant caching or forwarding servers inappropriately copy data
|
||||
from classic headers as queries are passed on to authoritative
|
||||
servers, the use of a bit from the EDNS0 header is proposed.
|
||||
|
||||
An alternative approach would be to use the existence of an EDNS0
|
||||
header as an implicit indication of client-side support of DNSSEC.
|
||||
This approach was not chosen as there may be applications in which
|
||||
EDNS0 is supported but in which the use of DNSSEC is inappropriate.
|
||||
|
||||
|
||||
|
||||
Conrad Standards Track [Page 2]
|
||||
|
||||
RFC 3225 Indicating Resolver Support of DNSSEC December 2001
|
||||
|
||||
|
||||
3. Protocol Changes
|
||||
|
||||
The mechanism chosen for the explicit notification of the ability of
|
||||
the client to accept (if not understand) DNSSEC security RRs is using
|
||||
the most significant bit of the Z field on the EDNS0 OPT header in
|
||||
the query. This bit is referred to as the "DNSSEC OK" (DO) bit. In
|
||||
the context of the EDNS0 OPT meta-RR, the DO bit is the first bit of
|
||||
the third and fourth bytes of the "extended RCODE and flags" portion
|
||||
of the EDNS0 OPT meta-RR, structured as follows:
|
||||
|
||||
+0 (MSB) +1 (LSB)
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
0: | EXTENDED-RCODE | VERSION |
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
2: |DO| Z |
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
|
||||
Setting the DO bit to one in a query indicates to the server that the
|
||||
resolver is able to accept DNSSEC security RRs. The DO bit cleared
|
||||
(set to zero) indicates the resolver is unprepared to handle DNSSEC
|
||||
security RRs and those RRs MUST NOT be returned in the response
|
||||
(unless DNSSEC security RRs are explicitly queried for). The DO bit
|
||||
of the query MUST be copied in the response.
|
||||
|
||||
More explicitly, DNSSEC-aware nameservers MUST NOT insert SIG, KEY,
|
||||
or NXT RRs to authenticate a response as specified in [RFC2535]
|
||||
unless the DO bit was set on the request. Security records that
|
||||
match an explicit SIG, KEY, NXT, or ANY query, or are part of the
|
||||
zone data for an AXFR or IXFR query, are included whether or not the
|
||||
DO bit was set.
|
||||
|
||||
A recursive DNSSEC-aware server MUST set the DO bit on recursive
|
||||
requests, regardless of the status of the DO bit on the initiating
|
||||
resolver request. If the initiating resolver request does not have
|
||||
the DO bit set, the recursive DNSSEC-aware server MUST remove DNSSEC
|
||||
security RRs before returning the data to the client, however cached
|
||||
data MUST NOT be modified.
|
||||
|
||||
In the event a server returns a NOTIMP, FORMERR or SERVFAIL response
|
||||
to a query that has the DO bit set, the resolver SHOULD NOT expect
|
||||
DNSSEC security RRs and SHOULD retry the query without EDNS0 in
|
||||
accordance with section 5.3 of [RFC2671].
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Conrad Standards Track [Page 3]
|
||||
|
||||
RFC 3225 Indicating Resolver Support of DNSSEC December 2001
|
||||
|
||||
|
||||
Security Considerations
|
||||
|
||||
The absence of DNSSEC data in response to a query with the DO bit set
|
||||
MUST NOT be taken to mean no security information is available for
|
||||
that zone as the response may be forged or a non-forged response of
|
||||
an altered (DO bit cleared) query.
|
||||
|
||||
IANA Considerations
|
||||
|
||||
EDNS0 [RFC2671] defines 16 bits as extended flags in the OPT record,
|
||||
these bits are encoded into the TTL field of the OPT record (RFC2671
|
||||
section 4.6).
|
||||
|
||||
This document reserves one of these bits as the OK bit. It is
|
||||
requested that the left most bit be allocated. Thus the USE of the
|
||||
OPT record TTL field would look like
|
||||
|
||||
+0 (MSB) +1 (LSB)
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
0: | EXTENDED-RCODE | VERSION |
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
2: |DO| Z |
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
|
||||
Acknowledgements
|
||||
|
||||
This document is based on a rough draft by Bob Halley with input from
|
||||
Olafur Gudmundsson, Andreas Gustafsson, Brian Wellington, Randy Bush,
|
||||
Rob Austein, Steve Bellovin, and Erik Nordmark.
|
||||
|
||||
References
|
||||
|
||||
[RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
|
||||
STD 13, RFC 1034, November 1987.
|
||||
|
||||
[RFC1035] Mockapetris, P., "Domain Names - Implementation and
|
||||
Specifications", STD 13, RFC 1035, November 1987.
|
||||
|
||||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", BCP 14, RFC 2119, March 1997.
|
||||
|
||||
[RFC2535] Eastlake, D., "Domain Name System Security Extensions", RFC
|
||||
2535, March 1999.
|
||||
|
||||
[RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC
|
||||
2671, August 1999.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Conrad Standards Track [Page 4]
|
||||
|
||||
RFC 3225 Indicating Resolver Support of DNSSEC December 2001
|
||||
|
||||
|
||||
Author's Address
|
||||
|
||||
David Conrad
|
||||
Nominum Inc.
|
||||
950 Charter Street
|
||||
Redwood City, CA 94063
|
||||
USA
|
||||
|
||||
Phone: +1 650 381 6003
|
||||
EMail: david.conrad@nominum.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Conrad Standards Track [Page 5]
|
||||
|
||||
RFC 3225 Indicating Resolver Support of DNSSEC December 2001
|
||||
|
||||
|
||||
Full Copyright Statement
|
||||
|
||||
Copyright (C) The Internet Society (2001). All Rights Reserved.
|
||||
|
||||
This document and translations of it may be copied and furnished to
|
||||
others, and derivative works that comment on or otherwise explain it
|
||||
or assist in its implementation may be prepared, copied, published
|
||||
and distributed, in whole or in part, without restriction of any
|
||||
kind, provided that the above copyright notice and this paragraph are
|
||||
included on all such copies and derivative works. However, this
|
||||
document itself may not be modified in any way, such as by removing
|
||||
the copyright notice or references to the Internet Society or other
|
||||
Internet organizations, except as needed for the purpose of
|
||||
developing Internet standards in which case the procedures for
|
||||
copyrights defined in the Internet Standards process must be
|
||||
followed, or as required to translate it into languages other than
|
||||
English.
|
||||
|
||||
The limited permissions granted above are perpetual and will not be
|
||||
revoked by the Internet Society or its successors or assigns.
|
||||
|
||||
This document and the information contained herein is provided on an
|
||||
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
|
||||
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
|
||||
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
|
||||
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
Acknowledgement
|
||||
|
||||
Funding for the RFC Editor function is currently provided by the
|
||||
Internet Society.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Conrad Standards Track [Page 6]
|
||||
|
||||
@@ -1,339 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Network Working Group O. Gudmundsson
|
||||
Request for Comments: 3226 December 2001
|
||||
Updates: 2874, 2535
|
||||
Category: Standards Track
|
||||
|
||||
|
||||
DNSSEC and IPv6 A6 aware server/resolver message size requirements
|
||||
|
||||
Status of this Memo
|
||||
|
||||
This document specifies an Internet standards track protocol for the
|
||||
Internet community, and requests discussion and suggestions for
|
||||
improvements. Please refer to the current edition of the "Internet
|
||||
Official Protocol Standards" (STD 1) for the standardization state
|
||||
and status of this protocol. Distribution of this memo is unlimited.
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Copyright (C) The Internet Society (2001). All Rights Reserved.
|
||||
|
||||
Abstract
|
||||
|
||||
This document mandates support for EDNS0 (Extension Mechanisms for
|
||||
DNS) in DNS entities claiming to support either DNS Security
|
||||
Extensions or A6 records. This requirement is necessary because
|
||||
these new features increase the size of DNS messages. If EDNS0 is
|
||||
not supported fall back to TCP will happen, having a detrimental
|
||||
impact on query latency and DNS server load. This document updates
|
||||
RFC 2535 and RFC 2874, by adding new requirements.
|
||||
|
||||
1. Introduction
|
||||
|
||||
Familiarity with the DNS [RFC1034, RFC1035], DNS Security Extensions
|
||||
[RFC2535], EDNS0 [RFC2671] and A6 [RFC2874] is helpful.
|
||||
|
||||
STD 13, RFC 1035 Section 2.3.4 requires that DNS messages over UDP
|
||||
have a data payload of 512 octets or less. Most DNS software today
|
||||
will not accept larger UDP datagrams. Any answer that requires more
|
||||
than 512 octets, results in a partial and sometimes useless reply
|
||||
with the Truncation Bit set; in most cases the requester will then
|
||||
retry using TCP. Furthermore, server delivery of truncated responses
|
||||
varies widely and resolver handling of these responses also varies,
|
||||
leading to additional inefficiencies in handling truncation.
|
||||
|
||||
Compared to UDP, TCP is an expensive protocol to use for a simple
|
||||
transaction like DNS: a TCP connection requires 5 packets for setup
|
||||
and tear down, excluding data packets, thus requiring at least 3
|
||||
round trips on top of the one for the original UDP query. The DNS
|
||||
|
||||
|
||||
|
||||
Gudmundsson Standards Track [Page 1]
|
||||
|
||||
RFC 3226 DNSSEC and IPv6 A6 requirements December 2001
|
||||
|
||||
|
||||
server also needs to keep a state of the connection during this
|
||||
transaction. Many DNS servers answer thousands of queries per
|
||||
second, requiring them to use TCP will cause significant overhead and
|
||||
delays.
|
||||
|
||||
1.1. Requirements
|
||||
|
||||
The key words "MUST", "REQUIRED", "SHOULD", "RECOMMENDED", and "MAY"
|
||||
in this document are to be interpreted as described in RFC 2119.
|
||||
|
||||
2. Motivating factors
|
||||
|
||||
2.1. DNSSEC motivations
|
||||
|
||||
DNSSEC [RFC2535] secures DNS by adding a Public Key signature on each
|
||||
RR set. These signatures range in size from about 80 octets to 800
|
||||
octets, most are going to be in the range of 80 to 200 octets. The
|
||||
addition of signatures on each or most RR sets in an answer
|
||||
significantly increases the size of DNS answers from secure zones.
|
||||
|
||||
For performance reasons and to reduce load on DNS servers, it is
|
||||
important that security aware servers and resolvers get all the data
|
||||
in Answer and Authority section in one query without truncation.
|
||||
Sending Additional Data in the same query is helpful when the server
|
||||
is authoritative for the data, and this reduces round trips.
|
||||
|
||||
DNSSEC OK[OK] specifies how a client can, using EDNS0, indicate that
|
||||
it is interested in receiving DNSSEC records. The OK bit does not
|
||||
eliminate the need for large answers for DNSSEC capable clients.
|
||||
|
||||
2.1.1. Message authentication or TSIG motivation
|
||||
|
||||
TSIG [RFC2845] allows for the light weight authentication of DNS
|
||||
messages, but increases the size of the messages by at least 70
|
||||
octets. DNSSEC specifies for computationally expensive message
|
||||
authentication SIG(0) using a standard public key signature. As only
|
||||
one TSIG or SIG(0) can be attached to each DNS answer the size
|
||||
increase of message authentication is not significant, but may still
|
||||
lead to a truncation.
|
||||
|
||||
2.2. IPv6 Motivations
|
||||
|
||||
IPv6 addresses [RFC2874] are 128 bits and can be represented in the
|
||||
DNS by multiple A6 records, each consisting of a domain name and a
|
||||
bit field. The domain name refers to an address prefix that may
|
||||
require additional A6 RRs to be included in the answer. Answers
|
||||
where the queried name has multiple A6 addresses may overflow a 512-
|
||||
octet UDP packet size.
|
||||
|
||||
|
||||
|
||||
Gudmundsson Standards Track [Page 2]
|
||||
|
||||
RFC 3226 DNSSEC and IPv6 A6 requirements December 2001
|
||||
|
||||
|
||||
2.3. Root server and TLD server motivations
|
||||
|
||||
The current number of root servers is limited to 13 as that is the
|
||||
maximum number of name servers and their address records that fit in
|
||||
one 512-octet answer for a SOA record. If root servers start
|
||||
advertising A6 or KEY records then the answer for the root NS records
|
||||
will not fit in a single 512-octet DNS message, resulting in a large
|
||||
number of TCP query connections to the root servers. Even if all
|
||||
client resolver query their local name server for information, there
|
||||
are millions of these servers. Each name server must periodically
|
||||
update its information about the high level servers.
|
||||
|
||||
For redundancy, latency and load balancing reasons, large numbers of
|
||||
DNS servers are required for some zones. Since the root zone is used
|
||||
by the entire net, it is important to have as many servers as
|
||||
possible. Large TLDs (and many high-visibility SLDs) often have
|
||||
enough servers that either A6 or KEY records would cause the NS
|
||||
response to overflow the 512 byte limit. Note that these zones with
|
||||
large numbers of servers are often exactly those zones that are
|
||||
critical to network operation and that already sustain fairly high
|
||||
loads.
|
||||
|
||||
2.4. UDP vs TCP for DNS messages
|
||||
|
||||
Given all these factors, it is essential that any implementation that
|
||||
supports DNSSEC and or A6 be able to use larger DNS messages than 512
|
||||
octets.
|
||||
|
||||
The original 512 restriction was put in place to reduce the
|
||||
probability of fragmentation of DNS responses. A fragmented UDP
|
||||
message that suffers a loss of one of the fragments renders the
|
||||
answer useless and the query must be retried. A TCP connection
|
||||
requires a larger number of round trips for establishment, data
|
||||
transfer and tear down, but only the lost data segments are
|
||||
retransmitted.
|
||||
|
||||
In the early days a number of IP implementations did not handle
|
||||
fragmentation well, but all modern operating systems have overcome
|
||||
that issue thus sending fragmented messages is fine from that
|
||||
standpoint. The open issue is the effect of losses on fragmented
|
||||
messages. If connection has high loss ratio only TCP will allow
|
||||
reliable transfer of DNS data, most links have low loss ratios thus
|
||||
sending fragmented UDP packet in one round trip is better than
|
||||
establishing a TCP connection to transfer a few thousand octets.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Gudmundsson Standards Track [Page 3]
|
||||
|
||||
RFC 3226 DNSSEC and IPv6 A6 requirements December 2001
|
||||
|
||||
|
||||
2.5. EDNS0 and large UDP messages
|
||||
|
||||
EDNS0 [RFC2671] allows clients to declare the maximum size of UDP
|
||||
message they are willing to handle. Thus, if the expected answer is
|
||||
between 512 octets and the maximum size that the client can accept,
|
||||
the additional overhead of a TCP connection can be avoided.
|
||||
|
||||
3. Protocol changes:
|
||||
|
||||
This document updates RFC 2535 and RFC 2874, by adding new
|
||||
requirements.
|
||||
|
||||
All RFC 2535 compliant servers and resolvers MUST support EDNS0 and
|
||||
advertise message size of at least 1220 octets, but SHOULD advertise
|
||||
message size of 4000. This value might be too low to get full
|
||||
answers for high level servers and successor of this document may
|
||||
require a larger value.
|
||||
|
||||
All RFC 2874 compliant servers and resolver MUST support EDNS0 and
|
||||
advertise message size of at least 1024 octets, but SHOULD advertise
|
||||
message size of 2048. The IPv6 datagrams should be 1024 octets,
|
||||
unless the MTU of the path is known. (Note that this is smaller than
|
||||
the minimum IPv6 MTU to allow for some extension headers and/or
|
||||
encapsulation without exceeding the minimum MTU.)
|
||||
|
||||
All RFC 2535 and RFC 2874 compliant entities MUST be able to handle
|
||||
fragmented IPv4 and IPv6 UDP packets.
|
||||
|
||||
All hosts supporting both RFC 2535 and RFC 2874 MUST use the larger
|
||||
required value in EDNS0 advertisements.
|
||||
|
||||
4. Acknowledgments
|
||||
|
||||
Harald Alvestrand, Rob Austein, Randy Bush, David Conrad, Andreas
|
||||
Gustafsson, Jun-ichiro itojun Hagino, Bob Halley, Edward Lewis
|
||||
Michael Patton and Kazu Yamamoto were instrumental in motivating and
|
||||
shaping this document.
|
||||
|
||||
5. Security Considerations:
|
||||
|
||||
There are no additional security considerations other than those in
|
||||
RFC 2671.
|
||||
|
||||
6. IANA Considerations:
|
||||
|
||||
None
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Gudmundsson Standards Track [Page 4]
|
||||
|
||||
RFC 3226 DNSSEC and IPv6 A6 requirements December 2001
|
||||
|
||||
|
||||
7. References
|
||||
|
||||
[RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
|
||||
STD 13, RFC 1034, November 1987.
|
||||
|
||||
[RFC1035] Mockapetris, P., "Domain Names - Implementation and
|
||||
Specification", STD 13, RFC 1035, November 1987.
|
||||
|
||||
[RFC2535] Eastlake, D. "Domain Name System Security Extensions", RFC
|
||||
2535, March 1999.
|
||||
|
||||
[RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC
|
||||
2671, August 1999.
|
||||
|
||||
[RFC2845] Vixie, P., Gudmundsson, O., Eastlake, D. and B.
|
||||
Wellington, "Secret Key Transaction Authentication for DNS
|
||||
(TSIG)", RFC 2845, May 2000.
|
||||
|
||||
[RFC2874] Crawford, M. and C. Huitema, "DNS Extensions to Support
|
||||
IPv6 Address Aggregation and Renumbering", RFC 2874, July
|
||||
2000.
|
||||
|
||||
[RFC3225] Conrad, D., "Indicating Resolver Support of DNSSEC", RFC
|
||||
3225, December 2001.
|
||||
|
||||
8. Author Address
|
||||
|
||||
Olafur Gudmundsson
|
||||
3826 Legation Street, NW
|
||||
Washington, DC 20015
|
||||
USA
|
||||
|
||||
EMail: ogud@ogud.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Gudmundsson Standards Track [Page 5]
|
||||
|
||||
RFC 3226 DNSSEC and IPv6 A6 requirements December 2001
|
||||
|
||||
|
||||
9. Full Copyright Statement
|
||||
|
||||
Copyright (C) The Internet Society (2001). All Rights Reserved.
|
||||
|
||||
This document and translations of it may be copied and furnished to
|
||||
others, and derivative works that comment on or otherwise explain it
|
||||
or assist in its implementation may be prepared, copied, published
|
||||
and distributed, in whole or in part, without restriction of any
|
||||
kind, provided that the above copyright notice and this paragraph are
|
||||
included on all such copies and derivative works. However, this
|
||||
document itself may not be modified in any way, such as by removing
|
||||
the copyright notice or references to the Internet Society or other
|
||||
Internet organizations, except as needed for the purpose of
|
||||
developing Internet standards in which case the procedures for
|
||||
copyrights defined in the Internet Standards process must be
|
||||
followed, or as required to translate it into languages other than
|
||||
English.
|
||||
|
||||
The limited permissions granted above are perpetual and will not be
|
||||
revoked by the Internet Society or its successors or assigns.
|
||||
|
||||
This document and the information contained herein is provided on an
|
||||
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
|
||||
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
|
||||
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
|
||||
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
Acknowledgement
|
||||
|
||||
Funding for the RFC Editor function is currently provided by the
|
||||
Internet Society.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Gudmundsson Standards Track [Page 6]
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Makefile
|
||||
Reference in New Issue
Block a user