1999-01-28 05:03:25 +00:00
|
|
|
/*
|
1999-03-06 04:12:06 +00:00
|
|
|
* Copyright (C) 1999 Internet Software Consortium.
|
1999-01-28 05:03:25 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
/* $Id: master.c,v 1.34 1999/12/23 00:08:29 explorer Exp $ */
|
1999-01-28 05:03:25 +00:00
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
1999-01-27 13:38:21 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
1999-03-22 06:21:29 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <limits.h>
|
1999-06-08 10:35:23 +00:00
|
|
|
#include <time.h>
|
1999-01-27 13:38:21 +00:00
|
|
|
|
|
|
|
#include <isc/lex.h>
|
|
|
|
#include <isc/list.h>
|
|
|
|
#include <isc/mem.h>
|
|
|
|
#include <isc/assertions.h>
|
1999-02-10 05:25:37 +00:00
|
|
|
#include <isc/error.h>
|
1999-06-08 10:35:23 +00:00
|
|
|
#include <isc/stdtime.h>
|
1999-01-27 13:38:21 +00:00
|
|
|
|
|
|
|
#include <dns/master.h>
|
|
|
|
#include <dns/types.h>
|
|
|
|
#include <dns/result.h>
|
|
|
|
#include <dns/rdatalist.h>
|
|
|
|
#include <dns/rdataset.h>
|
|
|
|
#include <dns/rdataclass.h>
|
|
|
|
#include <dns/rdatatype.h>
|
|
|
|
#include <dns/rdata.h>
|
1999-06-08 10:35:23 +00:00
|
|
|
#include <dns/time.h>
|
1999-11-02 13:07:53 +00:00
|
|
|
#include <dns/ttl.h>
|
1999-01-27 13:38:21 +00:00
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
* RDSZ reflects the number of rdata expected at a give name that can fit into
|
|
|
|
* 64k.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define RDLSZ 32
|
|
|
|
#define RDSZ 512
|
|
|
|
|
1999-03-23 00:04:01 +00:00
|
|
|
#define NBUFS 4
|
1999-03-22 06:21:29 +00:00
|
|
|
#define MAXWIRESZ 255
|
|
|
|
|
|
|
|
/*
|
1999-03-24 00:29:54 +00:00
|
|
|
* Target buffer size and minimum target size.
|
1999-03-22 06:21:29 +00:00
|
|
|
* MINTSIZ must be big enougth to hold the largest rdata record.
|
|
|
|
*
|
|
|
|
* TSIZ >= MINTSIZ
|
|
|
|
*/
|
|
|
|
#define TSIZ (128*1024)
|
|
|
|
/*
|
|
|
|
* max message size - header - root - type - class - ttl - rdlen
|
|
|
|
*/
|
|
|
|
#define MINTSIZ (65535 - 12 - 1 - 2 - 2 - 4 - 2)
|
1999-10-26 18:05:23 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
* there is no fixed upper bound on Cert records
|
|
|
|
* 2K is too small for some X.509's 8K is an overkill
|
|
|
|
*/
|
|
|
|
#define TOKENSIZ (8*1024)
|
1999-03-22 06:21:29 +00:00
|
|
|
|
1999-01-27 13:38:21 +00:00
|
|
|
typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t commit(dns_rdatacallbacks_t *, rdatalist_head_t *,
|
1999-02-09 08:02:21 +00:00
|
|
|
dns_name_t *);
|
1999-01-27 13:38:21 +00:00
|
|
|
static isc_boolean_t is_glue(rdatalist_head_t *, dns_name_t *);
|
|
|
|
static dns_rdatalist_t *grow_rdatalist(int, dns_rdatalist_t *, int,
|
|
|
|
rdatalist_head_t *,
|
|
|
|
rdatalist_head_t *,
|
|
|
|
isc_mem_t *mctx);
|
|
|
|
static dns_rdata_t *grow_rdata(int, dns_rdata_t *, int,
|
|
|
|
rdatalist_head_t *, rdatalist_head_t *,
|
|
|
|
isc_mem_t *);
|
1999-03-22 06:21:29 +00:00
|
|
|
static isc_boolean_t on_list(dns_rdatalist_t *this, dns_rdata_t *rdata);
|
1999-01-27 13:38:21 +00:00
|
|
|
|
1999-01-28 05:03:25 +00:00
|
|
|
#define GETTOKEN(lexer, options, token, eol) \
|
|
|
|
do { \
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t isc_r; \
|
1999-08-05 22:10:23 +00:00
|
|
|
isc_r = gettoken(lexer, options, token, eol, callbacks); \
|
1999-03-23 00:04:01 +00:00
|
|
|
switch (isc_r) { \
|
|
|
|
case DNS_R_SUCCESS: \
|
|
|
|
break; \
|
|
|
|
case DNS_R_UNEXPECTED: \
|
|
|
|
goto cleanup; \
|
|
|
|
default: \
|
1999-02-10 05:25:37 +00:00
|
|
|
goto error_cleanup; \
|
1999-01-28 05:03:25 +00:00
|
|
|
} \
|
1999-03-23 00:04:01 +00:00
|
|
|
} while (0) \
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static inline isc_result_t
|
1999-03-23 00:04:01 +00:00
|
|
|
gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token,
|
1999-08-05 22:10:23 +00:00
|
|
|
isc_boolean_t eol, dns_rdatacallbacks_t *callbacks)
|
1999-03-23 00:04:01 +00:00
|
|
|
{
|
|
|
|
isc_result_t result;
|
|
|
|
|
1999-06-09 11:56:45 +00:00
|
|
|
options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE |
|
|
|
|
ISC_LEXOPT_ESCAPE;
|
1999-03-23 00:04:01 +00:00
|
|
|
result = isc_lex_gettoken(lex, options, token);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
switch (result) {
|
|
|
|
case ISC_R_NOMEMORY:
|
|
|
|
return (DNS_R_NOMEMORY);
|
|
|
|
default:
|
|
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
|
|
"isc_lex_gettoken() failed: %s\n",
|
|
|
|
isc_result_totext(result));
|
|
|
|
return (DNS_R_UNEXPECTED);
|
|
|
|
}
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
if (eol != ISC_TRUE)
|
|
|
|
if (token->type == isc_tokentype_eol ||
|
|
|
|
token->type == isc_tokentype_eof) {
|
|
|
|
(*callbacks->error)(callbacks,
|
1999-10-25 18:41:36 +00:00
|
|
|
"dns_master_load: %s:%d unexpected end of %s\n",
|
1999-08-05 22:10:23 +00:00
|
|
|
isc_lex_getsourcename(lex),
|
|
|
|
isc_lex_getsourceline(lex),
|
1999-10-25 18:41:36 +00:00
|
|
|
(token->type ==
|
|
|
|
isc_tokentype_eol) ?
|
1999-08-05 22:10:23 +00:00
|
|
|
"line" : "file");
|
1999-03-23 00:04:01 +00:00
|
|
|
return (DNS_R_UNEXPECTEDEND);
|
|
|
|
}
|
|
|
|
return (DNS_R_SUCCESS);
|
|
|
|
}
|
1999-01-28 05:03:25 +00:00
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
1999-08-05 22:10:23 +00:00
|
|
|
load(isc_lex_t *lex, dns_name_t *top, dns_name_t *origin,
|
|
|
|
dns_rdataclass_t zclass, isc_boolean_t age_ttl,
|
|
|
|
int *soacount, int *nscount, dns_rdatacallbacks_t *callbacks,
|
|
|
|
isc_mem_t *mctx)
|
1999-01-27 13:38:21 +00:00
|
|
|
{
|
1999-03-04 02:48:47 +00:00
|
|
|
dns_rdataclass_t rdclass;
|
1999-08-31 22:14:06 +00:00
|
|
|
dns_rdatatype_t type, covers;
|
1999-02-10 05:25:37 +00:00
|
|
|
isc_uint32_t ttl = 0;
|
|
|
|
isc_uint32_t default_ttl = 0;
|
1999-06-08 10:35:23 +00:00
|
|
|
isc_uint32_t ttl_offset = 0;
|
1999-01-27 13:38:21 +00:00
|
|
|
dns_name_t current_name;
|
|
|
|
dns_name_t glue_name;
|
|
|
|
dns_name_t new_name;
|
1999-01-28 05:03:25 +00:00
|
|
|
dns_name_t origin_name = *origin;
|
1999-01-27 13:38:21 +00:00
|
|
|
isc_boolean_t ttl_known = ISC_FALSE;
|
1999-01-28 01:16:59 +00:00
|
|
|
isc_boolean_t default_ttl_known = ISC_FALSE;
|
1999-01-27 13:38:21 +00:00
|
|
|
isc_boolean_t current_known = ISC_FALSE;
|
|
|
|
isc_boolean_t in_glue = ISC_FALSE;
|
|
|
|
isc_boolean_t current_has_delegation = ISC_FALSE;
|
|
|
|
isc_boolean_t done = ISC_FALSE;
|
1999-01-27 23:57:46 +00:00
|
|
|
isc_boolean_t finish_origin = ISC_FALSE;
|
1999-01-28 01:16:59 +00:00
|
|
|
isc_boolean_t finish_include = ISC_FALSE;
|
1999-01-28 05:03:25 +00:00
|
|
|
isc_boolean_t read_till_eol = ISC_FALSE;
|
1999-03-22 06:21:29 +00:00
|
|
|
isc_boolean_t warn_1035 = ISC_TRUE; /* XXX Arguement? */
|
1999-01-28 01:16:59 +00:00
|
|
|
char *include_file = NULL;
|
1999-01-27 13:38:21 +00:00
|
|
|
isc_token_t token;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result = DNS_R_UNEXPECTED;
|
1999-01-27 13:38:21 +00:00
|
|
|
rdatalist_head_t glue_list;
|
|
|
|
rdatalist_head_t current_list;
|
|
|
|
dns_rdatalist_t *this;
|
|
|
|
dns_rdatalist_t *rdatalist = NULL;
|
|
|
|
dns_rdatalist_t *new_rdatalist;
|
|
|
|
int rdlcount = 0;
|
|
|
|
int rdlcount_save = 0;
|
|
|
|
int rdatalist_size = 0;
|
|
|
|
isc_buffer_t buffer;
|
|
|
|
isc_buffer_t target;
|
|
|
|
isc_buffer_t target_save;
|
|
|
|
dns_rdata_t *rdata = NULL;
|
|
|
|
dns_rdata_t *new_rdata;
|
|
|
|
int rdcount = 0;
|
|
|
|
int rdcount_save = 0;
|
|
|
|
int rdata_size = 0;
|
|
|
|
unsigned char *target_mem = NULL;
|
1999-03-22 06:21:29 +00:00
|
|
|
int target_size = TSIZ;
|
|
|
|
unsigned char name_buf[NBUFS][MAXWIRESZ];
|
|
|
|
isc_boolean_t name_in_use[NBUFS];
|
1999-01-27 23:17:57 +00:00
|
|
|
int glue_in_use = -1;
|
|
|
|
int current_in_use = -1;
|
1999-01-27 23:57:46 +00:00
|
|
|
int origin_in_use = -1;
|
1999-01-27 23:17:57 +00:00
|
|
|
int new_in_use;
|
|
|
|
isc_buffer_t name;
|
|
|
|
isc_lexspecials_t specials;
|
1999-01-27 13:38:21 +00:00
|
|
|
|
1999-08-05 22:10:23 +00:00
|
|
|
REQUIRE(lex != NULL);
|
1999-03-23 00:04:01 +00:00
|
|
|
REQUIRE(dns_name_isabsolute(top));
|
|
|
|
REQUIRE(dns_name_isabsolute(origin));
|
1999-02-10 05:25:37 +00:00
|
|
|
REQUIRE(callbacks != NULL);
|
1999-07-30 23:33:15 +00:00
|
|
|
REQUIRE(callbacks->add != NULL);
|
1999-02-10 05:25:37 +00:00
|
|
|
REQUIRE(callbacks->error != NULL);
|
|
|
|
REQUIRE(callbacks->warn != NULL);
|
|
|
|
REQUIRE(nscount != NULL);
|
|
|
|
REQUIRE(soacount != NULL);
|
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
|
1999-01-27 13:38:21 +00:00
|
|
|
dns_name_init(¤t_name, NULL);
|
|
|
|
dns_name_init(&glue_name, NULL);
|
|
|
|
|
|
|
|
ISC_LIST_INIT(glue_list);
|
|
|
|
ISC_LIST_INIT(current_list);
|
|
|
|
|
1999-01-27 23:17:57 +00:00
|
|
|
memset(specials, 0, sizeof specials);
|
|
|
|
specials['('] = 1;
|
|
|
|
specials[')'] = 1;
|
|
|
|
specials['"'] = 1;
|
|
|
|
isc_lex_setspecials(lex, specials);
|
|
|
|
isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
|
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* Allocate target_size of buffer space. This is greater than twice
|
|
|
|
* the maximum individual RR data size.
|
|
|
|
*/
|
1999-01-27 13:38:21 +00:00
|
|
|
target_mem = isc_mem_get(mctx, target_size);
|
|
|
|
if (target_mem == NULL) {
|
1999-02-10 05:25:37 +00:00
|
|
|
result = DNS_R_NOMEMORY;
|
|
|
|
goto error_cleanup;
|
1999-01-27 13:38:21 +00:00
|
|
|
}
|
|
|
|
isc_buffer_init(&target, target_mem, target_size,
|
|
|
|
ISC_BUFFERTYPE_BINARY);
|
|
|
|
target_save = target;
|
1999-03-22 06:21:29 +00:00
|
|
|
|
|
|
|
memset(name_in_use, 0, NBUFS * sizeof(isc_boolean_t));
|
|
|
|
|
1999-01-27 13:38:21 +00:00
|
|
|
do {
|
1999-01-28 05:03:25 +00:00
|
|
|
GETTOKEN(lex, ISC_LEXOPT_INITIALWS, &token, ISC_TRUE);
|
1999-01-27 13:38:21 +00:00
|
|
|
|
|
|
|
if (token.type == isc_tokentype_eof) {
|
|
|
|
done = ISC_TRUE;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
1999-01-28 05:03:25 +00:00
|
|
|
if (token.type == isc_tokentype_eol) {
|
|
|
|
read_till_eol = ISC_FALSE;
|
1999-01-27 13:38:21 +00:00
|
|
|
continue; /* blank line */
|
1999-01-28 05:03:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (read_till_eol)
|
|
|
|
continue;
|
1999-01-27 13:38:21 +00:00
|
|
|
|
|
|
|
if (token.type == isc_tokentype_initialws) {
|
|
|
|
if (!current_known) {
|
1999-02-10 05:25:37 +00:00
|
|
|
(*callbacks->error)(callbacks,
|
|
|
|
"%s: %s:%d: No current owner name\n",
|
1999-08-05 22:10:23 +00:00
|
|
|
"dns_master_load",
|
|
|
|
isc_lex_getsourcename(lex),
|
1999-02-10 05:25:37 +00:00
|
|
|
isc_lex_getsourceline(lex));
|
|
|
|
result = DNS_R_NOOWNER;
|
1999-01-27 13:38:21 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-03-22 06:21:29 +00:00
|
|
|
/* Still working on the same name. */
|
1999-01-27 13:38:21 +00:00
|
|
|
} else if (token.type == isc_tokentype_string) {
|
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* "$" Support.
|
|
|
|
*
|
|
|
|
* "$ORIGIN" and "$INCLUDE" can both take domain names.
|
|
|
|
* The processing of "$ORIGIN" and "$INCLUDE" extends
|
|
|
|
* across the normal domain name processing.
|
|
|
|
*/
|
|
|
|
|
1999-01-27 23:57:46 +00:00
|
|
|
if (strcasecmp(token.value.as_pointer,
|
|
|
|
"$ORIGIN") == 0) {
|
1999-01-28 05:03:25 +00:00
|
|
|
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
|
|
|
read_till_eol = ISC_TRUE;
|
1999-01-27 23:57:46 +00:00
|
|
|
finish_origin = ISC_TRUE;
|
1999-01-28 01:16:59 +00:00
|
|
|
} else if (strcasecmp(token.value.as_pointer,
|
|
|
|
"$TTL") == 0) {
|
1999-11-04 01:21:28 +00:00
|
|
|
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
|
|
|
result =
|
|
|
|
dns_ttl_fromtext(&token.value.as_textregion,
|
|
|
|
&ttl);
|
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
goto cleanup;
|
1999-03-22 06:21:29 +00:00
|
|
|
if (ttl > 0x7fffffffUL) {
|
1999-02-10 05:25:37 +00:00
|
|
|
(callbacks->warn)(callbacks,
|
1999-11-30 02:21:59 +00:00
|
|
|
"dns_master_load: %s:%d: $TTL %lu > MAXTLL, setting TTL to 0\n",
|
1999-08-05 22:10:23 +00:00
|
|
|
isc_lex_getsourcename(lex),
|
1999-02-10 05:25:37 +00:00
|
|
|
isc_lex_getsourceline(lex),
|
|
|
|
ttl);
|
|
|
|
ttl = 0;
|
1999-01-28 01:16:59 +00:00
|
|
|
}
|
|
|
|
default_ttl = ttl;
|
|
|
|
default_ttl_known = ISC_TRUE;
|
1999-01-28 05:03:25 +00:00
|
|
|
read_till_eol = ISC_TRUE;
|
1999-01-28 01:16:59 +00:00
|
|
|
continue;
|
|
|
|
} else if (strcasecmp(token.value.as_pointer,
|
|
|
|
"$INCLUDE") == 0) {
|
1999-06-08 10:35:23 +00:00
|
|
|
if (ttl_offset != 0) {
|
|
|
|
(callbacks->error)(callbacks,
|
1999-08-05 22:10:23 +00:00
|
|
|
"dns_master_load: %s:%d: $INCLUDE "
|
1999-06-08 10:35:23 +00:00
|
|
|
"may not be used with $DATE",
|
1999-08-05 22:10:23 +00:00
|
|
|
isc_lex_getsourcename(lex),
|
1999-06-08 10:35:23 +00:00
|
|
|
isc_lex_getsourceline(lex));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-01-28 05:03:25 +00:00
|
|
|
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
1999-01-28 01:16:59 +00:00
|
|
|
if (include_file != NULL)
|
|
|
|
isc_mem_free(mctx, include_file);
|
|
|
|
include_file = isc_mem_strdup(mctx,
|
|
|
|
token.value.as_pointer);
|
1999-02-10 05:25:37 +00:00
|
|
|
if (include_file == NULL) {
|
|
|
|
result = DNS_R_NOMEMORY;
|
|
|
|
goto error_cleanup;
|
|
|
|
}
|
1999-01-28 05:03:25 +00:00
|
|
|
GETTOKEN(lex, 0, &token, ISC_TRUE);
|
1999-01-28 01:16:59 +00:00
|
|
|
if (token.type == isc_tokentype_eol ||
|
|
|
|
token.type == isc_tokentype_eof) {
|
1999-10-25 18:41:36 +00:00
|
|
|
result =
|
|
|
|
dns_master_loadfile(include_file,
|
|
|
|
top,
|
|
|
|
&origin_name,
|
|
|
|
zclass,
|
|
|
|
age_ttl,
|
|
|
|
soacount,
|
|
|
|
nscount,
|
|
|
|
callbacks,
|
|
|
|
mctx);
|
1999-01-28 01:16:59 +00:00
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
isc_lex_ungettoken(lex, &token);
|
|
|
|
continue;
|
|
|
|
}
|
1999-01-28 05:03:25 +00:00
|
|
|
read_till_eol = ISC_TRUE;
|
1999-01-28 01:16:59 +00:00
|
|
|
finish_include = ISC_TRUE;
|
1999-06-08 10:35:23 +00:00
|
|
|
} else if (strcasecmp(token.value.as_pointer,
|
|
|
|
"$DATE") == 0) {
|
1999-06-24 17:55:41 +00:00
|
|
|
isc_int64_t dump_time64;
|
1999-06-08 10:35:23 +00:00
|
|
|
isc_stdtime_t dump_time, current_time;
|
|
|
|
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
1999-12-16 23:29:07 +00:00
|
|
|
isc_stdtime_get(¤t_time);
|
1999-06-08 10:35:23 +00:00
|
|
|
result = dns_time64_fromtext(token.value.
|
|
|
|
as_pointer, &dump_time64);
|
1999-10-08 23:26:55 +00:00
|
|
|
dump_time = (isc_stdtime_t)dump_time64;
|
1999-06-08 10:35:23 +00:00
|
|
|
if (dump_time != dump_time64) {
|
|
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
|
|
"dns_master_load: %s:%d: "
|
|
|
|
"$DATE outside epoch",
|
1999-08-05 22:10:23 +00:00
|
|
|
isc_lex_getsourcename(lex),
|
1999-06-08 10:35:23 +00:00
|
|
|
isc_lex_getsourceline(lex));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (dump_time > current_time) {
|
|
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
|
|
"dns_master_load: %s:%d: "
|
|
|
|
"$DATE in future, using current date",
|
1999-08-05 22:10:23 +00:00
|
|
|
isc_lex_getsourcename(lex),
|
1999-06-08 10:35:23 +00:00
|
|
|
isc_lex_getsourceline(lex));
|
|
|
|
dump_time = current_time;
|
|
|
|
}
|
|
|
|
ttl_offset = current_time - dump_time;
|
|
|
|
read_till_eol = ISC_TRUE;
|
|
|
|
continue;
|
1999-01-27 23:57:46 +00:00
|
|
|
}
|
1999-01-27 13:38:21 +00:00
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* Normal processing resumes.
|
|
|
|
*
|
|
|
|
* Find a free name buffer.
|
|
|
|
*/
|
|
|
|
for (new_in_use = 0; new_in_use < NBUFS ; new_in_use++)
|
1999-01-27 23:17:57 +00:00
|
|
|
if (!name_in_use[new_in_use])
|
|
|
|
break;
|
1999-03-22 06:21:29 +00:00
|
|
|
INSIST(new_in_use < NBUFS);
|
|
|
|
isc_buffer_init(&name, &name_buf[new_in_use][0],
|
|
|
|
MAXWIRESZ, ISC_BUFFERTYPE_BINARY);
|
1999-01-27 13:38:21 +00:00
|
|
|
dns_name_init(&new_name, NULL);
|
|
|
|
isc_buffer_init(&buffer, token.value.as_region.base,
|
|
|
|
token.value.as_region.length,
|
|
|
|
ISC_BUFFERTYPE_TEXT);
|
|
|
|
isc_buffer_add(&buffer, token.value.as_region.length);
|
|
|
|
isc_buffer_setactive(&buffer,
|
|
|
|
token.value.as_region.length);
|
|
|
|
result = dns_name_fromtext(&new_name, &buffer,
|
1999-01-28 05:03:25 +00:00
|
|
|
&origin_name, ISC_FALSE, &name);
|
1999-01-27 13:38:21 +00:00
|
|
|
|
|
|
|
if (result != DNS_R_SUCCESS)
|
1999-02-10 05:25:37 +00:00
|
|
|
goto error_cleanup;
|
1999-03-22 06:21:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Finish $ORIGIN / $INCLUDE processing if required.
|
|
|
|
*/
|
1999-01-27 23:57:46 +00:00
|
|
|
if (finish_origin) {
|
|
|
|
if (origin_in_use != -1)
|
|
|
|
name_in_use[origin_in_use] = ISC_FALSE;
|
|
|
|
origin_in_use = new_in_use;
|
|
|
|
name_in_use[origin_in_use] = ISC_TRUE;
|
|
|
|
origin_name = new_name;
|
|
|
|
finish_origin =ISC_FALSE;
|
|
|
|
continue;
|
|
|
|
}
|
1999-01-28 01:16:59 +00:00
|
|
|
if (finish_include) {
|
1999-08-05 22:10:23 +00:00
|
|
|
result = dns_master_loadfile(include_file,
|
|
|
|
top,
|
|
|
|
&new_name,
|
|
|
|
zclass,
|
|
|
|
age_ttl,
|
|
|
|
soacount,
|
|
|
|
nscount,
|
|
|
|
callbacks,
|
|
|
|
mctx);
|
1999-01-28 01:16:59 +00:00
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
finish_include = ISC_FALSE;
|
|
|
|
continue;
|
|
|
|
}
|
1999-03-22 06:21:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* "$" Processing Finished
|
|
|
|
*/
|
|
|
|
|
1999-01-27 13:38:21 +00:00
|
|
|
/*
|
1999-03-22 06:21:29 +00:00
|
|
|
* If we are processing glue and the new name does
|
|
|
|
* not match the current glue name, commit the glue
|
|
|
|
* and pop stacks leaving us in 'normal' processing
|
1999-03-23 00:04:01 +00:00
|
|
|
* state. Linked lists are undone by commit().
|
1999-01-27 13:38:21 +00:00
|
|
|
*/
|
|
|
|
if (in_glue && dns_name_compare(&glue_name,
|
|
|
|
&new_name) != 0) {
|
1999-02-09 08:02:21 +00:00
|
|
|
result = commit(callbacks, &glue_list,
|
|
|
|
&glue_name);
|
1999-01-27 13:38:21 +00:00
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
goto cleanup;
|
1999-01-27 23:17:57 +00:00
|
|
|
if (glue_in_use != -1)
|
|
|
|
name_in_use[glue_in_use] = ISC_FALSE;
|
1999-01-28 01:16:59 +00:00
|
|
|
glue_in_use = -1;
|
1999-01-27 13:38:21 +00:00
|
|
|
dns_name_invalidate(&glue_name);
|
|
|
|
in_glue = ISC_FALSE;
|
|
|
|
rdcount = rdcount_save;
|
|
|
|
rdlcount = rdlcount_save;
|
|
|
|
target = target_save;
|
|
|
|
}
|
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* If we are in 'normal' processing state and the new
|
|
|
|
* name does not match the current name, see if the
|
|
|
|
* new name is for glue and treat it as such,
|
|
|
|
* otherwise we have a new name so commit what we
|
|
|
|
* have.
|
|
|
|
*/
|
1999-01-30 13:11:24 +00:00
|
|
|
if (!in_glue && (!current_known ||
|
|
|
|
dns_name_compare(¤t_name, &new_name) != 0)) {
|
1999-01-27 13:38:21 +00:00
|
|
|
if (current_has_delegation &&
|
|
|
|
is_glue(¤t_list, &new_name)) {
|
|
|
|
in_glue = ISC_TRUE;
|
|
|
|
rdcount_save = rdcount;
|
|
|
|
rdlcount_save = rdlcount;
|
|
|
|
target_save = target;
|
|
|
|
glue_name = new_name;
|
1999-01-27 23:17:57 +00:00
|
|
|
glue_in_use = new_in_use;
|
|
|
|
name_in_use[glue_in_use] = ISC_TRUE;
|
1999-01-27 13:38:21 +00:00
|
|
|
} else {
|
1999-02-09 08:02:21 +00:00
|
|
|
result = commit(callbacks,
|
|
|
|
¤t_list,
|
|
|
|
¤t_name);
|
1999-01-27 13:38:21 +00:00
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
rdcount = 0;
|
|
|
|
rdlcount = 0;
|
1999-01-27 23:17:57 +00:00
|
|
|
if (current_in_use != -1)
|
|
|
|
name_in_use[current_in_use]
|
|
|
|
= ISC_FALSE;
|
|
|
|
current_in_use = new_in_use;
|
|
|
|
name_in_use[current_in_use] = ISC_TRUE;
|
1999-01-27 13:38:21 +00:00
|
|
|
current_name = new_name;
|
|
|
|
current_known = ISC_TRUE;
|
|
|
|
current_has_delegation = ISC_FALSE;
|
1999-01-27 23:17:57 +00:00
|
|
|
isc_buffer_init(&target, target_mem,
|
|
|
|
target_size,
|
|
|
|
ISC_BUFFERTYPE_BINARY);
|
1999-01-27 13:38:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
1999-02-10 05:25:37 +00:00
|
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
|
|
"%s:%d: isc_lex_gettoken() returned unexpeced token type (%d)\n",
|
1999-08-05 22:10:23 +00:00
|
|
|
isc_lex_getsourcename(lex),
|
1999-02-10 05:25:37 +00:00
|
|
|
isc_lex_getsourceline(lex),
|
|
|
|
token.type);
|
1999-01-27 13:38:21 +00:00
|
|
|
result = DNS_R_UNEXPECTED;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* Find TTL, class and type. Both TTL and class are optional
|
|
|
|
* and may occur in any order if they exist. TTL and class
|
|
|
|
* come before type which must exist.
|
|
|
|
*
|
|
|
|
* [<TTL>] [<class>] <type> <RDATA>
|
|
|
|
* [<class>] [<TTL>] <type> <RDATA>
|
|
|
|
*/
|
|
|
|
|
1999-01-27 13:38:21 +00:00
|
|
|
type = 0;
|
1999-03-04 02:48:47 +00:00
|
|
|
rdclass = 0;
|
1999-01-27 13:38:21 +00:00
|
|
|
|
1999-11-02 13:07:53 +00:00
|
|
|
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
1999-01-27 13:38:21 +00:00
|
|
|
|
1999-11-02 13:07:53 +00:00
|
|
|
if (dns_rdataclass_fromtext(&rdclass,
|
1999-03-22 06:21:29 +00:00
|
|
|
&token.value.as_textregion)
|
|
|
|
== DNS_R_SUCCESS)
|
1999-11-02 13:07:53 +00:00
|
|
|
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
1999-03-22 06:21:29 +00:00
|
|
|
|
1999-11-02 13:07:53 +00:00
|
|
|
if (dns_ttl_fromtext(&token.value.as_textregion, &ttl)
|
|
|
|
== DNS_R_SUCCESS) {
|
1999-03-22 06:21:29 +00:00
|
|
|
if (ttl > 0x7fffffffUL) {
|
1999-02-10 05:25:37 +00:00
|
|
|
(callbacks->warn)(callbacks,
|
1999-11-30 02:21:59 +00:00
|
|
|
"dns_master_load: %s:%d: TTL %lu > maxtll, setting ttl to 0\n",
|
1999-08-05 22:10:23 +00:00
|
|
|
isc_lex_getsourcename(lex),
|
1999-02-10 05:25:37 +00:00
|
|
|
isc_lex_getsourceline(lex),
|
|
|
|
ttl);
|
|
|
|
ttl = 0;
|
1999-01-28 01:16:59 +00:00
|
|
|
}
|
1999-01-27 13:38:21 +00:00
|
|
|
ttl_known = ISC_TRUE;
|
1999-01-28 05:03:25 +00:00
|
|
|
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
1999-01-28 01:16:59 +00:00
|
|
|
} else if (!ttl_known && !default_ttl_known) {
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* BIND 4 / 8 'USE_SOA_MINIMUM' could be set here.
|
|
|
|
*/
|
1999-02-10 05:25:37 +00:00
|
|
|
(*callbacks->error)(callbacks,
|
1999-11-30 02:21:59 +00:00
|
|
|
"%s: %s:%d: no TTL specified\n",
|
1999-08-05 22:10:23 +00:00
|
|
|
"dns_master_load",
|
|
|
|
isc_lex_getsourcename(lex),
|
1999-02-10 05:25:37 +00:00
|
|
|
isc_lex_getsourceline(lex));
|
|
|
|
result = DNS_R_NOTTL;
|
1999-01-27 13:38:21 +00:00
|
|
|
goto cleanup;
|
1999-03-22 06:21:29 +00:00
|
|
|
} else if (default_ttl_known) {
|
1999-01-28 01:16:59 +00:00
|
|
|
ttl = default_ttl;
|
1999-03-22 06:21:29 +00:00
|
|
|
} else if (warn_1035) {
|
|
|
|
(*callbacks->warn)(callbacks,
|
1999-11-30 02:21:59 +00:00
|
|
|
"%s: %s:%d: using RFC 1035 TTL semantics\n",
|
1999-08-05 22:10:23 +00:00
|
|
|
"dns_master_load",
|
|
|
|
isc_lex_getsourcename(lex),
|
1999-03-22 06:21:29 +00:00
|
|
|
isc_lex_getsourceline(lex));
|
|
|
|
warn_1035 = ISC_FALSE;
|
|
|
|
}
|
1999-01-27 13:38:21 +00:00
|
|
|
|
1999-01-28 05:03:25 +00:00
|
|
|
if (token.type != isc_tokentype_string) {
|
1999-02-10 05:25:37 +00:00
|
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
|
|
"isc_lex_gettoken() returned unexpected token type\n");
|
1999-01-27 13:38:21 +00:00
|
|
|
result = DNS_R_UNEXPECTED;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
if (rdclass == 0 &&
|
1999-10-25 18:41:36 +00:00
|
|
|
dns_rdataclass_fromtext(&rdclass,
|
|
|
|
&token.value.as_textregion)
|
1999-01-28 05:03:25 +00:00
|
|
|
== DNS_R_SUCCESS)
|
|
|
|
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
1999-01-27 13:38:21 +00:00
|
|
|
|
|
|
|
if (token.type != isc_tokentype_string) {
|
1999-02-10 05:25:37 +00:00
|
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
|
|
"isc_lex_gettoken() returned unexpected token type\n");
|
1999-01-27 13:38:21 +00:00
|
|
|
result = DNS_R_UNEXPECTED;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-03-22 06:21:29 +00:00
|
|
|
|
1999-01-28 05:03:25 +00:00
|
|
|
result = dns_rdatatype_fromtext(&type,
|
|
|
|
&token.value.as_textregion);
|
|
|
|
if (result != DNS_R_SUCCESS)
|
1999-01-27 13:38:21 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* If the class specified does not match the zone's class
|
|
|
|
* print out a error message and exit.
|
|
|
|
*/
|
1999-03-04 02:48:47 +00:00
|
|
|
if (rdclass != 0 && rdclass != zclass) {
|
1999-02-10 05:25:37 +00:00
|
|
|
char buf1[32];
|
|
|
|
char buf2[32];
|
|
|
|
unsigned int len1, len2;
|
|
|
|
isc_buffer_t buffer;
|
|
|
|
isc_region_t region;
|
|
|
|
|
|
|
|
isc_buffer_init(&buffer, buf1, sizeof buf1,
|
|
|
|
ISC_BUFFERTYPE_TEXT);
|
1999-03-04 02:48:47 +00:00
|
|
|
result = dns_rdataclass_totext(rdclass, &buffer);
|
1999-02-10 05:25:37 +00:00
|
|
|
if (result != DNS_R_SUCCESS) {
|
|
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
|
|
"dns_rdataclass_totext() failed: %s",
|
|
|
|
dns_result_totext(result));
|
|
|
|
result = DNS_R_UNEXPECTED;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-11-30 02:20:24 +00:00
|
|
|
isc_buffer_used(&buffer, ®ion);
|
1999-02-10 05:25:37 +00:00
|
|
|
len1 = region.length;
|
|
|
|
isc_buffer_init(&buffer, buf2, sizeof buf2,
|
|
|
|
ISC_BUFFERTYPE_TEXT);
|
1999-04-25 22:18:11 +00:00
|
|
|
result = dns_rdataclass_totext(zclass, &buffer);
|
1999-02-10 05:25:37 +00:00
|
|
|
if (result != DNS_R_SUCCESS) {
|
|
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
|
|
"dns_rdataclass_totext() failed: %s",
|
|
|
|
dns_result_totext(result));
|
|
|
|
result = DNS_R_UNEXPECTED;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-11-30 02:20:24 +00:00
|
|
|
isc_buffer_used(&buffer, ®ion);
|
1999-02-10 05:25:37 +00:00
|
|
|
len2 = region.length;
|
|
|
|
(*callbacks->error)(callbacks,
|
1999-11-30 02:21:59 +00:00
|
|
|
"%s: %s:%d: class (%.*s) != zone class (%.*s)\n",
|
1999-08-05 22:10:23 +00:00
|
|
|
"dns_master_load",
|
|
|
|
isc_lex_getsourcename(lex),
|
1999-02-10 05:25:37 +00:00
|
|
|
isc_lex_getsourceline(lex),
|
|
|
|
len1, buf1, len2, buf2);
|
|
|
|
result = DNS_R_BADCLASS;
|
1999-01-27 13:38:21 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
1999-02-04 06:38:43 +00:00
|
|
|
if (type == dns_rdatatype_ns && !in_glue)
|
1999-01-27 13:38:21 +00:00
|
|
|
current_has_delegation = ISC_TRUE;
|
1999-01-28 05:03:25 +00:00
|
|
|
|
1999-06-08 10:35:23 +00:00
|
|
|
if (age_ttl) {
|
|
|
|
/*
|
|
|
|
* Adjust the TTL for $DATE. If the RR has already
|
|
|
|
* expired, ignore it without even parsing the rdata
|
|
|
|
* part (good for performance, bad for catching
|
|
|
|
* syntax errors).
|
|
|
|
*/
|
|
|
|
if (ttl < ttl_offset) {
|
1999-10-25 18:41:36 +00:00
|
|
|
read_till_eol = ISC_TRUE;
|
1999-06-08 10:35:23 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ttl -= ttl_offset;
|
|
|
|
}
|
|
|
|
|
1999-08-31 22:14:06 +00:00
|
|
|
/*
|
|
|
|
* Find a rdata structure.
|
|
|
|
*/
|
|
|
|
if (rdcount == rdata_size) {
|
|
|
|
new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
|
|
|
|
rdata_size, ¤t_list,
|
|
|
|
&glue_list, mctx);
|
|
|
|
if (new_rdata == NULL) {
|
|
|
|
result = DNS_R_NOMEMORY;
|
|
|
|
goto error_cleanup;
|
|
|
|
}
|
|
|
|
rdata_size += RDSZ;
|
|
|
|
rdata = new_rdata;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read rdata contents.
|
|
|
|
*/
|
|
|
|
result = dns_rdata_fromtext(&rdata[rdcount], zclass, type,
|
|
|
|
lex, &origin_name, ISC_FALSE, &target,
|
|
|
|
callbacks);
|
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
if (type == dns_rdatatype_sig)
|
|
|
|
covers = dns_rdata_covers(&rdata[rdcount]);
|
|
|
|
else
|
|
|
|
covers = 0;
|
|
|
|
|
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* Find type in rdatalist.
|
|
|
|
* If it does not exit create new one and prepend to list
|
|
|
|
* as this will mimimise list traversal.
|
|
|
|
*/
|
1999-01-27 13:38:21 +00:00
|
|
|
if (in_glue)
|
|
|
|
this = ISC_LIST_HEAD(glue_list);
|
|
|
|
else
|
|
|
|
this = ISC_LIST_HEAD(current_list);
|
|
|
|
|
1999-01-27 23:17:57 +00:00
|
|
|
while (this != NULL) {
|
1999-08-31 22:14:06 +00:00
|
|
|
if (this->type == type && this->covers == covers)
|
1999-01-27 13:38:21 +00:00
|
|
|
break;
|
|
|
|
this = ISC_LIST_NEXT(this, link);
|
|
|
|
}
|
1999-03-22 06:21:29 +00:00
|
|
|
|
1999-01-27 13:38:21 +00:00
|
|
|
if (this == NULL) {
|
|
|
|
if (rdlcount == rdatalist_size) {
|
|
|
|
new_rdatalist =
|
1999-03-22 06:21:29 +00:00
|
|
|
grow_rdatalist(rdatalist_size + RDLSZ,
|
1999-01-27 13:38:21 +00:00
|
|
|
rdatalist,
|
|
|
|
rdatalist_size,
|
|
|
|
¤t_list,
|
|
|
|
&glue_list,
|
|
|
|
mctx);
|
|
|
|
if (new_rdatalist == NULL) {
|
1999-02-10 05:25:37 +00:00
|
|
|
result = DNS_R_NOMEMORY;
|
|
|
|
goto error_cleanup;
|
1999-01-27 13:38:21 +00:00
|
|
|
}
|
|
|
|
rdatalist = new_rdatalist;
|
1999-03-22 06:21:29 +00:00
|
|
|
rdatalist_size += RDLSZ;
|
1999-01-27 13:38:21 +00:00
|
|
|
}
|
|
|
|
this = &rdatalist[rdlcount++];
|
|
|
|
this->type = type;
|
1999-08-31 22:14:06 +00:00
|
|
|
this->covers = covers;
|
1999-03-04 02:48:47 +00:00
|
|
|
this->rdclass = zclass;
|
1999-01-27 13:38:21 +00:00
|
|
|
this->ttl = ttl;
|
|
|
|
ISC_LIST_INIT(this->rdata);
|
|
|
|
ISC_LINK_INIT(this, link);
|
|
|
|
if (in_glue)
|
|
|
|
ISC_LIST_PREPEND(glue_list, this, link);
|
|
|
|
else
|
|
|
|
ISC_LIST_PREPEND(current_list, this, link);
|
1999-02-10 05:25:37 +00:00
|
|
|
} else if (this->ttl != ttl) {
|
|
|
|
(*callbacks->warn)(callbacks,
|
1999-03-24 00:29:54 +00:00
|
|
|
"%s: %s:%d: TTL set to prior TTL (%lu)\n",
|
1999-08-05 22:10:23 +00:00
|
|
|
"dns_master_load",
|
|
|
|
isc_lex_getsourcename(lex),
|
1999-02-10 05:25:37 +00:00
|
|
|
isc_lex_getsourceline(lex),
|
|
|
|
this->ttl);
|
|
|
|
ttl = this->ttl;
|
1999-01-27 13:38:21 +00:00
|
|
|
}
|
1999-02-10 05:25:37 +00:00
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* If the new rdata is not on the list add it.
|
|
|
|
*
|
|
|
|
* If the new rdata is on the list do not worry about
|
|
|
|
* recovering the space it is using in target as it will be
|
|
|
|
* recovered when we next call commit. The worst that can
|
|
|
|
* happen is that we make a few extra calls to commit.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!on_list(this, &rdata[rdcount])) {
|
1999-10-07 19:40:30 +00:00
|
|
|
ISC_LIST_APPEND(this->rdata, &rdata[rdcount], link);
|
1999-03-22 06:21:29 +00:00
|
|
|
rdcount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We must have at least 64k as rdlen is 16 bits.
|
|
|
|
* If we don't commit everything we have so far.
|
|
|
|
*/
|
|
|
|
if ((target.length - target.used) < MINTSIZ) {
|
1999-02-09 08:02:21 +00:00
|
|
|
result = commit(callbacks, ¤t_list,
|
|
|
|
¤t_name);
|
1999-01-27 23:17:57 +00:00
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
goto cleanup;
|
1999-02-09 08:02:21 +00:00
|
|
|
result = commit(callbacks, &glue_list, &glue_name);
|
1999-01-27 23:17:57 +00:00
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
rdcount = 0;
|
|
|
|
rdlcount = 0;
|
1999-01-28 01:16:59 +00:00
|
|
|
if (glue_in_use != -1)
|
|
|
|
name_in_use[glue_in_use] = ISC_FALSE;
|
|
|
|
glue_in_use = -1;
|
1999-01-27 23:17:57 +00:00
|
|
|
in_glue = ISC_FALSE;
|
|
|
|
current_has_delegation = ISC_FALSE;
|
|
|
|
isc_buffer_init(&target, target_mem, target_size,
|
|
|
|
ISC_BUFFERTYPE_BINARY);
|
|
|
|
}
|
1999-01-27 13:38:21 +00:00
|
|
|
} while (!done);
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* Commit what has not yet been committed.
|
|
|
|
*/
|
1999-02-09 08:02:21 +00:00
|
|
|
result = commit(callbacks, ¤t_list, ¤t_name);
|
1999-01-27 13:38:21 +00:00
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
goto cleanup;
|
1999-02-09 08:02:21 +00:00
|
|
|
result = commit(callbacks, &glue_list, &glue_name);
|
1999-01-27 13:38:21 +00:00
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
goto cleanup;
|
1999-02-10 05:25:37 +00:00
|
|
|
else
|
|
|
|
result = DNS_R_SUCCESS;
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
error_cleanup:
|
1999-08-05 22:10:23 +00:00
|
|
|
(*callbacks->error)(callbacks, "dns_master_load: %s\n",
|
1999-02-10 05:25:37 +00:00
|
|
|
dns_result_totext(result));
|
1999-01-27 13:38:21 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (lex != NULL) {
|
|
|
|
isc_lex_close(lex);
|
|
|
|
isc_lex_destroy(&lex);
|
|
|
|
}
|
|
|
|
while ((this = ISC_LIST_HEAD(current_list)) != NULL)
|
|
|
|
ISC_LIST_UNLINK(current_list, this, link);
|
|
|
|
while ((this = ISC_LIST_HEAD(glue_list)) != NULL)
|
|
|
|
ISC_LIST_UNLINK(glue_list, this, link);
|
|
|
|
if (rdatalist != NULL)
|
|
|
|
isc_mem_put(mctx, rdatalist,
|
|
|
|
rdatalist_size * sizeof *rdatalist);
|
|
|
|
if (rdata != NULL)
|
|
|
|
isc_mem_put(mctx, rdata, rdata_size * sizeof *rdata);
|
1999-01-28 01:16:59 +00:00
|
|
|
if (target_mem != NULL)
|
1999-01-27 13:38:21 +00:00
|
|
|
isc_mem_put(mctx, target_mem, target_size);
|
1999-01-28 01:16:59 +00:00
|
|
|
if (include_file != NULL)
|
|
|
|
isc_mem_free(mctx, include_file);
|
1999-01-27 13:38:21 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-10-25 18:41:36 +00:00
|
|
|
dns_master_loadfile(const char *master_file, dns_name_t *top,
|
|
|
|
dns_name_t *origin,
|
1999-08-05 22:10:23 +00:00
|
|
|
dns_rdataclass_t zclass, isc_boolean_t age_ttl,
|
1999-10-25 18:41:36 +00:00
|
|
|
int *soacount, int *nscount,
|
|
|
|
dns_rdatacallbacks_t *callbacks,
|
1999-08-05 22:10:23 +00:00
|
|
|
isc_mem_t *mctx)
|
|
|
|
{
|
|
|
|
isc_result_t result;
|
|
|
|
isc_lex_t *lex = NULL;
|
|
|
|
|
|
|
|
REQUIRE(master_file != NULL);
|
|
|
|
|
1999-10-26 18:05:23 +00:00
|
|
|
result = isc_lex_create(mctx, TOKENSIZ, &lex);
|
1999-08-05 22:10:23 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
|
|
|
result = isc_lex_openfile(lex, master_file);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_lex_destroy(&lex);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-10-25 18:41:36 +00:00
|
|
|
return (load(lex, top, origin, zclass, age_ttl, soacount, nscount,
|
|
|
|
callbacks, mctx));
|
1999-08-05 22:10:23 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-08-05 22:10:23 +00:00
|
|
|
dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
|
|
|
|
dns_rdataclass_t zclass, isc_boolean_t age_ttl,
|
1999-10-25 18:41:36 +00:00
|
|
|
int *soacount, int *nscount,
|
|
|
|
dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
|
1999-08-05 22:10:23 +00:00
|
|
|
{
|
|
|
|
isc_result_t result;
|
|
|
|
isc_lex_t *lex = NULL;
|
|
|
|
|
|
|
|
REQUIRE(stream != NULL);
|
|
|
|
|
1999-10-26 18:05:23 +00:00
|
|
|
result = isc_lex_create(mctx, TOKENSIZ, &lex);
|
1999-08-05 22:10:23 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
|
|
|
result = isc_lex_openstream(lex, stream);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_lex_destroy(&lex);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-10-25 18:41:36 +00:00
|
|
|
return (load(lex, top, origin, zclass, age_ttl, soacount, nscount,
|
|
|
|
callbacks, mctx));
|
1999-08-05 22:10:23 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-10-25 18:41:36 +00:00
|
|
|
dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top,
|
|
|
|
dns_name_t *origin, dns_rdataclass_t zclass,
|
|
|
|
isc_boolean_t age_ttl,
|
|
|
|
int *soacount, int *nscount,
|
|
|
|
dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
|
1999-08-05 22:10:23 +00:00
|
|
|
{
|
|
|
|
isc_result_t result;
|
|
|
|
isc_lex_t *lex = NULL;
|
|
|
|
|
|
|
|
REQUIRE(buffer != NULL);
|
|
|
|
|
1999-10-26 18:05:23 +00:00
|
|
|
result = isc_lex_create(mctx, TOKENSIZ, &lex);
|
1999-08-05 22:10:23 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
|
|
|
result = isc_lex_openbuffer(lex, buffer);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_lex_destroy(&lex);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-10-25 18:41:36 +00:00
|
|
|
return (load(lex, top, origin, zclass, age_ttl, soacount, nscount,
|
|
|
|
callbacks, mctx));
|
1999-08-05 22:10:23 +00:00
|
|
|
}
|
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* Grow the slab of dns_rdatalist_t structures.
|
|
|
|
* Re-link glue and current list.
|
|
|
|
*/
|
1999-01-27 13:38:21 +00:00
|
|
|
static dns_rdatalist_t *
|
|
|
|
grow_rdatalist(int new_len, dns_rdatalist_t *old, int old_len,
|
|
|
|
rdatalist_head_t *current, rdatalist_head_t *glue,
|
|
|
|
isc_mem_t *mctx)
|
|
|
|
{
|
|
|
|
dns_rdatalist_t *new;
|
|
|
|
int rdlcount = 0;
|
|
|
|
ISC_LIST(dns_rdatalist_t) save;
|
|
|
|
dns_rdatalist_t *this;
|
|
|
|
|
|
|
|
new = isc_mem_get(mctx, new_len * sizeof *new);
|
|
|
|
if (new == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
ISC_LIST_INIT(save);
|
|
|
|
this = ISC_LIST_HEAD(*current);
|
|
|
|
while ((this = ISC_LIST_HEAD(*current)) != NULL) {
|
|
|
|
ISC_LIST_UNLINK(*current, this, link);
|
|
|
|
ISC_LIST_APPEND(save, this, link);
|
|
|
|
}
|
|
|
|
while ((this = ISC_LIST_HEAD(save)) != NULL) {
|
|
|
|
ISC_LIST_UNLINK(save, this, link);
|
|
|
|
new[rdlcount] = *this;
|
|
|
|
ISC_LIST_APPEND(*current, &new[rdlcount], link);
|
|
|
|
rdlcount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
ISC_LIST_INIT(save);
|
|
|
|
this = ISC_LIST_HEAD(*glue);
|
|
|
|
while ((this = ISC_LIST_HEAD(*glue)) != NULL) {
|
|
|
|
ISC_LIST_UNLINK(*glue, this, link);
|
|
|
|
ISC_LIST_APPEND(save, this, link);
|
|
|
|
}
|
|
|
|
while ((this = ISC_LIST_HEAD(save)) != NULL) {
|
|
|
|
ISC_LIST_UNLINK(save, this, link);
|
|
|
|
new[rdlcount] = *this;
|
|
|
|
ISC_LIST_APPEND(*glue, &new[rdlcount], link);
|
|
|
|
rdlcount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
INSIST(rdlcount == old_len);
|
|
|
|
if (old != NULL)
|
|
|
|
isc_mem_put(mctx, old, old_len * sizeof *old);
|
|
|
|
return (new);
|
|
|
|
}
|
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* Grow the slab of rdata structs.
|
|
|
|
* Re-link the current and glue chains.
|
|
|
|
*/
|
1999-01-27 13:38:21 +00:00
|
|
|
static dns_rdata_t *
|
|
|
|
grow_rdata(int new_len, dns_rdata_t *old, int old_len,
|
|
|
|
rdatalist_head_t *current, rdatalist_head_t *glue,
|
|
|
|
isc_mem_t *mctx)
|
|
|
|
{
|
|
|
|
dns_rdata_t *new;
|
|
|
|
int rdcount = 0;
|
|
|
|
ISC_LIST(dns_rdata_t) save;
|
|
|
|
dns_rdatalist_t *this;
|
|
|
|
dns_rdata_t *rdata;
|
|
|
|
|
|
|
|
new = isc_mem_get(mctx, new_len * sizeof *new);
|
|
|
|
if (new == NULL)
|
|
|
|
return (NULL);
|
|
|
|
memset(new, 0, new_len * sizeof *new);
|
1999-03-22 06:21:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy current relinking.
|
|
|
|
*/
|
1999-01-27 13:38:21 +00:00
|
|
|
this = ISC_LIST_HEAD(*current);
|
|
|
|
while (this != NULL) {
|
|
|
|
ISC_LIST_INIT(save);
|
|
|
|
while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
|
|
|
|
ISC_LIST_UNLINK(this->rdata, rdata, link);
|
|
|
|
ISC_LIST_APPEND(save, rdata, link);
|
|
|
|
}
|
|
|
|
while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
|
|
|
|
ISC_LIST_UNLINK(save, rdata, link);
|
|
|
|
new[rdcount] = *rdata;
|
|
|
|
ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
|
|
|
|
rdcount++;
|
|
|
|
}
|
|
|
|
this = ISC_LIST_NEXT(this, link);
|
|
|
|
}
|
1999-03-22 06:21:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy glue relinking.
|
|
|
|
*/
|
1999-01-27 13:38:21 +00:00
|
|
|
this = ISC_LIST_HEAD(*glue);
|
|
|
|
while (this != NULL) {
|
|
|
|
ISC_LIST_INIT(save);
|
|
|
|
while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
|
|
|
|
ISC_LIST_UNLINK(this->rdata, rdata, link);
|
|
|
|
ISC_LIST_APPEND(save, rdata, link);
|
|
|
|
}
|
|
|
|
while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
|
|
|
|
ISC_LIST_UNLINK(save, rdata, link);
|
|
|
|
new[rdcount] = *rdata;
|
|
|
|
ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
|
|
|
|
rdcount++;
|
|
|
|
}
|
|
|
|
this = ISC_LIST_NEXT(this, link);
|
|
|
|
}
|
|
|
|
INSIST(rdcount == old_len);
|
|
|
|
if (old != NULL)
|
|
|
|
isc_mem_put(mctx, old, old_len * sizeof *old);
|
|
|
|
return (new);
|
|
|
|
}
|
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* Convert each element from a rdatalist_t to rdataset then call commit.
|
|
|
|
* Unlink each element as we go.
|
|
|
|
*/
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
1999-02-09 08:02:21 +00:00
|
|
|
commit(dns_rdatacallbacks_t *callbacks, rdatalist_head_t *head,
|
|
|
|
dns_name_t *owner)
|
1999-01-28 05:03:25 +00:00
|
|
|
{
|
1999-01-27 13:38:21 +00:00
|
|
|
dns_rdatalist_t *this;
|
|
|
|
dns_rdataset_t dataset;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-01-27 13:38:21 +00:00
|
|
|
|
|
|
|
while ((this = ISC_LIST_HEAD(*head)) != NULL) {
|
|
|
|
dns_rdataset_init(&dataset);
|
|
|
|
dns_rdatalist_tordataset(this, &dataset);
|
1999-07-30 23:33:15 +00:00
|
|
|
result = ((*callbacks->add)(callbacks->add_private, owner,
|
|
|
|
&dataset));
|
1999-01-27 13:38:21 +00:00
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
ISC_LIST_UNLINK(*head, this, link);
|
|
|
|
}
|
|
|
|
return (DNS_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
1999-03-22 06:21:29 +00:00
|
|
|
/*
|
|
|
|
* Returns ISC_TRUE if one of the NS rdata's contains 'owner'.
|
|
|
|
*/
|
|
|
|
|
1999-01-27 13:38:21 +00:00
|
|
|
static isc_boolean_t
|
|
|
|
is_glue(rdatalist_head_t *head, dns_name_t *owner) {
|
|
|
|
dns_rdatalist_t *this;
|
|
|
|
dns_rdata_t *rdata;
|
|
|
|
isc_region_t region;
|
|
|
|
dns_name_t name;
|
|
|
|
|
|
|
|
/* find NS rrset */
|
|
|
|
this = ISC_LIST_HEAD(*head);
|
|
|
|
while (this != NULL) {
|
1999-02-04 06:38:43 +00:00
|
|
|
if (this->type == dns_rdatatype_ns)
|
1999-01-27 13:38:21 +00:00
|
|
|
break;
|
|
|
|
this = ISC_LIST_NEXT(this, link);
|
|
|
|
}
|
|
|
|
if (this == NULL)
|
|
|
|
return (ISC_FALSE);
|
|
|
|
|
|
|
|
rdata = ISC_LIST_HEAD(this->rdata);
|
|
|
|
while (rdata != NULL) {
|
|
|
|
dns_name_init(&name, NULL);
|
|
|
|
dns_rdata_toregion(rdata, ®ion);
|
|
|
|
dns_name_fromregion(&name, ®ion);
|
|
|
|
if (dns_name_compare(&name, owner) == 0)
|
|
|
|
return (ISC_TRUE);
|
1999-01-27 23:17:57 +00:00
|
|
|
rdata = ISC_LIST_NEXT(rdata, link);
|
1999-01-27 13:38:21 +00:00
|
|
|
}
|
|
|
|
return (ISC_FALSE);
|
|
|
|
}
|
1999-03-22 06:21:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns ISC_TRUE if the 'rdata' is already on 'rdatalist'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static isc_boolean_t
|
|
|
|
on_list(dns_rdatalist_t *rdatalist, dns_rdata_t *rdata) {
|
|
|
|
dns_rdata_t *rdata2;
|
|
|
|
|
|
|
|
rdata2 = ISC_LIST_HEAD(rdatalist->rdata);
|
|
|
|
while (rdata2 != NULL) {
|
|
|
|
if (dns_rdata_compare(rdata, rdata2) == 0)
|
|
|
|
return (ISC_TRUE);
|
|
|
|
rdata2 = ISC_LIST_NEXT(rdata2, link);
|
|
|
|
}
|
|
|
|
return (ISC_FALSE);
|
|
|
|
}
|