/*
* Copyright (C) 2011 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.
*/
/*
* This provides a very simple example of an external loadable DLZ
* driver, with update support.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdint.h>
#include "../modules/include/dlz_minimal.h"
#ifdef WIN32
#elif defined(_REENTRANT)
#else
#endif
#define CHECK(x) \
do { \
result = (x); \
if (result != ISC_R_SUCCESS) \
goto failure; \
} while (0)
/* For this simple example, use fixed sized strings */
struct record {
};
struct dlz_example_data {
char *zone_name;
/* An example driver doesn't need good memory management :-) */
/* Helper functions from the dlz_dlopen driver */
};
static isc_boolean_t
int i;
for (i = 0; single[i]; i++) {
return (ISC_TRUE);
}
}
return (ISC_FALSE);
}
/*
* Add a record to a list
*/
static isc_result_t
{
int i;
for (i = 0; i < MAX_RECORDS; i++) {
first_empty = i;
}
continue;
continue;
continue;
break;
}
i = first_empty;
}
if (i == MAX_RECORDS) {
"dlz_example: out of record space");
return (ISC_R_FAILURE);
}
return (ISC_R_NOSPACE);
return (ISC_R_SUCCESS);
}
/*
* Delete a record from a list
*/
static isc_result_t
const char *data)
{
int i;
for (i = 0; i < MAX_RECORDS; i++) {
break;
}
}
if (i == MAX_RECORDS) {
return (ISC_R_NOTFOUND);
}
return (ISC_R_SUCCESS);
}
static isc_result_t
const char *ret;
case AF_INET:
sizeof(addr_buf));
break;
case AF_INET6:
sizeof(addr_buf));
break;
default:
return (ISC_R_FAILURE);
}
return (ISC_R_FAILURE);
return (ISC_R_SUCCESS);
}
/*
* Return the version of the API
*/
int
return (DLZ_DLOPEN_VERSION);
}
/*
* Remember a helper function from the bind9 dlz_dlopen driver
*/
static void
const char *helper_name, void *ptr)
{
}
/*
* Called to initialize the driver
*/
void **dbdata, ...)
{
const char *helper_name;
const char *extra;
int n;
return (ISC_R_NOMEMORY);
/* Fill in the helper functions */
}
"dlz_example: please specify a zone name");
return (ISC_R_FAILURE);
}
/* Ensure zone name is absolute */
return (ISC_R_NOMEMORY);
}
else
extra = ".root";
else
extra = ".";
if (n < 0)
if ((unsigned)n >= sizeof(soa_data))
"a", 1800, "10.53.0.1");
return (ISC_R_SUCCESS);
return (result);
}
/*
* Shut down the backend
*/
void
"dlz_example: shutting down zone %s",
}
/*
* See if we handle a given zone
*/
{
{
}
"dlz_example: findzonedb connection from: %s", addrbuf);
"dlz_example: dlz_findzonedb called with name '%s' "
/*
* Returning ISC_R_NOTFOUND will cause the query logic to
* check the database for parent names, looking for zone cuts.
*
* Returning ISC_R_NOMORE prevents the query logic from doing
* this; it will move onto the next database after a single query.
*/
return (ISC_R_NOMORE);
/*
* For example.net, only return ISC_R_NOMORE when queried
* from 10.53.0.1.
*/
return (ISC_R_NOMORE);
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
return (ISC_R_NOTFOUND);
}
/*
* Look up one record in the sample database.
*
* If the queryname is "source-addr", send back a TXT record containing
* the address of the client; this demonstrates the use of 'methods'
* and 'clientinfo'.
*
* If the queryname is "too-long", send back a TXT record that's too long
* to process; this should result in a SERVFAIL when queried.
*/
{
int i;
return (ISC_R_NOTIMPLEMENTED);
} else
/*
* If we need to know the database version (as set in
* the 'newversion' dlz function) we can pick it up from the
* clientinfo.
*
* This allows a lookup to query the correct version of the DNS
* data, if the DLZ can differentiate between versions.
*
* For example, if a new database transaction is created by
* 'newversion', the lookup should query within the same
* transaction scope if it can.
*
* If the DLZ only operates on 'live' data, then version
* wouldn't necessarily be needed.
*/
if (clientinfo != NULL &&
"dlz_example: lookup against live "
"transaction\n");
}
{
}
"dlz_example: lookup connection from: %s", buf);
if (result != ISC_R_SUCCESS)
return (result);
}
for (i = 0; i < 511; i++)
buf[i] = 'x';
buf[i] = '\0';
if (result != ISC_R_SUCCESS)
return (result);
}
for (i = 0; i < MAX_RECORDS; i++) {
if (result != ISC_R_SUCCESS)
return (result);
}
}
if (!found)
return (ISC_R_NOTFOUND);
return (ISC_R_SUCCESS);
}
/*
* See if a zone transfer is allowed
*/
/* Just say yes for all our zones */
}
/*
* Perform a zone transfer
*/
int i;
return (ISC_R_NOTIMPLEMENTED);
for (i = 0; i < MAX_RECORDS; i++) {
continue;
}
if (result != ISC_R_SUCCESS)
return (result);
}
return (ISC_R_SUCCESS);
}
/*
* Start a transaction
*/
if (state->transaction_started) {
"dlz_example: transaction already "
"started for zone %s", zone);
return (ISC_R_FAILURE);
}
return (ISC_R_SUCCESS);
}
/*
* End a transaction
*/
void
{
if (!state->transaction_started) {
"started for zone %s", zone);
return;
}
if (commit) {
int i;
"transaction on zone %s", zone);
for (i = 0; i < MAX_RECORDS; i++) {
}
}
for (i = 0; i < MAX_RECORDS; i++) {
}
}
} else {
"transaction on zone %s", zone);
}
}
/*
* Configure a writeable zone
*/
"writeable_zone method available");
return (ISC_R_FAILURE);
}
if (result != ISC_R_SUCCESS) {
return (result);
}
return (ISC_R_SUCCESS);
}
/*
* Authorize a zone update
*/
{
return (ISC_FALSE);
}
return (ISC_TRUE);
}
static isc_result_t
{
#if defined(WIN32) || defined(_REENTRANT)
#endif
return (ISC_R_FAILURE);
/*
* 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
*/
goto error;
goto error;
goto error;
goto error;
goto error;
}
return (result);
return (ISC_R_FAILURE);
}
{
return (ISC_R_FAILURE);
}
{
return (ISC_R_FAILURE);
}
{
return (ISC_R_FAILURE);
return (ISC_R_SUCCESS);
}