catz.c revision d4609e9eea19b0bbab7eb30ae76f83643e96aa75
/*
* Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
*
* 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 ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC 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.
*/
/*! \file */
#include <config.h>
#include <isc/parseint.h>
#include <dns/dbiterator.h>
#include <dns/rdatasetiter.h>
/*%
* Single member zone in a catalog
*/
struct dns_catz_entry {
};
/*%
* Catalog zone
*/
struct dns_catz_zone {
/* key in entries is 'mhash', not domain name! */
/*
* defoptions are taken from named.conf
* zoneoptions are global options from zone
*/
};
/*%
* Collection of catalog zones for a view
*/
struct dns_catz_zones {
};
void
}
void
}
{
/* TODO error handling */
}
return (ISC_R_SUCCESS);
}
{
/* This option is always taken from config, so it's always 'default' */
return (ISC_R_SUCCESS);
}
{
return (ISC_R_NOMEMORY);
if (result != ISC_R_SUCCESS)
goto cleanup;
return (ISC_R_SUCCESS);
return (result);
}
}
{
if (result != ISC_R_SUCCESS)
return (result);
if (result != ISC_R_SUCCESS)
return (result);
}
void
}
void
unsigned int refs;
if (refs == 0) {
}
}
return (ISC_TRUE);
}
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_TRUE);
}
}
return (&zone->defoptions);
}
void
}
static isc_result_t
void *data)
{
char cznamebuf[DNS_NAME_FORMATSIZE];
char znamebuf[DNS_NAME_FORMATSIZE];
isc_buffer_putuint8(&czname, 0);
isc_buffer_putuint8(&zname, 0);
if (result != ISC_R_SUCCESS) {
"catz: adding zone '%s' from catalog '%s' - %s",
return (ISC_R_SUCCESS);
}
"catz: modifying zone '%s' from catalog "
"'%s' - %s",
}
return (ISC_R_SUCCESS);
}
static isc_result_t
void *data)
{
char cznamebuf[DNS_NAME_FORMATSIZE];
char znamebuf[DNS_NAME_FORMATSIZE];
isc_buffer_putuint8(&czname, 0);
isc_buffer_putuint8(&czname, 0);
"catz: deleting zone '%s' from catalog '%s' - %s",
return (ISC_R_EXISTS);
}
/* TODO verify the new zone first! */
/* Copy zoneoptions from newzone into target. */
&target->zoneoptions);
&target->zoneoptions);
/*
* first - walk the new zone and find all nodes that are not in the
* old zone, or are in both zones and are modified
*/
/* newzonewalk always returns ISC_R_SUCCESS */
/*
* then - walk the old zone; only deleted entries should remain
* return (ISC_R_SUCCESS);
*/
/*
* oldzonewalk always returns ISC_R_EXISTS, so walk should return
* ISC_R_SUCCESS
*/
/* at this moment target->entries has to be be empty */
return (ISC_R_SUCCESS);
}
{
return (ISC_R_NOMEMORY);
if (result != ISC_R_SUCCESS)
goto cleanup_newzones;
if (result != ISC_R_SUCCESS)
goto cleanup_mutex;
if (result != ISC_R_SUCCESS)
goto cleanup_refcount;
if (result != ISC_R_SUCCESS)
goto cleanup_ht;
return (ISC_R_SUCCESS);
return (result);
}
void
/* either it's a new one or it's being reconfigured */
}
const dns_name_t *name) {
return (ISC_R_NOMEMORY);
if (result != ISC_R_SUCCESS)
goto cleanup_newzone;
if (result != ISC_R_SUCCESS)
goto cleanup_name;
if (result != ISC_R_SUCCESS)
goto cleanup_ht;
return (ISC_R_SUCCESS);
return (result);
}
{
if (result != ISC_R_SUCCESS)
goto cleanup;
if (result != ISC_R_SUCCESS) {
if (result != ISC_R_EXISTS)
goto cleanup;
}
if (result == ISC_R_EXISTS) {
}
return (result);
}
(void **) &found);
if (result != ISC_R_SUCCESS)
return (NULL);
return (found);
}
void
}
static isc_result_t
void *data)
{
return (ISC_R_EXISTS);
}
void
}
void
unsigned int refs;
if (refs == 0) {
/*
* freewalk always returns ISC_R_EXISTS, triggering
* isc_ht_walk to delete the node. If isc_ht_walk
* returns an error, it is a critical condition
*/
/* the hashtable has to be empty now */
}
}
}
static isc_result_t
void *data)
{
return (ISC_R_EXISTS);
}
void
unsigned int refs;
if (refs == 0) {
catzs);
}
}
}
typedef enum {
} catz_opt_t;
static isc_boolean_t
return (ISC_TRUE);
else
return (ISC_FALSE);
}
static catz_opt_t
return (CATZ_OPT_ZONES);
return (CATZ_OPT_MASTERS);
return (CATZ_OPT_ALLOW_QUERY);
return (CATZ_OPT_ALLOW_TRANSFER);
return (CATZ_OPT_VERSION);
else
return (CATZ_OPT_NONE);
}
static isc_result_t
{
switch (opt) {
case CATZ_OPT_ZONES:
break;
}
/*
* We only take -first- value, as mhash must be
* different
*/
if (result != ISC_R_SUCCESS)
break;
if (result == ISC_R_SUCCESS) {
/* we have a duplicate */
return (ISC_R_FAILURE);
} else {
if (result != ISC_R_SUCCESS) {
return (result);
}
}
} else {
&entry);
if (result != ISC_R_SUCCESS) {
return (result);
}
if (result != ISC_R_SUCCESS) {
return (result);
}
}
break;
default:
return (ISC_R_FAILURE);
}
return (ISC_R_SUCCESS);
}
static isc_result_t
char t[16];
return (ISC_R_FAILURE);
if (result != ISC_R_SUCCESS)
return (result);
if (result != ISC_R_SUCCESS)
goto cleanup;
if (result != ISC_R_SUCCESS)
goto cleanup;
if (result != ISC_R_NOMORE) {
goto cleanup;
}
goto cleanup;
}
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
return (result);
}
static isc_result_t
{
unsigned int rcount;
return (ISC_R_FAILURE);
(rcount * sizeof(isc_sockaddr_t)));
return (ISC_R_NOMEMORY);
(rcount * sizeof(dns_name_t *)));
return (ISC_R_NOMEMORY);
}
result == ISC_R_SUCCESS;
{
/*
* port 0 == take the default
*/
}
return (ISC_R_SUCCESS);
}
static isc_result_t
{
/*
* we're adding this entry now, in case the option is invalid we'll get
* rid of in verification phase
*/
if (result != ISC_R_SUCCESS) {
if (result != ISC_R_SUCCESS)
return (result);
entry);
if (result != ISC_R_SUCCESS) {
return (result);
}
}
switch (subopt) {
case CATZ_OPT_MASTERS:
break;
case CATZ_OPT_ALLOW_QUERY:
#if 0
#endif
case CATZ_OPT_ALLOW_TRANSFER:
default:
return (ISC_R_FAILURE);
}
return (ISC_R_FAILURE);
}
static isc_result_t
{
switch (option) {
case CATZ_OPT_MASTERS:
value));
break;
case CATZ_OPT_VERSION:
break;
case CATZ_OPT_ALLOW_QUERY:
#if 0
#endif
case CATZ_OPT_ALLOW_TRANSFER:
default:
return (ISC_R_FAILURE);
}
return (ISC_R_FAILURE);
}
static isc_result_t
{
case 1:
/* Catalog zone-wide option */
case 2:
/* Global list (eg. 'zones') */
case 3:
/* Zone option */
if (opt == CATZ_OPT_ZONES)
rdataset));
break;
default:
break;
}
return (ISC_R_FAILURE);
}
{
int order;
unsigned int nlabels;
if (nrres == dns_namereln_equal) {
if (result != ISC_R_SUCCESS)
return (result);
/*
* xxxwpk TODO do we want to save something from SOA?
*/
return (result);
return (ISC_R_SUCCESS);
} else {
return (ISC_R_UNEXPECTED);
}
} else if (nrres != dns_namereln_subdomain) {
return (ISC_R_UNEXPECTED);
}
return (result);
}
{
isc_region_t r;
if (result != ISC_R_SUCCESS)
return (result);
if (result != ISC_R_SUCCESS)
goto cleanup;
if (result != ISC_R_SUCCESS)
goto cleanup;
strlen(".db"));
if (result != ISC_R_SUCCESS)
goto cleanup;
isc_buffer_usedregion(tbuf, &r);
/* we can do that because digest string < 2*DNS_NAME */
} else {
isc_buffer_copyregion(*buffer, &r);
}
return (result);
}
isc_buffer_t **buf)
{
/* We have to generate a text buffer with regular zone config:
* zone foo.bar {
* type slave;
* masters { ip1 port1; ip2 port2; };
* }
*/
isc_uint32_t i;
/*
* The buffer will be reallocated if something won't fit,
* ISC_BUFFER_INC seems like a good start.
*/
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
/* TODO port and DSCP */
if (result != ISC_R_SUCCESS)
goto cleanup;
}
}
if (result != ISC_R_SUCCESS)
goto cleanup;
}
return (ISC_R_SUCCESS);
if (buffer)
return (result);
}
void
(void) task;
}
isc_region_t r;
if (result != ISC_R_SUCCESS)
goto cleanup;
isc_time_now(&now);
"catz: new zone version came too soon, "
"deferring update");
5 - (unsigned int)tdiff, 0);
if (result != ISC_R_SUCCESS)
goto cleanup;
} else {
}
} else {
"catz: update already queued");
}
return (result);
}
void
isc_region_t r;
char bname[DNS_NAME_FORMATSIZE];
/*
* Create a new catz in the same context as current catz
*/
if (result != ISC_R_SUCCESS) {
/* this can happen if we remove the zone in the meantime */
"catz: zone '%s' not in config",
bname);
return;
}
if (result != ISC_R_SUCCESS) {
/* A zone without SOA record?!? */
"catz: zone '%s' has no SOA record (%s)",
return;
}
"catz: updating catalog zone '%s' with serial %d",
if (result != ISC_R_SUCCESS) {
"catz: failed to create new zone - %s",
return;
}
if (result != ISC_R_SUCCESS) {
"catz: failed to create DB iterator - %s",
return;
}
/*
* Iterate over database to fill the new zone
*/
if (result != ISC_R_SUCCESS) {
"catz: failed to get db iterator - %s",
}
while (result == ISC_R_SUCCESS) {
if (result != ISC_R_SUCCESS) {
"catz: failed to get db iterator - %s",
break;
}
&rdsiter);
if (result != ISC_R_SUCCESS) {
"catz: failed to fetch rrdatasets - %s",
break;
}
while (result == ISC_R_SUCCESS) {
&rdataset);
if (result != ISC_R_SUCCESS) {
char cname[DNS_NAME_FORMATSIZE];
"catz: unknown record in catalog "
"zone - %s (%s) - ignoring",
}
if (result != ISC_R_SUCCESS) {
break;
}
}
}
"catz: update_from_db: iteration finished");
/*
* Finally merge new zone into old zone
*/
if (result != ISC_R_SUCCESS) {
"catz: failed merging zones: %s",
return;
}
"catz: update_from_db: new zone merged");
}
static isc_result_t
void *data)
{
return (ISC_R_SUCCESS);
}
void
}
static isc_result_t
void *data)
{
char cname[DNS_NAME_FORMATSIZE];
"catz: removing catalog zone %s", cname);
/* Merge the old zone with an empty one to remove all members */
/* Make sure that we have an empty catalog zone */
return (ISC_R_EXISTS);
}
return (ISC_R_SUCCESS);
}
void
}
}