2010-12-18 01:56:23 +00:00
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
|
2010-12-18 01:56:23 +00:00
|
|
|
*
|
2011-10-20 22:01:48 +00:00
|
|
|
* Permission to use, copy, modify, and/or 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.
|
2010-12-18 01:56:23 +00:00
|
|
|
*
|
2011-10-20 22:01:48 +00:00
|
|
|
* 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.
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
/* $Id: dlz_example.c,v 1.3 2011/10/20 22:01:48 each Exp $ */
|
|
|
|
|
2010-12-18 01:56:23 +00:00
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* This provides a very simple example of an external loadable DLZ
|
|
|
|
* driver, with update support.
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdarg.h>
|
2011-10-20 22:01:48 +00:00
|
|
|
#include <stdint.h>
|
2010-12-18 01:56:23 +00:00
|
|
|
|
|
|
|
#include "dlz_minimal.h"
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
#define STRTOK_R(a, b, c) strtok_s(a, b, c)
|
|
|
|
#elif defined(_REENTRANT)
|
|
|
|
#define STRTOK_R(a, b, c) strtok_r(a, b, c)
|
|
|
|
#else
|
|
|
|
#define STRTOK_R(a, b, c) strtok(a, b)
|
|
|
|
#endif
|
2010-12-18 01:56:23 +00:00
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
/* For this simple example, use fixed sized strings */
|
2010-12-18 01:56:23 +00:00
|
|
|
struct record {
|
|
|
|
char name[100];
|
|
|
|
char type[10];
|
|
|
|
char data[200];
|
2011-10-20 22:01:48 +00:00
|
|
|
dns_ttl_t ttl;
|
2010-12-18 01:56:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define MAX_RECORDS 100
|
|
|
|
|
|
|
|
struct dlz_example_data {
|
|
|
|
char *zone_name;
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
/* An example driver doesn't need good memory management :-) */
|
2010-12-18 01:56:23 +00:00
|
|
|
struct record current[MAX_RECORDS];
|
|
|
|
struct record adds[MAX_RECORDS];
|
|
|
|
struct record deletes[MAX_RECORDS];
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_boolean_t transaction_started;
|
2010-12-18 01:56:23 +00:00
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
/* Helper functions from the dlz_dlopen driver */
|
|
|
|
log_t *log;
|
|
|
|
dns_sdlz_putrr_t *putrr;
|
|
|
|
dns_sdlz_putnamedrr_t *putnamedrr;
|
|
|
|
dns_dlz_writeablezone_t *writeable_zone;
|
2010-12-18 01:56:23 +00:00
|
|
|
};
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
static isc_boolean_t
|
|
|
|
single_valued(const char *type) {
|
2010-12-18 01:56:23 +00:00
|
|
|
const char *single[] = { "soa", "cname", NULL };
|
|
|
|
int i;
|
2011-10-20 22:01:48 +00:00
|
|
|
|
|
|
|
for (i = 0; single[i]; i++) {
|
2010-12-18 01:56:23 +00:00
|
|
|
if (strcasecmp(single[i], type) == 0) {
|
2011-10-20 22:01:48 +00:00
|
|
|
return (ISC_TRUE);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
}
|
2011-10-20 22:01:48 +00:00
|
|
|
return (ISC_FALSE);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* Add a record to a list
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
static isc_result_t
|
|
|
|
add_name(struct dlz_example_data *state, struct record *list,
|
|
|
|
const char *name, const char *type, dns_ttl_t ttl, const char *data)
|
2010-12-18 01:56:23 +00:00
|
|
|
{
|
|
|
|
int i;
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_boolean_t single = single_valued(type);
|
2010-12-18 01:56:23 +00:00
|
|
|
int first_empty = -1;
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
for (i = 0; i < MAX_RECORDS; i++) {
|
|
|
|
if (first_empty == -1 && strlen(list[i].name) == 0U) {
|
2010-12-18 01:56:23 +00:00
|
|
|
first_empty = i;
|
|
|
|
}
|
2011-10-20 22:01:48 +00:00
|
|
|
if (strcasecmp(list[i].name, name) != 0)
|
2010-12-18 01:56:23 +00:00
|
|
|
continue;
|
|
|
|
if (strcasecmp(list[i].type, type) != 0)
|
|
|
|
continue;
|
|
|
|
if (!single && strcasecmp(list[i].data, data) != 0)
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == MAX_RECORDS && first_empty != -1) {
|
|
|
|
i = first_empty;
|
|
|
|
}
|
|
|
|
if (i == MAX_RECORDS) {
|
|
|
|
state->log(ISC_LOG_ERROR, "dlz_example: out of record space");
|
2011-10-20 22:01:48 +00:00
|
|
|
return (ISC_R_FAILURE);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
strcpy(list[i].name, name);
|
|
|
|
strcpy(list[i].type, type);
|
|
|
|
strcpy(list[i].data, data);
|
|
|
|
list[i].ttl = ttl;
|
2011-10-20 22:01:48 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* Delete a record from a list
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
static isc_result_t
|
|
|
|
del_name(struct dlz_example_data *state, struct record *list,
|
|
|
|
const char *name, const char *type, dns_ttl_t ttl,
|
|
|
|
const char *data)
|
2010-12-18 01:56:23 +00:00
|
|
|
{
|
|
|
|
int i;
|
2011-10-20 22:01:48 +00:00
|
|
|
|
|
|
|
UNUSED(state);
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_RECORDS; i++) {
|
2010-12-18 01:56:23 +00:00
|
|
|
if (strcasecmp(name, list[i].name) == 0 &&
|
|
|
|
strcasecmp(type, list[i].type) == 0 &&
|
|
|
|
strcasecmp(data, list[i].data) == 0 &&
|
|
|
|
ttl == list[i].ttl) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i == MAX_RECORDS) {
|
2011-10-20 22:01:48 +00:00
|
|
|
return (ISC_R_NOTFOUND);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
memset(&list[i], 0, sizeof(struct record));
|
2011-10-20 22:01:48 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
static isc_result_t
|
|
|
|
fmt_address(isc_sockaddr_t *addr, char *buffer, size_t size) {
|
|
|
|
char addr_buf[100];
|
|
|
|
const char *ret;
|
|
|
|
uint16_t port = 0;
|
|
|
|
|
|
|
|
switch (addr->type.sa.sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
port = ntohs(addr->type.sin.sin_port);
|
|
|
|
ret = inet_ntop(AF_INET, &addr->type.sin.sin_addr, addr_buf,
|
|
|
|
sizeof(addr_buf));
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
port = ntohs(addr->type.sin6.sin6_port);
|
|
|
|
ret = inet_ntop(AF_INET6, &addr->type.sin6.sin6_addr, addr_buf,
|
|
|
|
sizeof(addr_buf));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret == NULL)
|
|
|
|
return (ISC_R_FAILURE);
|
2010-12-18 01:56:23 +00:00
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
snprintf(buffer, size, "%s#%u", addr_buf, port);
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
2010-12-18 01:56:23 +00:00
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* Return the version of the API
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
int
|
|
|
|
dlz_version(unsigned int *flags) {
|
|
|
|
UNUSED(flags);
|
|
|
|
return (DLZ_DLOPEN_VERSION);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* Remember a helper function from the bind9 dlz_dlopen driver
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
static void
|
|
|
|
b9_add_helper(struct dlz_example_data *state,
|
|
|
|
const char *helper_name, void *ptr)
|
2010-12-18 01:56:23 +00:00
|
|
|
{
|
2011-10-20 22:01:48 +00:00
|
|
|
if (strcmp(helper_name, "log") == 0)
|
|
|
|
state->log = (log_t *)ptr;
|
|
|
|
if (strcmp(helper_name, "putrr") == 0)
|
|
|
|
state->putrr = (dns_sdlz_putrr_t *)ptr;
|
|
|
|
if (strcmp(helper_name, "putnamedrr") == 0)
|
|
|
|
state->putnamedrr = (dns_sdlz_putnamedrr_t *)ptr;
|
|
|
|
if (strcmp(helper_name, "writeable_zone") == 0)
|
|
|
|
state->writeable_zone = (dns_dlz_writeablezone_t *)ptr;
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* Called to initialize the driver
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_result_t
|
|
|
|
dlz_create(const char *dlzname, unsigned int argc, char *argv[],
|
|
|
|
void **dbdata, ...)
|
2010-12-18 01:56:23 +00:00
|
|
|
{
|
|
|
|
struct dlz_example_data *state;
|
|
|
|
const char *helper_name;
|
|
|
|
va_list ap;
|
|
|
|
char soa_data[200];
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
UNUSED(dlzname);
|
|
|
|
|
2010-12-18 01:56:23 +00:00
|
|
|
state = calloc(1, sizeof(struct dlz_example_data));
|
2011-10-20 22:01:48 +00:00
|
|
|
if (state == NULL)
|
|
|
|
return (ISC_R_NOMEMORY);
|
2010-12-18 01:56:23 +00:00
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
/* Fill in the helper functions */
|
2010-12-18 01:56:23 +00:00
|
|
|
va_start(ap, dbdata);
|
|
|
|
while ((helper_name = va_arg(ap, const char *)) != NULL) {
|
|
|
|
b9_add_helper(state, helper_name, va_arg(ap, void*));
|
|
|
|
}
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
if (argc < 2) {
|
2011-10-20 22:01:48 +00:00
|
|
|
state->log(ISC_LOG_ERROR,
|
|
|
|
"dlz_example: please specify a zone name");
|
|
|
|
return (ISC_R_FAILURE);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
state->zone_name = strdup(argv[1]);
|
|
|
|
|
|
|
|
sprintf(soa_data, "%s hostmaster.%s 123 900 600 86400 3600",
|
|
|
|
state->zone_name, state->zone_name);
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
add_name(state, &state->current[0], state->zone_name,
|
|
|
|
"soa", 3600, soa_data);
|
|
|
|
add_name(state, &state->current[0], state->zone_name,
|
|
|
|
"ns", 3600, state->zone_name);
|
|
|
|
add_name(state, &state->current[0], state->zone_name,
|
|
|
|
"a", 1800, "10.53.0.1");
|
2010-12-18 01:56:23 +00:00
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
state->log(ISC_LOG_INFO,
|
|
|
|
"dlz_example: started for zone %s",
|
|
|
|
state->zone_name);
|
2010-12-18 01:56:23 +00:00
|
|
|
|
|
|
|
*dbdata = state;
|
2011-10-20 22:01:48 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* Shut down the backend
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
void
|
|
|
|
dlz_destroy(void *dbdata) {
|
2010-12-18 01:56:23 +00:00
|
|
|
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
2011-10-20 22:01:48 +00:00
|
|
|
|
|
|
|
state->log(ISC_LOG_INFO,
|
|
|
|
"dlz_example: shutting down zone %s",
|
|
|
|
state->zone_name);
|
2010-12-18 01:56:23 +00:00
|
|
|
free(state->zone_name);
|
|
|
|
free(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* See if we handle a given zone
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_result_t
|
|
|
|
dlz_findzonedb(void *dbdata, const char *name) {
|
2010-12-18 01:56:23 +00:00
|
|
|
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
if (strcasecmp(state->zone_name, name) == 0)
|
|
|
|
return (ISC_R_SUCCESS);
|
2010-12-18 01:56:23 +00:00
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
return (ISC_R_NOTFOUND);
|
|
|
|
}
|
2010-12-18 01:56:23 +00:00
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* Look up one record in the sample database.
|
|
|
|
*
|
|
|
|
* If the queryname is "source-addr", we add a TXT record containing
|
|
|
|
* the address of the client; this demonstrates the use of 'methods'
|
|
|
|
* and 'clientinfo'.
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_result_t
|
|
|
|
dlz_lookup(const char *zone, const char *name, void *dbdata,
|
|
|
|
dns_sdlzlookup_t *lookup, dns_clientinfomethods_t *methods,
|
|
|
|
dns_clientinfo_t *clientinfo)
|
2010-12-18 01:56:23 +00:00
|
|
|
{
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_result_t result;
|
2010-12-18 01:56:23 +00:00
|
|
|
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_boolean_t found = ISC_FALSE;
|
|
|
|
isc_sockaddr_t *src;
|
2010-12-18 01:56:23 +00:00
|
|
|
char full_name[100];
|
2011-10-20 22:01:48 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
UNUSED(zone);
|
|
|
|
|
|
|
|
if (strcmp(name, "@") == 0)
|
2010-12-18 01:56:23 +00:00
|
|
|
strcpy(full_name, state->zone_name);
|
2011-10-20 22:01:48 +00:00
|
|
|
else
|
2010-12-18 01:56:23 +00:00
|
|
|
sprintf(full_name, "%s.%s", name, state->zone_name);
|
2011-10-20 22:01:48 +00:00
|
|
|
|
|
|
|
if (strcmp(name, "source-addr") == 0) {
|
|
|
|
char buf[100];
|
|
|
|
strcpy(buf, "unknown");
|
|
|
|
if (methods != NULL &&
|
|
|
|
methods->version - methods->age >=
|
|
|
|
DNS_CLIENTINFOMETHODS_VERSION)
|
|
|
|
{
|
|
|
|
methods->sourceip(clientinfo, &src);
|
|
|
|
fmt_address(src, buf, sizeof(buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "connection from: %s\n", buf);
|
|
|
|
|
|
|
|
found = ISC_TRUE;
|
|
|
|
result = state->putrr(lookup, "TXT", 0, buf);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
2011-10-20 22:01:48 +00:00
|
|
|
|
|
|
|
for (i = 0; i < MAX_RECORDS; i++) {
|
2010-12-18 01:56:23 +00:00
|
|
|
if (strcasecmp(state->current[i].name, full_name) == 0) {
|
2011-10-20 22:01:48 +00:00
|
|
|
found = ISC_TRUE;
|
|
|
|
result = state->putrr(lookup, state->current[i].type,
|
|
|
|
state->current[i].ttl,
|
|
|
|
state->current[i].data);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
}
|
2011-10-20 22:01:48 +00:00
|
|
|
|
|
|
|
if (!found)
|
|
|
|
return (ISC_R_NOTFOUND);
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* See if a zone transfer is allowed
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_result_t
|
|
|
|
dlz_allowzonexfr(void *dbdata, const char *name, const char *client) {
|
|
|
|
UNUSED(client);
|
|
|
|
|
|
|
|
/* Just say yes for all our zones */
|
|
|
|
return (dlz_findzonedb(dbdata, name));
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* Perform a zone transfer
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_result_t
|
|
|
|
dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes) {
|
2010-12-18 01:56:23 +00:00
|
|
|
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
|
|
|
int i;
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
UNUSED(zone);
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_RECORDS; i++) {
|
2010-12-18 01:56:23 +00:00
|
|
|
isc_result_t result;
|
2011-10-20 22:01:48 +00:00
|
|
|
if (strlen(state->current[i].name) == 0U) {
|
2010-12-18 01:56:23 +00:00
|
|
|
continue;
|
|
|
|
}
|
2011-10-20 22:01:48 +00:00
|
|
|
result = state->putnamedrr(allnodes, state->current[i].name,
|
|
|
|
state->current[i].type,
|
|
|
|
state->current[i].ttl,
|
|
|
|
state->current[i].data);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* Start a transaction
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_result_t
|
|
|
|
dlz_newversion(const char *zone, void *dbdata, void **versionp) {
|
2010-12-18 01:56:23 +00:00
|
|
|
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
|
|
|
|
|
|
|
if (state->transaction_started) {
|
2011-10-20 22:01:48 +00:00
|
|
|
state->log(ISC_LOG_INFO,
|
|
|
|
"dlz_example: transaction already "
|
|
|
|
"started for zone %s", zone);
|
|
|
|
return (ISC_R_FAILURE);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
state->transaction_started = ISC_TRUE;
|
2010-12-18 01:56:23 +00:00
|
|
|
*versionp = (void *) &state->transaction_started;
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* End a transaction
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
void
|
|
|
|
dlz_closeversion(const char *zone, isc_boolean_t commit,
|
|
|
|
void *dbdata, void **versionp)
|
2010-12-18 01:56:23 +00:00
|
|
|
{
|
|
|
|
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
|
|
|
|
|
|
|
if (!state->transaction_started) {
|
2011-10-20 22:01:48 +00:00
|
|
|
state->log(ISC_LOG_INFO,
|
|
|
|
"dlz_example: transaction not started for zone %s",
|
|
|
|
zone);
|
2010-12-18 01:56:23 +00:00
|
|
|
*versionp = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
state->transaction_started = ISC_FALSE;
|
2010-12-18 01:56:23 +00:00
|
|
|
|
|
|
|
*versionp = NULL;
|
|
|
|
|
|
|
|
if (commit) {
|
|
|
|
int i;
|
2011-10-20 22:01:48 +00:00
|
|
|
state->log(ISC_LOG_INFO,
|
|
|
|
"dlz_example: committing transaction on zone %s",
|
|
|
|
zone);
|
|
|
|
for (i = 0; i < MAX_RECORDS; i++) {
|
|
|
|
if (strlen(state->adds[i].name) > 0U) {
|
|
|
|
add_name(state, &state->current[0],
|
|
|
|
state->adds[i].name,
|
|
|
|
state->adds[i].type,
|
|
|
|
state->adds[i].ttl,
|
2010-12-18 01:56:23 +00:00
|
|
|
state->adds[i].data);
|
|
|
|
}
|
|
|
|
}
|
2011-10-20 22:01:48 +00:00
|
|
|
for (i = 0; i < MAX_RECORDS; i++) {
|
|
|
|
if (strlen(state->deletes[i].name) > 0U) {
|
|
|
|
del_name(state, &state->current[0],
|
|
|
|
state->deletes[i].name,
|
|
|
|
state->deletes[i].type,
|
|
|
|
state->deletes[i].ttl,
|
2010-12-18 01:56:23 +00:00
|
|
|
state->deletes[i].data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2011-10-20 22:01:48 +00:00
|
|
|
state->log(ISC_LOG_INFO,
|
|
|
|
"dlz_example: cancelling transaction on zone %s",
|
|
|
|
zone);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
memset(state->adds, 0, sizeof(state->adds));
|
|
|
|
memset(state->deletes, 0, sizeof(state->deletes));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* Configure a writeable zone
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_result_t
|
|
|
|
dlz_configure(dns_view_t *view, void *dbdata) {
|
2010-12-18 01:56:23 +00:00
|
|
|
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
|
|
|
|
state->log(ISC_LOG_INFO, "dlz_example: starting configure");
|
|
|
|
if (state->writeable_zone == NULL) {
|
2011-10-20 22:01:48 +00:00
|
|
|
state->log(ISC_LOG_INFO,
|
|
|
|
"dlz_example: no writeable_zone method available");
|
|
|
|
return (ISC_R_FAILURE);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
2012-03-05 15:42:52 -08:00
|
|
|
result = state->writeable_zone(view, state->zone_name);
|
2010-12-18 01:56:23 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2011-10-20 22:01:48 +00:00
|
|
|
state->log(ISC_LOG_ERROR,
|
|
|
|
"dlz_example: failed to configure zone %s",
|
|
|
|
state->zone_name);
|
|
|
|
return (result);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
state->log(ISC_LOG_INFO,
|
|
|
|
"dlz_example: configured writeable zone %s",
|
|
|
|
state->zone_name);
|
|
|
|
return (ISC_R_SUCCESS);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* Authorize a zone update
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_boolean_t
|
|
|
|
dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
|
|
|
|
const char *type, const char *key, uint32_t keydatalen,
|
|
|
|
unsigned char *keydata, void *dbdata)
|
2010-12-18 01:56:23 +00:00
|
|
|
{
|
|
|
|
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
2011-10-20 22:01:48 +00:00
|
|
|
|
|
|
|
UNUSED(tcpaddr);
|
|
|
|
UNUSED(type);
|
|
|
|
UNUSED(key);
|
|
|
|
UNUSED(keydatalen);
|
|
|
|
UNUSED(keydata);
|
|
|
|
|
2010-12-18 01:56:23 +00:00
|
|
|
if (strncmp(name, "deny.", 5) == 0) {
|
2011-10-20 22:01:48 +00:00
|
|
|
state->log(ISC_LOG_INFO,
|
|
|
|
"dlz_example: denying update of name=%s by %s",
|
2010-12-18 01:56:23 +00:00
|
|
|
name, signer);
|
2011-10-20 22:01:48 +00:00
|
|
|
return (ISC_FALSE);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
2011-10-20 22:01:48 +00:00
|
|
|
state->log(ISC_LOG_INFO,
|
|
|
|
"dlz_example: allowing update of name=%s by %s",
|
2010-12-18 01:56:23 +00:00
|
|
|
name, signer);
|
2011-10-20 22:01:48 +00:00
|
|
|
return (ISC_TRUE);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
static isc_result_t
|
|
|
|
modrdataset(struct dlz_example_data *state, const char *name,
|
|
|
|
const char *rdatastr, struct record *list)
|
2010-12-18 01:56:23 +00:00
|
|
|
{
|
|
|
|
char *full_name, *dclass, *type, *data, *ttlstr;
|
|
|
|
char *buf = strdup(rdatastr);
|
|
|
|
isc_result_t result;
|
2011-10-20 22:01:48 +00:00
|
|
|
#if defined(WIN32) || defined(_REENTRANT)
|
2010-12-18 01:56:23 +00:00
|
|
|
char *saveptr = NULL;
|
2011-10-20 22:01:48 +00:00
|
|
|
#endif
|
2010-12-18 01:56:23 +00:00
|
|
|
|
|
|
|
/*
|
2011-10-20 22:01:48 +00:00
|
|
|
* The format is:
|
|
|
|
* FULLNAME\tTTL\tDCLASS\tTYPE\tDATA
|
|
|
|
*
|
|
|
|
* The DATA field is space separated, and is in the data format
|
|
|
|
* for the type used by dig
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
full_name = STRTOK_R(buf, "\t", &saveptr);
|
|
|
|
if (full_name == NULL)
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
|
|
|
|
ttlstr = STRTOK_R(NULL, "\t", &saveptr);
|
|
|
|
if (ttlstr == NULL)
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
|
|
|
|
dclass = STRTOK_R(NULL, "\t", &saveptr);
|
|
|
|
if (dclass == NULL)
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
|
|
|
|
type = STRTOK_R(NULL, "\t", &saveptr);
|
|
|
|
if (type == NULL)
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
|
|
|
|
data = STRTOK_R(NULL, "\t", &saveptr);
|
|
|
|
if (data == NULL)
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
|
|
|
|
result = add_name(state, list, name, type,
|
|
|
|
strtoul(ttlstr, NULL, 10), data);
|
2010-12-18 01:56:23 +00:00
|
|
|
free(buf);
|
2011-10-20 22:01:48 +00:00
|
|
|
return (result);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_result_t
|
|
|
|
dlz_addrdataset(const char *name, const char *rdatastr,
|
|
|
|
void *dbdata, void *version)
|
2010-12-18 01:56:23 +00:00
|
|
|
{
|
|
|
|
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
if (version != (void *) &state->transaction_started)
|
|
|
|
return (ISC_R_FAILURE);
|
2010-12-18 01:56:23 +00:00
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
state->log(ISC_LOG_INFO,
|
|
|
|
"dlz_example: adding rdataset %s '%s'",
|
|
|
|
name, rdatastr);
|
2010-12-18 01:56:23 +00:00
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
return (modrdataset(state, name, rdatastr, &state->adds[0]));
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_result_t
|
|
|
|
dlz_subrdataset(const char *name, const char *rdatastr,
|
|
|
|
void *dbdata, void *version)
|
2010-12-18 01:56:23 +00:00
|
|
|
{
|
|
|
|
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
if (version != (void *) &state->transaction_started)
|
|
|
|
return (ISC_R_FAILURE);
|
2010-12-18 01:56:23 +00:00
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
state->log(ISC_LOG_INFO,
|
|
|
|
"dlz_example: subtracting rdataset %s '%s'",
|
|
|
|
name, rdatastr);
|
|
|
|
|
|
|
|
return (modrdataset(state, name, rdatastr, &state->deletes[0]));
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
isc_result_t
|
|
|
|
dlz_delrdataset(const char *name, const char *type,
|
|
|
|
void *dbdata, void *version)
|
2010-12-18 01:56:23 +00:00
|
|
|
{
|
|
|
|
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
if (version != (void *) &state->transaction_started)
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
|
|
|
|
state->log(ISC_LOG_INFO,
|
|
|
|
"dlz_example: deleting rdataset %s of type %s",
|
|
|
|
name, type);
|
2010-12-18 01:56:23 +00:00
|
|
|
|
2011-10-20 22:01:48 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|