Commit 686b27bf authored by Mark Andrews's avatar Mark Andrews
Browse files

Initial zone code. Minimally functional.

parent a0c88183
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <isc/error.h>
#include <isc/mem.h>
#include <isc/app.h>
#include <dns/db.h>
#include <dns/zone.h>
#include <dns/rdataclass.h>
static int debug = 0;
static int quiet = 0;
static int stats = 0;
static isc_mem_t *mctx = NULL;
dns_zone_t *zone = NULL;
isc_taskmgr_t *manager = NULL;
dns_zonetype_t zonetype = dns_zone_master;
isc_sockaddr_t addr;
#define ERRRET(result, function) \
do { \
if (result != DNS_R_SUCCESS) { \
fprintf(stderr, "%s() returned %s\n", \
function, dns_result_totext(result)); \
return; \
} \
} while (0)
#define ERRCONT(result, function) \
if (result != DNS_R_SUCCESS) { \
fprintf(stderr, "%s() returned %s\n", \
function, dns_result_totext(result)); \
continue; \
} else \
(void)NULL
static void
usage() {
fprintf(stderr,
"usage: test_zone [-dqsSM] [-c class] [-f file] zone\n");
exit(1);
}
static void
setup(char *zonename, char *filename, char *classname) {
dns_result_t result;
dns_rdataclass_t rdclass;
isc_textregion_t region;
if (debug)
fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
zonename, filename, classname);
result = dns_zone_create(&zone, mctx);
ERRRET(result, "dns_zone_new");
dns_zone_settype(zone, zonetype);
result = dns_zone_setorigin(zone, zonename);
ERRRET(result, "dns_zone_setorigin");
result = dns_zone_setdbtype(zone, "rbt");
ERRRET(result, "dns_zone_setdatabase");
result = dns_zone_setdatabase(zone, filename);
ERRRET(result, "dns_zone_setdatabase");
region.base = classname;
region.length = strlen(classname);
result = dns_rdataclass_fromtext(&rdclass, &region);
ERRRET(result, "dns_rdataclass_fromtext");
dns_zone_setclass(zone, rdclass);
if (zonetype == dns_zone_slave) {
dns_zone_addmaster(zone, &addr);
}
result = dns_zone_load(zone);
ERRRET(result, "dns_zone_load");
result = dns_zone_manage(zone, manager);
ERRRET(result, "dns_zone_load");
}
static void
print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset) {
isc_buffer_t text;
char t[1000];
dns_result_t result;
isc_region_t r;
isc_buffer_init(&text, t, sizeof t, ISC_BUFFERTYPE_TEXT);
result = dns_rdataset_totext(rdataset, name, ISC_FALSE, ISC_FALSE,
&text);
isc_buffer_used(&text, &r);
if (result == DNS_R_SUCCESS)
printf("%.*s", (int)r.length, (char *)r.base);
else
printf("%s\n", dns_result_totext(result));
}
static void
query(void) {
char buf[1024];
dns_fixedname_t name;
dns_fixedname_t found;
dns_db_t *db;
char *s;
isc_buffer_t buffer;
dns_result_t result;
dns_rdataset_t rdataset;
fd_set rfdset;
db = dns_zone_getdb(zone);
if (db == NULL) {
fprintf(stderr, "db == NULL\n");
return;
}
dns_fixedname_init(&found);
dns_rdataset_init(&rdataset);
do {
fprintf(stdout, "zone_test ");
fflush(stdout);
FD_ZERO(&rfdset);
FD_SET(0, &rfdset);
select(1, &rfdset, NULL, NULL, NULL);
if (fgets(buf, sizeof buf, stdin) == NULL) {
fprintf(stdout, "\n");
break;
}
buf[sizeof(buf) - 1] = '\0';
s = strchr(buf, '\n');
if (s != NULL)
*s = '\0';
s = strchr(buf, '\r');
if (s != NULL)
*s = '\0';
if (strcmp(buf, "dump") == 0) {
dns_zone_dump(zone, stdout);
continue;
}
if (strlen(buf) == 0)
continue;
dns_fixedname_init(&name);
isc_buffer_init(&buffer, buf, strlen(buf), ISC_BUFFERTYPE_TEXT);
isc_buffer_add(&buffer, strlen(buf));
result = dns_name_fromtext(dns_fixedname_name(&name),
&buffer, dns_rootname, ISC_FALSE, NULL);
ERRCONT(result, "dns_name_fromtext");
result = dns_db_find(db, dns_fixedname_name(&name),
NULL /*vesion*/,
dns_rdatatype_a,
0 /*options*/,
0 /*time*/,
NULL /*nodep*/,
dns_fixedname_name(&found),
&rdataset);
fprintf(stderr, "%s() returned %s\n", "dns_db_find",
dns_result_totext(result));
switch (result) {
case DNS_R_DELEGATION:
print_rdataset(dns_fixedname_name(&found), &rdataset);
break;
case DNS_R_SUCCESS:
print_rdataset(dns_fixedname_name(&name), &rdataset);
break;
default:
continue;
}
dns_rdataset_disassociate(&rdataset);
} while (1);
dns_rdataset_invalidate(&rdataset);
}
static void
destroy(void) {
if (zone == NULL)
return;
dns_zone_detach(&zone);
}
int
main(int argc, char **argv) {
int c;
char *filename = NULL;
char *classname = "IN";
while ((c = getopt(argc, argv, "cdf:m:qsMS")) != EOF) {
switch (c) {
case 'c':
classname = optarg;
break;
case 'd':
debug++;
break;
case 'f':
if (filename != NULL)
usage();
filename = optarg;
break;
case 'm':
memset(&addr, 0, sizeof addr);
addr.type.sin.sin_family = AF_INET;
inet_pton(AF_INET, optarg, &addr.type.sin.sin_addr);
addr.type.sin.sin_port = htons(53);
break;
case 'q':
quiet++;
break;
case 's':
stats++;
break;
case 'S':
zonetype = dns_zone_slave;
break;
case 'M':
zonetype = dns_zone_master;
break;
default:
usage();
}
}
if (argv[optind] == NULL)
usage();
RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_taskmgr_create(mctx, 2, 0, &manager) ==
ISC_R_SUCCESS);
if (filename == NULL)
filename = argv[optind];
setup(argv[optind], filename, classname);
query();
destroy();
isc_taskmgr_destroy(&manager);
if (!quiet && stats)
isc_mem_stats(mctx, stdout);
isc_mem_destroy(&mctx);
exit(0);
}
/*
* Copyright (C) 1999 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.
*/
#ifndef DNS_ZONE_H
#define DNS_ZONE_H 1
/***
*** Imports
***/
#include <isc/lang.h>
#include <isc/mem.h>
#include <isc/lex.h>
#include <isc/mutex.h>
#include <isc/time.h>
#include <isc/stdtime.h>
#include <isc/socket.h>
#include <dns/types.h>
#include <dns/result.h>
#include <dns/name.h>
#include <dns/fixedname.h>
#include <dns/rdataset.h>
#include <dns/callbacks.h>
#include <dns/confctx.h>
typedef enum {
dns_zone_none,
dns_zone_master,
dns_zone_slave,
dns_zone_hint,
dns_zone_stub,
dns_zone_cache,
dns_zone_forward
} dns_zonetype_t;
#define DNS_ZONE_O_SERVERS 0x00000001U /* perform server checks */
#define DNS_ZONE_O_PARENTS 0x00000002U /* perform parent checks */
#define DNS_ZONE_O_CHILDREN 0x00000004U /* perform child checks */
#define DNS_ZONE_O_DIALUP 0x00000008U /* zone xfr over dialup link */
#define DNS_ZONE_O_NOTIFY 0x00000010U /* perform NOTIFY */
typedef struct dns_zone dns_zone_t;
ISC_LANG_BEGINDECLS
/***
*** Functions
***/
dns_result_t dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx);
/*
* Creates a new empty zone and attach to it.
*
* Requires:
* 'zonep' to point to a NULL pointer.
* 'mctx' to be a valid memory context.
*
* Ensures:
* '*zonep' refers to a valid zone.
*
* Returns:
* DNS_R_SUCCESS
* DNS_R_NOMEMORY
* DNS_R_UNEXPECTED
*/
void dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass);
/*
* Sets the class of a zone. This operation can only be performed
* once on a zone.
*
* Require:
* 'zone' to be a valid initalised zone.
* dns_zone_setclass() not to have been called since the zone was
* initalised.
* 'rdclass' != dns_rdataclass_none.
*/
void dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type);
/*
* Sets the zone type. This operation can only be performed once on
* a zone.
*
* Requires:
* 'zone' to be a valid initalised zone.
* dns_zone_settype() not to have been called since the zone was
* initalised.
* 'type' != dns_zone_none
*/
dns_result_t dns_zone_setorigin(dns_zone_t *zone, char *origin);
/*
* Sets the zones origin to 'origin'.
*
* Require:
* 'zone' to be a valid initalised zone.
* 'origin' to be non NULL.
*
* Returns:
* All possible values from dns_name_fromtext().
*/
dns_result_t dns_zone_setdatabase(dns_zone_t *zone, const char *database);
/*
* Sets the name of the database to be loaded.
* For databases loaded from MASTER files this corresponds to the
* file name of the MASTER file.
*
* Require:
* 'zone' to be a valid initalised zone.
* 'database' to be non NULL.
*
* Returns:
* DNS_R_NOMEMORY
* DNS_R_SUCCESS
*/
dns_result_t dns_zone_setixfrlog(dns_zone_t *zone, const char *ixfrlog);
/*
* Sets the name of the IXFR log file.
*
* Require:
* 'zone' to be a valid initalised zone.
* 'ixfrlog' to be non NULL.
*
* Returns:
* DNS_R_NOMEMORY
* DNS_R_SUCCESS
*/
dns_result_t dns_zone_setupdatelog(dns_zone_t *zone, char *updatelog);
/*
* Sets the name of the UPDATE log file.
*
* Require:
* 'zone' to be a valid initalised zone.
* 'updatelog' to be non NULL.
*
* Returns:
* DNS_R_NOMEMORY
* DNS_R_SUCCESS
*/
dns_result_t dns_zone_load(dns_zone_t *zone);
/*
* Cause the database to be loaded from its backing store.
* Confirm that the mimimum requirements for the zone type are
* met, otherwise DNS_R_BADZONE is return.
*
* Require:
* 'zone' to be a valid initalised zone.
*
* Returns:
* DNS_R_UNEXPECTED
* DNS_R_SUCCESS
* DNS_R_BADZONE
* Any result value from dns_db_load().
*/
void dns_zone_checkservers(dns_zone_t *zone);
/*
* Initiate a consistancy check of the zones servers.
* XXX MPA to be implemented.
*
* Require:
* 'zone' to be a valid initalised zone.
*/
void dns_zone_checkparents(dns_zone_t *zone);
/*
* Initiate a consistancy check of the zone and the parent zone servers.
* XXX MPA to be implemented.
*
* Require:
* 'zone' to be a valid initalised zone.
*/
void dns_zone_checkchildren(dns_zone_t *zone);
/*
* Initiate a consistancy check of the child delegations from this zone.
* XXX MPA to be implemented.
*
* Require:
* 'zone' to be a valid initalised zone.
*/
void dns_zone_checkglue(dns_zone_t *zone);
/*
* Initiate a consistancy check of the glue records in this zone.
* XXX MPA to be implemented.
*
* Require:
* 'zone' to be a valid initalised zone.
*/
void dns_zone_attach(dns_zone_t *source, dns_zone_t **target);
/*
* Attach 'zone' to 'target'. Increment reference count.
*
* Require:
* 'zone' to be a valid initalised zone.
* 'target' to be non NULL and '*target' to be NULL.
*/
void dns_zone_detach(dns_zone_t **zonep);
/*
* Detach the current zone. If this is the last reference to the
* zone it will be destroyed.
*
* Require:
* 'zonep' to point to a valid initalised zone.
*/
void dns_zone_setflag(dns_zone_t *zone, unsigned int flags,
isc_boolean_t value);
/*
* Sets ('value' == 'ISC_TRUE') / clears ('value' == 'IS_FALSE')
* zone flags. Valid flag bits are DNS_ZONE_F_*.
*
* Requires
* 'zone' to be a valid initalised zone.
*/
dns_result_t dns_zone_adddbarg(dns_zone_t *zone, char *arg);
/*
* Add 'arg' to the end of the list of database arguements.
* No attempt in made to validate the arguements.
*
* Require:
* 'zone' to be a valid initalised zone.
* 'arg' to be non NULL.
*
* Returns:
* DNS_R_NOMEMORY
* DNS_R_SUCCESS
*/
void dns_zone_cleardbargs(dns_zone_t *zone);
/*
* Clear all database arguements.
*
* Require:
* 'zone' to be a valid initalised zone.
*/
dns_db_t * dns_zone_getdb(dns_zone_t *zone);
/*
* Return a pointer to the database.
*
* Require:
* 'zone' to be a valid initalised zone.
*
* Returns:
* A pointer to a database structure or NULL.
*/
dns_result_t dns_zone_setdbtype(dns_zone_t *zone, char *db_type);
/*
* Sets the database type. Current database types are: "rbt", "rbt64".
* 'db_type' is not checked to see if it is a valid database type.
*
* Require:
* 'zone' to be a valid initalised zone.
* 'database' to be non NULL.
*
* Returns:
* DNS_R_NOMEMORY
* DNS_R_SUCCESS
*/
void dns_zone_validate(dns_zone_t *zone);
/* XXX MPA */
void dns_zone_expire(dns_zone_t *zone);
/*
* Mark the zone as expired. If the zone requires dumping cause it to
* be initiated. Set the refresh and retry intervals to there default
* values and unload the zone.
*
* Require
* 'zone' to be a valid initalised zone.
*/
void dns_zone_refresh(dns_zone_t *zone);
/*
* Initiate zone up to date checks. The zone must already be being
* managed.
*
* Require
* 'zone' to be a valid initalised zone.
*/
dns_result_t dns_zone_dump(dns_zone_t *zone, FILE *fd);
/*
* Write the zone to 'fd' in MASTER file format.
*
* Require:
* 'zone' to be a valid initalised zone.
* 'fd' to be an active file handle open for writing.
*/
void dns_zone_maintenance(dns_zone_t *zone);
/*
* Perform regular maintenace on the zone. This is called as a
* result of a zone being managed.
*
* Require
* 'zone' to be a valid initalised zone.
*/
void dns_zone_clearmasters(dns_zone_t *zone);
/*
* Clear the set of master servers the zone transfers from.
*
* Require
* 'zone' to be a valid initalised zone.
*/
dns_result_t dns_zone_addmaster(dns_zone_t *zone, isc_sockaddr_t *master);
/*
* Add a master server to the end of the set of master servers for
* the zone.
*
* Require:
* 'zone' to be a valid initalised zone.
* 'master' to be non NULL.
*
* Returns:
* DNS_R_SUCCESS
* DNS_R_NOMEMORY
*/
void dns_zone_clearnotify(dns_zone_t *zone);
/*
* Clear the set of additional servers to be notified when the zone
* changes.
*
* Require:
* 'zone' to be a valid initalised zone.
*/
dns_result_t dns_zone_addnotify(dns_zone_t *zone, isc_sockaddr_t *notify);
/*
* Add a server to the end of the list of additional servers to be
* notified when a zone changes.
*
* Require:
* 'zone' to be a valid initalised zone.
* 'notify' to be non NULL.
*
* Returns:
* DNS_R_SUCCESS
* DNS_R_NOMEMORY
*/
void dns_zone_unmount(dns_zone_t *zone);
/* XXX MPA */
void dns_zone_unload(dns_zone_t *zone);
/*
* detach the database from the zone structure.
*
* Require:
* 'zone' to be a valid initalised zone.
*/
dns_result_t dns_zone_manage(dns_zone_t *zone, isc_taskmgr_t *tmgr);