summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/lib/dns/master.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/lib/dns/master.c')
-rw-r--r--contrib/bind9/lib/dns/master.c566
1 files changed, 513 insertions, 53 deletions
diff --git a/contrib/bind9/lib/dns/master.c b/contrib/bind9/lib/dns/master.c
index 7a2dab3..8eb1f2d 100644
--- a/contrib/bind9/lib/dns/master.c
+++ b/contrib/bind9/lib/dns/master.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
@@ -15,7 +15,9 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: master.c,v 1.122.2.8.2.14 2004/05/05 01:32:16 marka Exp $ */
+/* $Id: master.c,v 1.148.18.13 2006/12/07 23:57:58 marka Exp $ */
+
+/*! \file */
#include <config.h>
@@ -25,6 +27,7 @@
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/serial.h>
+#include <isc/stdio.h>
#include <isc/stdtime.h>
#include <isc/string.h>
#include <isc/task.h>
@@ -46,33 +49,34 @@
#include <dns/time.h>
#include <dns/ttl.h>
-/*
- * Grow the number of dns_rdatalist_t (RDLSZ) and dns_rdata_t (RDSZ) structures
+/*!
+ * Grow the number of dns_rdatalist_t (#RDLSZ) and dns_rdata_t (#RDSZ) structures
* by these sizes when we need to.
*
- * RDLSZ reflects the number of different types with the same name expected.
+ */
+/*% RDLSZ reflects the number of different types with the same name expected. */
+#define RDLSZ 32
+/*%
* RDSZ reflects the number of rdata expected at a give name that can fit into
* 64k.
*/
-
-#define RDLSZ 32
#define RDSZ 512
#define NBUFS 4
#define MAXWIRESZ 255
-/*
+/*%
* Target buffer size and minimum target size.
* MINTSIZ must be big enough to hold the largest rdata record.
- *
+ * \brief
* TSIZ >= MINTSIZ
*/
#define TSIZ (128*1024)
-/*
+/*%
* max message size - header - root - type - class - ttl - rdlen
*/
#define MINTSIZ (65535 - 12 - 1 - 2 - 2 - 4 - 2)
-/*
+/*%
* Size for tokens in the presentation format,
* The largest tokens are the base64 blocks in KEY and CERT records,
* Largest key allowed is about 1372 bytes but
@@ -87,19 +91,28 @@ typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
typedef struct dns_incctx dns_incctx_t;
-/*
+/*%
* Master file load state.
*/
struct dns_loadctx {
unsigned int magic;
isc_mem_t *mctx;
- isc_lex_t *lex;
- isc_boolean_t keep_lex;
+ dns_masterformat_t format;
+
dns_rdatacallbacks_t *callbacks;
isc_task_t *task;
dns_loaddonefunc_t done;
void *done_arg;
+
+ /* Common methods */
+ isc_result_t (*openfile)(dns_loadctx_t *lctx,
+ const char *filename);
+ isc_result_t (*load)(dns_loadctx_t *lctx);
+
+ /* Members specific to the text format: */
+ isc_lex_t *lex;
+ isc_boolean_t keep_lex;
unsigned int options;
isc_boolean_t ttl_known;
isc_boolean_t default_ttl_known;
@@ -111,9 +124,14 @@ struct dns_loadctx {
isc_uint32_t default_ttl;
dns_rdataclass_t zclass;
dns_fixedname_t fixed_top;
- dns_name_t *top; /* top of zone */
+ dns_name_t *top; /*%< top of zone */
+
+ /* Members specific to the raw format: */
+ FILE *f;
+ isc_boolean_t first;
+
/* Which fixed buffers we are using? */
- unsigned int loop_cnt; /* records per quantum,
+ unsigned int loop_cnt; /*% records per quantum,
* 0 => all. */
isc_boolean_t canceled;
isc_mutex_t lock;
@@ -144,6 +162,18 @@ struct dns_incctx {
#define DNS_AS_STR(t) ((t).value.as_textregion.base)
static isc_result_t
+openfile_text(dns_loadctx_t *lctx, const char *master_file);
+
+static isc_result_t
+openfile_raw(dns_loadctx_t *lctx, const char *master_file);
+
+static isc_result_t
+load_text(dns_loadctx_t *lctx);
+
+static isc_result_t
+load_raw(dns_loadctx_t *lctx);
+
+static isc_result_t
pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx);
static isc_result_t
@@ -405,6 +435,7 @@ incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
static void
loadctx_destroy(dns_loadctx_t *lctx) {
isc_mem_t *mctx;
+ isc_result_t result;
REQUIRE(DNS_LCTX_VALID(lctx));
@@ -412,6 +443,15 @@ loadctx_destroy(dns_loadctx_t *lctx) {
if (lctx->inc != NULL)
incctx_destroy(lctx->mctx, lctx->inc);
+ if (lctx->f != NULL) {
+ result = isc_stdio_close(lctx->f);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_stdio_close() failed: %s",
+ isc_result_totext(result));
+ }
+ }
+
/* isc_lex_destroy() will close all open streams */
if (lctx->lex != NULL && !lctx->keep_lex)
isc_lex_destroy(&lctx->lex);
@@ -461,7 +501,8 @@ incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
}
static isc_result_t
-loadctx_create(isc_mem_t *mctx, unsigned int options, dns_name_t *top,
+loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
+ unsigned int options, dns_name_t *top,
dns_rdataclass_t zclass, dns_name_t *origin,
dns_rdatacallbacks_t *callbacks, isc_task_t *task,
dns_loaddonefunc_t done, void *done_arg, isc_lex_t *lex,
@@ -489,10 +530,7 @@ loadctx_create(isc_mem_t *mctx, unsigned int options, dns_name_t *top,
result = isc_mutex_init(&lctx->lock);
if (result != ISC_R_SUCCESS) {
isc_mem_put(mctx, lctx, sizeof(*lctx));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "isc_mutex_init() failed: %s",
- isc_result_totext(result));
- return (ISC_R_UNEXPECTED);
+ return (result);
}
lctx->inc = NULL;
@@ -500,6 +538,20 @@ loadctx_create(isc_mem_t *mctx, unsigned int options, dns_name_t *top,
if (result != ISC_R_SUCCESS)
goto cleanup_ctx;
+ lctx->format = format;
+ switch (format) {
+ default:
+ INSIST(0);
+ case dns_masterformat_text:
+ lctx->openfile = openfile_text;
+ lctx->load = load_text;
+ break;
+ case dns_masterformat_raw:
+ lctx->openfile = openfile_raw;
+ lctx->load = load_raw;
+ break;
+ }
+
if (lex != NULL) {
lctx->lex = lex;
lctx->keep_lex = ISC_TRUE;
@@ -534,6 +586,9 @@ loadctx_create(isc_mem_t *mctx, unsigned int options, dns_name_t *top,
dns_name_toregion(top, &r);
dns_name_fromregion(lctx->top, &r);
+ lctx->f = NULL;
+ lctx->first = ISC_TRUE;
+
lctx->loop_cnt = (done != NULL) ? 100 : 0;
lctx->callbacks = callbacks;
lctx->task = NULL;
@@ -640,6 +695,25 @@ genname(char *name, int it, char *buffer, size_t length) {
}
static isc_result_t
+openfile_text(dns_loadctx_t *lctx, const char *master_file) {
+ return (isc_lex_openfile(lctx->lex, master_file));
+}
+
+static isc_result_t
+openfile_raw(dns_loadctx_t *lctx, const char *master_file) {
+ isc_result_t result;
+
+ result = isc_stdio_open(master_file, "r", &lctx->f);
+ if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_stdio_open() failed: %s",
+ isc_result_totext(result));
+ }
+
+ return (result);
+}
+
+static isc_result_t
generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
const char *source, unsigned int line)
{
@@ -711,6 +785,7 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
case dns_rdatatype_a:
case dns_rdatatype_aaaa:
if (lctx->zclass == dns_rdataclass_in ||
+ lctx->zclass == dns_rdataclass_ch ||
lctx->zclass == dns_rdataclass_hs)
break;
/* FALLTHROUGH */
@@ -862,8 +937,25 @@ check_ns(dns_loadctx_t *lctx, isc_token_t *token, const char *source,
return (result);
}
+static void
+check_wildcard(dns_incctx_t *ictx, const char *source, unsigned long line,
+ dns_rdatacallbacks_t *callbacks)
+{
+ dns_name_t *name;
+
+ name = (ictx->glue != NULL) ? ictx->glue : ictx->current;
+ if (dns_name_internalwildcard(name)) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ (*callbacks->warn)(callbacks, "%s:%lu: warning: ownername "
+ "'%s' contains an non-terminal wildcard",
+ source, line, namebuf);
+ }
+}
+
static isc_result_t
-load(dns_loadctx_t *lctx) {
+load_text(dns_loadctx_t *lctx) {
dns_rdataclass_t rdclass;
dns_rdatatype_t type, covers;
isc_uint32_t ttl_offset = 0;
@@ -939,11 +1031,16 @@ load(dns_loadctx_t *lctx) {
options |= DNS_RDATA_CHECKNAMES;
if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0)
options |= DNS_RDATA_CHECKNAMESFAIL;
+ if ((lctx->options & DNS_MASTER_CHECKMX) != 0)
+ options |= DNS_RDATA_CHECKMX;
+ if ((lctx->options & DNS_MASTER_CHECKMXFAIL) != 0)
+ options |= DNS_RDATA_CHECKMXFAIL;
source = isc_lex_getsourcename(lctx->lex);
do {
initialws = ISC_FALSE;
line = isc_lex_getsourceline(lctx->lex);
- GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS, &token, ISC_TRUE);
+ GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS | ISC_LEXOPT_QSTRING,
+ &token, ISC_TRUE);
line = isc_lex_getsourceline(lctx->lex);
if (token.type == isc_tokentype_eof) {
@@ -979,7 +1076,8 @@ load(dns_loadctx_t *lctx) {
* Still working on the same name.
*/
initialws = ISC_TRUE;
- } else if (token.type == isc_tokentype_string) {
+ } else if (token.type == isc_tokentype_string ||
+ token.type == isc_tokentype_qstring) {
/*
* "$" Support.
@@ -1117,6 +1215,7 @@ load(dns_loadctx_t *lctx) {
isc_mem_free(mctx, gtype);
if (rhs != NULL)
isc_mem_free(mctx, rhs);
+ range = lhs = gtype = rhs = NULL;
/* RANGE */
GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
range = isc_mem_strdup(mctx,
@@ -1346,6 +1445,14 @@ load(dns_loadctx_t *lctx) {
isc_buffer_init(&target, target_mem,
target_size);
}
+ /*
+ * Check for internal wildcards.
+ */
+ if ((lctx->options & DNS_MASTER_CHECKWILDCARD)
+ != 0)
+ check_wildcard(ictx, source, line,
+ callbacks);
+
}
if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
(lctx->options & DNS_MASTER_SLAVE) == 0 &&
@@ -1508,7 +1615,7 @@ load(dns_loadctx_t *lctx) {
current_has_delegation = ISC_TRUE;
/*
- * RFC 1123: MD and MF are not allowed to be loaded from
+ * RFC1123: MD and MF are not allowed to be loaded from
* master files.
*/
if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
@@ -1571,7 +1678,7 @@ load(dns_loadctx_t *lctx) {
isc_boolean_t ok;
dns_name_t *name;
- name = (ictx->glue != NULL) ? ictx-> glue :
+ name = (ictx->glue != NULL) ? ictx->glue :
ictx->current;
ok = dns_rdata_checkowner(name, lctx->zclass, type,
ISC_TRUE);
@@ -1686,7 +1793,7 @@ load(dns_loadctx_t *lctx) {
} else if (!explicit_ttl && lctx->warn_1035) {
(*callbacks->warn)(callbacks,
"%s:%lu: "
- "using RFC 1035 TTL semantics",
+ "using RFC1035 TTL semantics",
source, line);
lctx->warn_1035 = ISC_FALSE;
}
@@ -1879,7 +1986,7 @@ pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) {
new->drop = ictx->drop;
}
- result = isc_lex_openfile(lctx->lex, master_file);
+ result = (lctx->openfile)(lctx, master_file);
if (result != ISC_R_SUCCESS)
goto cleanup;
new->parent = ictx;
@@ -1892,25 +1999,352 @@ pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) {
return (result);
}
+static inline isc_result_t
+read_and_check(isc_boolean_t do_read, isc_buffer_t *buffer,
+ size_t len, FILE *f)
+{
+ isc_result_t result;
+
+ if (do_read) {
+ INSIST(isc_buffer_availablelength(buffer) >= len);
+ result = isc_stdio_read(isc_buffer_used(buffer), 1, len,
+ f, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_add(buffer, len);
+ } else if (isc_buffer_remaininglength(buffer) < len)
+ return (ISC_R_RANGE);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+load_raw(dns_loadctx_t *lctx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_boolean_t done = ISC_FALSE;
+ unsigned int loop_cnt = 0;
+ dns_rdatacallbacks_t *callbacks;
+ unsigned char namebuf[DNS_NAME_MAXWIRE];
+ isc_region_t r;
+ dns_name_t name;
+ rdatalist_head_t head, dummy;
+ dns_rdatalist_t rdatalist;
+ isc_mem_t *mctx = lctx->mctx;
+ dns_rdata_t *rdata = NULL;
+ unsigned int rdata_size = 0;
+ int target_size = TSIZ;
+ isc_buffer_t target;
+ unsigned char *target_mem = NULL;
+
+ REQUIRE(DNS_LCTX_VALID(lctx));
+ callbacks = lctx->callbacks;
+
+ if (lctx->first) {
+ dns_masterrawheader_t header;
+ isc_uint32_t format, version, dumptime;
+ size_t hdrlen = sizeof(format) + sizeof(version) +
+ sizeof(dumptime);
+
+ INSIST(hdrlen <= sizeof(header));
+ isc_buffer_init(&target, &header, sizeof(header));
+
+ result = isc_stdio_read(&header, 1, hdrlen, lctx->f, NULL);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_stdio_read failed: %s",
+ isc_result_totext(result));
+ return (result);
+ }
+ isc_buffer_add(&target, hdrlen);
+ format = isc_buffer_getuint32(&target);
+ if (format != dns_masterformat_raw) {
+ (*callbacks->error)(callbacks,
+ "dns_master_load: "
+ "file format mismatch");
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ version = isc_buffer_getuint32(&target);
+ if (version > DNS_RAWFORMAT_VERSION) {
+ (*callbacks->error)(callbacks,
+ "dns_master_load: "
+ "unsupported file format version");
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ /* Empty read: currently, we do not use dumptime */
+ dumptime = isc_buffer_getuint32(&target);
+
+ lctx->first = ISC_FALSE;
+ }
+
+ ISC_LIST_INIT(head);
+ ISC_LIST_INIT(dummy);
+ dns_rdatalist_init(&rdatalist);
+
+ /*
+ * Allocate target_size of buffer space. This is greater than twice
+ * the maximum individual RR data size.
+ */
+ target_mem = isc_mem_get(mctx, target_size);
+ if (target_mem == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ isc_buffer_init(&target, target_mem, target_size);
+
+ /*
+ * In the following loop, we regard any error fatal regardless of
+ * whether "MANYERRORS" is set in the context option. This is because
+ * normal errors should already have been checked at creation time.
+ * Besides, it is very unlikely that we can recover from an error
+ * in this format, and so trying to continue parsing erroneous data
+ * does not really make sense.
+ */
+ for (loop_cnt = 0;
+ (lctx->loop_cnt == 0 || loop_cnt < lctx->loop_cnt);
+ loop_cnt++) {
+ unsigned int i, rdcount, consumed_name;
+ isc_uint16_t namelen;
+ isc_uint32_t totallen;
+ size_t minlen, readlen;
+ isc_boolean_t sequential_read = ISC_FALSE;
+
+ /* Read the data length */
+ isc_buffer_clear(&target);
+ INSIST(isc_buffer_availablelength(&target) >=
+ sizeof(totallen));
+ result = isc_stdio_read(target.base, 1, sizeof(totallen),
+ lctx->f, NULL);
+ if (result == ISC_R_EOF) {
+ result = ISC_R_SUCCESS;
+ done = ISC_TRUE;
+ break;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_buffer_add(&target, sizeof(totallen));
+ totallen = isc_buffer_getuint32(&target);
+ /*
+ * Validation: the input data must at least contain the common
+ * header.
+ */
+ minlen = sizeof(totallen) + sizeof(isc_uint16_t) +
+ sizeof(isc_uint16_t) + sizeof(isc_uint16_t) +
+ sizeof(isc_uint32_t) + sizeof(isc_uint32_t);
+ if (totallen < minlen) {
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+ totallen -= sizeof(totallen);
+
+ isc_buffer_clear(&target);
+ if (totallen > isc_buffer_availablelength(&target)) {
+ /*
+ * The default buffer size should typically be large
+ * enough to store the entire RRset. We could try to
+ * allocate enough space if this is not the case, but
+ * it might cause a hazardous result when "totallen"
+ * is forged. Thus, we'd rather take an inefficient
+ * but robust approach in this atypical case: read
+ * data step by step, and commit partial data when
+ * necessary. Note that the buffer must be large
+ * enough to store the "header part", owner name, and
+ * at least one rdata (however large it is).
+ */
+ sequential_read = ISC_TRUE;
+ readlen = minlen - sizeof(totallen);
+ } else {
+ /*
+ * Typical case. We can read the whole RRset at once
+ * with the default buffer.
+ */
+ readlen = totallen;
+ }
+ result = isc_stdio_read(target.base, 1, readlen,
+ lctx->f, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_buffer_add(&target, readlen);
+
+ /* Construct RRset headers */
+ rdatalist.rdclass = isc_buffer_getuint16(&target);
+ rdatalist.type = isc_buffer_getuint16(&target);
+ rdatalist.covers = isc_buffer_getuint16(&target);
+ rdatalist.ttl = isc_buffer_getuint32(&target);
+ rdcount = isc_buffer_getuint32(&target);
+ if (rdcount == 0) {
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+ INSIST(isc_buffer_consumedlength(&target) <= readlen);
+
+ /* Owner name: length followed by name */
+ result = read_and_check(sequential_read, &target,
+ sizeof(namelen), lctx->f);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ namelen = isc_buffer_getuint16(&target);
+ if (namelen > sizeof(namebuf)) {
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+
+ result = read_and_check(sequential_read, &target, namelen,
+ lctx->f);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_buffer_setactive(&target, (unsigned int)namelen);
+ isc_buffer_activeregion(&target, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ isc_buffer_forward(&target, (unsigned int)namelen);
+ consumed_name = isc_buffer_consumedlength(&target);
+
+ /* Rdata contents. */
+ if (rdcount > rdata_size) {
+ dns_rdata_t *new_rdata = NULL;
+
+ new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
+ rdata_size, &head,
+ &dummy, mctx);
+ if (new_rdata == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ rdata_size += RDSZ;
+ rdata = new_rdata;
+ }
+
+ continue_read:
+ for (i = 0; i < rdcount; i++) {
+ isc_uint16_t rdlen;
+
+ dns_rdata_init(&rdata[i]);
+
+ if (sequential_read &&
+ isc_buffer_availablelength(&target) < MINTSIZ) {
+ unsigned int j;
+
+ INSIST(i > 0); /* detect an infinite loop */
+
+ /* Partial Commit. */
+ ISC_LIST_APPEND(head, &rdatalist, link);
+ result = commit(callbacks, lctx, &head, &name,
+ NULL, 0);
+ for (j = 0; j < i; j++) {
+ ISC_LIST_UNLINK(rdatalist.rdata,
+ &rdata[j], link);
+ dns_rdata_reset(&rdata[j]);
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /* Rewind the buffer and continue */
+ isc_buffer_clear(&target);
+ isc_buffer_add(&target, consumed_name);
+ isc_buffer_forward(&target, consumed_name);
+
+ rdcount -= i;
+ i = 0;
+
+ goto continue_read;
+ }
+
+ /* rdata length */
+ result = read_and_check(sequential_read, &target,
+ sizeof(rdlen), lctx->f);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ rdlen = isc_buffer_getuint16(&target);
+
+ /* rdata */
+ result = read_and_check(sequential_read, &target,
+ rdlen, lctx->f);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_buffer_setactive(&target, (unsigned int)rdlen);
+ isc_buffer_activeregion(&target, &r);
+ isc_buffer_forward(&target, (unsigned int)rdlen);
+ dns_rdata_fromregion(&rdata[i], rdatalist.rdclass,
+ rdatalist.type, &r);
+
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link);
+ }
+
+ /*
+ * Sanity check. Still having remaining space is not
+ * necessarily critical, but it very likely indicates broken
+ * or malformed data.
+ */
+ if (isc_buffer_remaininglength(&target) != 0) {
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+
+ ISC_LIST_APPEND(head, &rdatalist, link);
+
+ /* Commit this RRset. rdatalist will be unlinked. */
+ result = commit(callbacks, lctx, &head, &name, NULL, 0);
+
+ for (i = 0; i < rdcount; i++) {
+ ISC_LIST_UNLINK(rdatalist.rdata, &rdata[i], link);
+ dns_rdata_reset(&rdata[i]);
+ }
+
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ if (!done) {
+ INSIST(lctx->done != NULL && lctx->task != NULL);
+ result = DNS_R_CONTINUE;
+ } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS)
+ result = lctx->result;
+
+ cleanup:
+ if (rdata != NULL)
+ isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
+ if (target_mem != NULL)
+ isc_mem_put(mctx, target_mem, target_size);
+ if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE) {
+ (*callbacks->error)(callbacks, "dns_master_load: %s",
+ dns_result_totext(result));
+ }
+
+ return (result);
+}
+
isc_result_t
dns_master_loadfile(const char *master_file, dns_name_t *top,
dns_name_t *origin,
dns_rdataclass_t zclass, unsigned int options,
dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
{
+ return (dns_master_loadfile2(master_file, top, origin, zclass, options,
+ callbacks, mctx, dns_masterformat_text));
+}
+
+isc_result_t
+dns_master_loadfile2(const char *master_file, dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass, unsigned int options,
+ dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
+ dns_masterformat_t format)
+{
dns_loadctx_t *lctx = NULL;
isc_result_t result;
- result = loadctx_create(mctx, options, top, zclass, origin,
+ result = loadctx_create(format, mctx, options, top, zclass, origin,
callbacks, NULL, NULL, NULL, NULL, &lctx);
if (result != ISC_R_SUCCESS)
return (result);
- result = isc_lex_openfile(lctx->lex, master_file);
+ result = (lctx->openfile)(lctx, master_file);
if (result != ISC_R_SUCCESS)
goto cleanup;
- result = load(lctx);
+ result = (lctx->load)(lctx);
INSIST(result != DNS_R_CONTINUE);
cleanup:
@@ -1926,18 +2360,32 @@ dns_master_loadfileinc(const char *master_file, dns_name_t *top,
isc_task_t *task, dns_loaddonefunc_t done,
void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx)
{
+ return (dns_master_loadfileinc2(master_file, top, origin, zclass,
+ options, callbacks, task, done,
+ done_arg, lctxp, mctx,
+ dns_masterformat_text));
+}
+
+isc_result_t
+dns_master_loadfileinc2(const char *master_file, dns_name_t *top,
+ dns_name_t *origin, dns_rdataclass_t zclass,
+ unsigned int options, dns_rdatacallbacks_t *callbacks,
+ isc_task_t *task, dns_loaddonefunc_t done,
+ void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx,
+ dns_masterformat_t format)
+{
dns_loadctx_t *lctx = NULL;
isc_result_t result;
-
+
REQUIRE(task != NULL);
REQUIRE(done != NULL);
- result = loadctx_create(mctx, options, top, zclass, origin,
+ result = loadctx_create(format, mctx, options, top, zclass, origin,
callbacks, task, done, done_arg, NULL, &lctx);
if (result != ISC_R_SUCCESS)
return (result);
- result = isc_lex_openfile(lctx->lex, master_file);
+ result = (lctx->openfile)(lctx, master_file);
if (result != ISC_R_SUCCESS)
goto cleanup;
@@ -1963,8 +2411,9 @@ dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
REQUIRE(stream != NULL);
- result = loadctx_create(mctx, options, top, zclass, origin,
- callbacks, NULL, NULL, NULL, NULL, &lctx);
+ result = loadctx_create(dns_masterformat_text, mctx, options, top,
+ zclass, origin, callbacks, NULL, NULL, NULL,
+ NULL, &lctx);
if (result != ISC_R_SUCCESS)
goto cleanup;
@@ -1972,7 +2421,7 @@ dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
if (result != ISC_R_SUCCESS)
goto cleanup;
- result = load(lctx);
+ result = (lctx->load)(lctx);
INSIST(result != DNS_R_CONTINUE);
cleanup:
@@ -1995,8 +2444,9 @@ dns_master_loadstreaminc(FILE *stream, dns_name_t *top, dns_name_t *origin,
REQUIRE(task != NULL);
REQUIRE(done != NULL);
- result = loadctx_create(mctx, options, top, zclass, origin,
- callbacks, task, done, done_arg, NULL, &lctx);
+ result = loadctx_create(dns_masterformat_text, mctx, options, top,
+ zclass, origin, callbacks, task, done,
+ done_arg, NULL, &lctx);
if (result != ISC_R_SUCCESS)
goto cleanup;
@@ -2027,8 +2477,9 @@ dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top,
REQUIRE(buffer != NULL);
- result = loadctx_create(mctx, options, top, zclass, origin,
- callbacks, NULL, NULL, NULL, NULL, &lctx);
+ result = loadctx_create(dns_masterformat_text, mctx, options, top,
+ zclass, origin, callbacks, NULL, NULL, NULL,
+ NULL, &lctx);
if (result != ISC_R_SUCCESS)
return (result);
@@ -2036,7 +2487,7 @@ dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top,
if (result != ISC_R_SUCCESS)
goto cleanup;
- result = load(lctx);
+ result = (lctx->load)(lctx);
INSIST(result != DNS_R_CONTINUE);
cleanup:
@@ -2060,8 +2511,9 @@ dns_master_loadbufferinc(isc_buffer_t *buffer, dns_name_t *top,
REQUIRE(task != NULL);
REQUIRE(done != NULL);
- result = loadctx_create(mctx, options, top, zclass, origin,
- callbacks, task, done, done_arg, NULL, &lctx);
+ result = loadctx_create(dns_masterformat_text, mctx, options, top,
+ zclass, origin, callbacks, task, done,
+ done_arg, NULL, &lctx);
if (result != ISC_R_SUCCESS)
return (result);
@@ -2092,12 +2544,13 @@ dns_master_loadlexer(isc_lex_t *lex, dns_name_t *top,
REQUIRE(lex != NULL);
- result = loadctx_create(mctx, options, top, zclass, origin,
- callbacks, NULL, NULL, NULL, lex, &lctx);
+ result = loadctx_create(dns_masterformat_text, mctx, options, top,
+ zclass, origin, callbacks, NULL, NULL, NULL,
+ lex, &lctx);
if (result != ISC_R_SUCCESS)
return (result);
- result = load(lctx);
+ result = (lctx->load)(lctx);
INSIST(result != DNS_R_CONTINUE);
dns_loadctx_detach(&lctx);
@@ -2119,8 +2572,9 @@ dns_master_loadlexerinc(isc_lex_t *lex, dns_name_t *top,
REQUIRE(task != NULL);
REQUIRE(done != NULL);
- result = loadctx_create(mctx, options, top, zclass, origin,
- callbacks, task, done, done_arg, lex, &lctx);
+ result = loadctx_create(dns_masterformat_text, mctx, options, top,
+ zclass, origin, callbacks, task, done,
+ done_arg, lex, &lctx);
if (result != ISC_R_SUCCESS)
return (result);
@@ -2281,9 +2735,15 @@ commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
} else if (result != ISC_R_SUCCESS) {
dns_name_format(owner, namebuf,
sizeof(namebuf));
- (*error)(callbacks, "%s: %s:%lu: %s: %s",
- "dns_master_load", source, line,
- namebuf, dns_result_totext(result));
+ if (source != NULL) {
+ (*error)(callbacks, "%s: %s:%lu: %s: %s",
+ "dns_master_load", source, line,
+ namebuf, dns_result_totext(result));
+ } else {
+ (*error)(callbacks, "%s: %s: %s",
+ "dns_master_load", namebuf,
+ dns_result_totext(result));
+ }
}
if (MANYERRS(lctx, result))
SETRESULT(lctx, result);
@@ -2342,7 +2802,7 @@ load_quantum(isc_task_t *task, isc_event_t *event) {
if (lctx->canceled)
result = ISC_R_CANCELED;
else
- result = load(lctx);
+ result = (lctx->load)(lctx);
if (result == DNS_R_CONTINUE) {
event->ev_arg = lctx;
isc_task_send(task, &event);
OpenPOWER on IntegriCloud