mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 14:07:59 +00:00
Added BIND 8.x ttl processing.
Allow ttl / class to be specified in any order. Suppress duplicate rdata. Additional commentry.
This commit is contained in:
326
lib/dns/master.c
326
lib/dns/master.c
@@ -15,12 +15,14 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: master.c,v 1.13 1999/03/06 04:08:29 halley Exp $ */
|
/* $Id: master.c,v 1.14 1999/03/22 06:21:29 marka Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include <isc/lex.h>
|
#include <isc/lex.h>
|
||||||
#include <isc/list.h>
|
#include <isc/list.h>
|
||||||
@@ -37,6 +39,33 @@
|
|||||||
#include <dns/rdatatype.h>
|
#include <dns/rdatatype.h>
|
||||||
#include <dns/rdata.h>
|
#include <dns/rdata.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
#define NBUFS 3
|
||||||
|
#define MAXWIRESZ 255
|
||||||
|
|
||||||
|
/*
|
||||||
|
*<2A>Target buffer size and minimum target size.
|
||||||
|
* 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)
|
||||||
|
|
||||||
typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
|
typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
|
||||||
|
|
||||||
static dns_result_t commit(dns_rdatacallbacks_t *, rdatalist_head_t *,
|
static dns_result_t commit(dns_rdatacallbacks_t *, rdatalist_head_t *,
|
||||||
@@ -49,37 +78,39 @@ static dns_rdatalist_t *grow_rdatalist(int, dns_rdatalist_t *, int,
|
|||||||
static dns_rdata_t *grow_rdata(int, dns_rdata_t *, int,
|
static dns_rdata_t *grow_rdata(int, dns_rdata_t *, int,
|
||||||
rdatalist_head_t *, rdatalist_head_t *,
|
rdatalist_head_t *, rdatalist_head_t *,
|
||||||
isc_mem_t *);
|
isc_mem_t *);
|
||||||
|
static isc_boolean_t bind_ttl(char *s, isc_uint32_t *ttl);
|
||||||
|
static isc_boolean_t on_list(dns_rdatalist_t *this, dns_rdata_t *rdata);
|
||||||
|
|
||||||
#define GETTOKEN(lexer, options, token, eol) \
|
#define GETTOKEN(lexer, options, token, eol) \
|
||||||
do { \
|
do { \
|
||||||
unsigned int __o; \
|
unsigned int isc_o; \
|
||||||
isc_result_t __r; \
|
isc_result_t isc_r; \
|
||||||
isc_token_t *__t = (token); \
|
isc_token_t *isc_t = (token); \
|
||||||
__o = (options) | ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | \
|
isc_o = (options) | ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | \
|
||||||
ISC_LEXOPT_DNSMULTILINE; \
|
ISC_LEXOPT_DNSMULTILINE; \
|
||||||
if ((__r = isc_lex_gettoken(lexer, __o, __t)) \
|
isc_r = isc_lex_gettoken(lexer, isc_o, isc_t); \
|
||||||
!= ISC_R_SUCCESS) { \
|
if (isc_r != ISC_R_SUCCESS) { \
|
||||||
switch (__r) { \
|
switch (isc_r) { \
|
||||||
case ISC_R_NOMEMORY: \
|
case ISC_R_NOMEMORY: \
|
||||||
result = DNS_R_NOMEMORY; \
|
result = DNS_R_NOMEMORY; \
|
||||||
break; \
|
break; \
|
||||||
default: \
|
default: \
|
||||||
UNEXPECTED_ERROR(__FILE__, __LINE__, \
|
UNEXPECTED_ERROR(__FILE__, __LINE__, \
|
||||||
"isc_lex_gettoken() failed: %s\n", \
|
"isc_lex_gettoken() failed: %s\n", \
|
||||||
isc_result_totext(__r)); \
|
isc_result_totext(isc_r)); \
|
||||||
result = DNS_R_UNEXPECTED; \
|
result = DNS_R_UNEXPECTED; \
|
||||||
goto cleanup; \
|
goto cleanup; \
|
||||||
} \
|
} \
|
||||||
goto error_cleanup; \
|
goto error_cleanup; \
|
||||||
} \
|
} \
|
||||||
if (eol != ISC_TRUE) \
|
if (eol != ISC_TRUE) \
|
||||||
if (__t->type == isc_tokentype_eol || \
|
if (isc_t->type == isc_tokentype_eol || \
|
||||||
__t->type == isc_tokentype_eof) { \
|
isc_t->type == isc_tokentype_eof) { \
|
||||||
(*callbacks->error)(callbacks, \
|
(*callbacks->error)(callbacks, \
|
||||||
"dns_load_master: %s:%d unexpected end of %s\n", \
|
"dns_load_master: %s:%d unexpected end of %s\n", \
|
||||||
master_file, \
|
master_file, \
|
||||||
isc_lex_getsourceline(lex), \
|
isc_lex_getsourceline(lex), \
|
||||||
(__t->type == isc_tokentype_eol) ? \
|
(isc_t->type == isc_tokentype_eol) ? \
|
||||||
"line" : "file"); \
|
"line" : "file"); \
|
||||||
result = DNS_R_UNEXPECTEDEND; \
|
result = DNS_R_UNEXPECTEDEND; \
|
||||||
goto cleanup; \
|
goto cleanup; \
|
||||||
@@ -108,6 +139,7 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
isc_boolean_t finish_origin = ISC_FALSE;
|
isc_boolean_t finish_origin = ISC_FALSE;
|
||||||
isc_boolean_t finish_include = ISC_FALSE;
|
isc_boolean_t finish_include = ISC_FALSE;
|
||||||
isc_boolean_t read_till_eol = ISC_FALSE;
|
isc_boolean_t read_till_eol = ISC_FALSE;
|
||||||
|
isc_boolean_t warn_1035 = ISC_TRUE; /* XXX Arguement? */
|
||||||
char *include_file = NULL;
|
char *include_file = NULL;
|
||||||
isc_token_t token;
|
isc_token_t token;
|
||||||
isc_lex_t *lex = NULL;
|
isc_lex_t *lex = NULL;
|
||||||
@@ -130,9 +162,9 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
int rdcount_save = 0;
|
int rdcount_save = 0;
|
||||||
int rdata_size = 0;
|
int rdata_size = 0;
|
||||||
unsigned char *target_mem = NULL;
|
unsigned char *target_mem = NULL;
|
||||||
int target_size = 128*1024;
|
int target_size = TSIZ;
|
||||||
unsigned char name_buf[5][255];
|
unsigned char name_buf[NBUFS][MAXWIRESZ];
|
||||||
isc_boolean_t name_in_use[5];
|
isc_boolean_t name_in_use[NBUFS];
|
||||||
int glue_in_use = -1;
|
int glue_in_use = -1;
|
||||||
int current_in_use = -1;
|
int current_in_use = -1;
|
||||||
int origin_in_use = -1;
|
int origin_in_use = -1;
|
||||||
@@ -157,6 +189,9 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
ISC_LIST_INIT(glue_list);
|
ISC_LIST_INIT(glue_list);
|
||||||
ISC_LIST_INIT(current_list);
|
ISC_LIST_INIT(current_list);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up lexer to process master file syntax.
|
||||||
|
*/
|
||||||
iresult = isc_lex_create(mctx, 256, &lex);
|
iresult = isc_lex_create(mctx, 256, &lex);
|
||||||
if (iresult != ISC_R_SUCCESS) {
|
if (iresult != ISC_R_SUCCESS) {
|
||||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||||
@@ -172,6 +207,9 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
isc_lex_setspecials(lex, specials);
|
isc_lex_setspecials(lex, specials);
|
||||||
isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
|
isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open master file.
|
||||||
|
*/
|
||||||
iresult = isc_lex_openfile(lex, master_file);
|
iresult = isc_lex_openfile(lex, master_file);
|
||||||
if (iresult != ISC_R_SUCCESS) {
|
if (iresult != ISC_R_SUCCESS) {
|
||||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||||
@@ -180,6 +218,10 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
target_mem = isc_mem_get(mctx, target_size);
|
||||||
if (target_mem == NULL) {
|
if (target_mem == NULL) {
|
||||||
result = DNS_R_NOMEMORY;
|
result = DNS_R_NOMEMORY;
|
||||||
@@ -188,7 +230,9 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
isc_buffer_init(&target, target_mem, target_size,
|
isc_buffer_init(&target, target_mem, target_size,
|
||||||
ISC_BUFFERTYPE_BINARY);
|
ISC_BUFFERTYPE_BINARY);
|
||||||
target_save = target;
|
target_save = target;
|
||||||
memset(name_in_use, 0, 5 * sizeof(isc_boolean_t));
|
|
||||||
|
memset(name_in_use, 0, NBUFS * sizeof(isc_boolean_t));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
GETTOKEN(lex, ISC_LEXOPT_INITIALWS, &token, ISC_TRUE);
|
GETTOKEN(lex, ISC_LEXOPT_INITIALWS, &token, ISC_TRUE);
|
||||||
|
|
||||||
@@ -215,10 +259,17 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
result = DNS_R_NOOWNER;
|
result = DNS_R_NOOWNER;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
/* still working on the same name */
|
/* Still working on the same name. */
|
||||||
} else if (token.type == isc_tokentype_string) {
|
} else if (token.type == isc_tokentype_string) {
|
||||||
|
|
||||||
/* "$" Support */
|
/*
|
||||||
|
* "$" Support.
|
||||||
|
*
|
||||||
|
* "$ORIGIN" and "$INCLUDE" can both take domain names.
|
||||||
|
* The processing of "$ORIGIN" and "$INCLUDE" extends
|
||||||
|
* across the normal domain name processing.
|
||||||
|
*/
|
||||||
|
|
||||||
if (strcasecmp(token.value.as_pointer,
|
if (strcasecmp(token.value.as_pointer,
|
||||||
"$ORIGIN") == 0) {
|
"$ORIGIN") == 0) {
|
||||||
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
||||||
@@ -228,8 +279,16 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
"$TTL") == 0) {
|
"$TTL") == 0) {
|
||||||
GETTOKEN(lex, ISC_LEXOPT_NUMBER, &token,
|
GETTOKEN(lex, ISC_LEXOPT_NUMBER, &token,
|
||||||
ISC_FALSE);
|
ISC_FALSE);
|
||||||
|
if (token.type != isc_tokentype_number) {
|
||||||
|
(callbacks->warn)(callbacks,
|
||||||
|
"dns_load_master: %s:%d $TTL expects number\n",
|
||||||
|
master_file,
|
||||||
|
isc_lex_getsourceline(lex));
|
||||||
|
result = DNS_R_BADTTL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
ttl = token.value.as_ulong;
|
ttl = token.value.as_ulong;
|
||||||
if (ttl > 0x7fffffff) {
|
if (ttl > 0x7fffffffUL) {
|
||||||
(callbacks->warn)(callbacks,
|
(callbacks->warn)(callbacks,
|
||||||
"dns_load_master: %s:%d $TTL %lu > MAXTLL, setting TTL to 0\n",
|
"dns_load_master: %s:%d $TTL %lu > MAXTLL, setting TTL to 0\n",
|
||||||
master_file,
|
master_file,
|
||||||
@@ -273,12 +332,17 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
finish_include = ISC_TRUE;
|
finish_include = ISC_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (new_in_use = 0; new_in_use < 5 ; new_in_use++)
|
/*
|
||||||
|
* Normal processing resumes.
|
||||||
|
*
|
||||||
|
* Find a free name buffer.
|
||||||
|
*/
|
||||||
|
for (new_in_use = 0; new_in_use < NBUFS ; new_in_use++)
|
||||||
if (!name_in_use[new_in_use])
|
if (!name_in_use[new_in_use])
|
||||||
break;
|
break;
|
||||||
INSIST(new_in_use < 5);
|
INSIST(new_in_use < NBUFS);
|
||||||
isc_buffer_init(&name, &name_buf[new_in_use][0], 255,
|
isc_buffer_init(&name, &name_buf[new_in_use][0],
|
||||||
ISC_BUFFERTYPE_BINARY);
|
MAXWIRESZ, ISC_BUFFERTYPE_BINARY);
|
||||||
dns_name_init(&new_name, NULL);
|
dns_name_init(&new_name, NULL);
|
||||||
isc_buffer_init(&buffer, token.value.as_region.base,
|
isc_buffer_init(&buffer, token.value.as_region.base,
|
||||||
token.value.as_region.length,
|
token.value.as_region.length,
|
||||||
@@ -291,6 +355,10 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
|
|
||||||
if (result != DNS_R_SUCCESS)
|
if (result != DNS_R_SUCCESS)
|
||||||
goto error_cleanup;
|
goto error_cleanup;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish $ORIGIN / $INCLUDE processing if required.
|
||||||
|
*/
|
||||||
if (finish_origin) {
|
if (finish_origin) {
|
||||||
if (origin_in_use != -1)
|
if (origin_in_use != -1)
|
||||||
name_in_use[origin_in_use] = ISC_FALSE;
|
name_in_use[origin_in_use] = ISC_FALSE;
|
||||||
@@ -314,8 +382,16 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
finish_include = ISC_FALSE;
|
finish_include = ISC_FALSE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* commit glue and pop stacks
|
* "$" Processing Finished
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* state.
|
||||||
*/
|
*/
|
||||||
if (in_glue && dns_name_compare(&glue_name,
|
if (in_glue && dns_name_compare(&glue_name,
|
||||||
&new_name) != 0) {
|
&new_name) != 0) {
|
||||||
@@ -333,6 +409,13 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
target = target_save;
|
target = target_save;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
if (!in_glue && (!current_known ||
|
if (!in_glue && (!current_known ||
|
||||||
dns_name_compare(¤t_name, &new_name) != 0)) {
|
dns_name_compare(¤t_name, &new_name) != 0)) {
|
||||||
if (current_has_delegation &&
|
if (current_has_delegation &&
|
||||||
@@ -375,14 +458,29 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
*/
|
||||||
|
|
||||||
type = 0;
|
type = 0;
|
||||||
rdclass = 0;
|
rdclass = 0;
|
||||||
|
|
||||||
GETTOKEN(lex, ISC_LEXOPT_NUMBER, &token, ISC_FALSE);
|
GETTOKEN(lex, ISC_LEXOPT_NUMBER, &token, ISC_FALSE);
|
||||||
|
|
||||||
|
if (token.type == isc_tokentype_string &&
|
||||||
|
dns_rdataclass_fromtext(&rdclass,
|
||||||
|
&token.value.as_textregion)
|
||||||
|
== DNS_R_SUCCESS)
|
||||||
|
GETTOKEN(lex, ISC_LEXOPT_NUMBER, &token, ISC_FALSE);
|
||||||
|
|
||||||
if (token.type == isc_tokentype_number) {
|
if (token.type == isc_tokentype_number) {
|
||||||
ttl = token.value.as_ulong;
|
ttl = token.value.as_ulong;
|
||||||
if (ttl > 0x7fffffff) {
|
if (ttl > 0x7fffffffUL) {
|
||||||
(callbacks->warn)(callbacks,
|
(callbacks->warn)(callbacks,
|
||||||
"dns_load_master: %s:%d TTL %lu > maxtll, setting ttl to 0\n",
|
"dns_load_master: %s:%d TTL %lu > maxtll, setting ttl to 0\n",
|
||||||
master_file,
|
master_file,
|
||||||
@@ -392,15 +490,28 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
}
|
}
|
||||||
ttl_known = ISC_TRUE;
|
ttl_known = ISC_TRUE;
|
||||||
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
||||||
|
} else if (bind_ttl(token.value.as_pointer, &ttl)) {
|
||||||
|
ttl_known = ISC_TRUE;
|
||||||
|
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
||||||
} else if (!ttl_known && !default_ttl_known) {
|
} else if (!ttl_known && !default_ttl_known) {
|
||||||
|
/*
|
||||||
|
* BIND 4 / 8 'USE_SOA_MINIMUM' could be set here.
|
||||||
|
*/
|
||||||
(*callbacks->error)(callbacks,
|
(*callbacks->error)(callbacks,
|
||||||
"%s: %s:%d no TTL specified\n",
|
"%s: %s:%d no TTL specified\n",
|
||||||
"dns_load_master", master_file,
|
"dns_load_master", master_file,
|
||||||
isc_lex_getsourceline(lex));
|
isc_lex_getsourceline(lex));
|
||||||
result = DNS_R_NOTTL;
|
result = DNS_R_NOTTL;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else if (default_ttl_known)
|
} else if (default_ttl_known) {
|
||||||
ttl = default_ttl;
|
ttl = default_ttl;
|
||||||
|
} else if (warn_1035) {
|
||||||
|
(*callbacks->warn)(callbacks,
|
||||||
|
"%s: %s:%d using RFC 1035 TTL semantics\n",
|
||||||
|
"dns_load_master", master_file,
|
||||||
|
isc_lex_getsourceline(lex));
|
||||||
|
warn_1035 = ISC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (token.type != isc_tokentype_string) {
|
if (token.type != isc_tokentype_string) {
|
||||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||||
@@ -409,8 +520,8 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dns_rdataclass_fromtext(&rdclass,
|
if (rdclass == 0 &&
|
||||||
&token.value.as_textregion)
|
dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion)
|
||||||
== DNS_R_SUCCESS)
|
== DNS_R_SUCCESS)
|
||||||
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
GETTOKEN(lex, 0, &token, ISC_FALSE);
|
||||||
|
|
||||||
@@ -420,12 +531,16 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
result = DNS_R_UNEXPECTED;
|
result = DNS_R_UNEXPECTED;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = dns_rdatatype_fromtext(&type,
|
result = dns_rdatatype_fromtext(&type,
|
||||||
&token.value.as_textregion);
|
&token.value.as_textregion);
|
||||||
if (result != DNS_R_SUCCESS)
|
if (result != DNS_R_SUCCESS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the class specified does not match the zone's class
|
||||||
|
* print out a error message and exit.
|
||||||
|
*/
|
||||||
if (rdclass != 0 && rdclass != zclass) {
|
if (rdclass != 0 && rdclass != zclass) {
|
||||||
char buf1[32];
|
char buf1[32];
|
||||||
char buf2[32];
|
char buf2[32];
|
||||||
@@ -466,19 +581,14 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!in_glue && type == dns_rdatatype_soa &&
|
|
||||||
dns_name_compare(top, ¤t_name) == 0) {
|
|
||||||
(*soacount)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_glue && type == dns_rdatatype_ns &&
|
|
||||||
dns_name_compare(top, ¤t_name) == 0) {
|
|
||||||
(*nscount)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == dns_rdatatype_ns && !in_glue)
|
if (type == dns_rdatatype_ns && !in_glue)
|
||||||
current_has_delegation = ISC_TRUE;
|
current_has_delegation = ISC_TRUE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find type in rdatalist.
|
||||||
|
* If it does not exit create new one and prepend to list
|
||||||
|
* as this will mimimise list traversal.
|
||||||
|
*/
|
||||||
if (in_glue)
|
if (in_glue)
|
||||||
this = ISC_LIST_HEAD(glue_list);
|
this = ISC_LIST_HEAD(glue_list);
|
||||||
else
|
else
|
||||||
@@ -489,10 +599,11 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
break;
|
break;
|
||||||
this = ISC_LIST_NEXT(this, link);
|
this = ISC_LIST_NEXT(this, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this == NULL) {
|
if (this == NULL) {
|
||||||
if (rdlcount == rdatalist_size) {
|
if (rdlcount == rdatalist_size) {
|
||||||
new_rdatalist =
|
new_rdatalist =
|
||||||
grow_rdatalist(rdatalist_size + 32,
|
grow_rdatalist(rdatalist_size + RDLSZ,
|
||||||
rdatalist,
|
rdatalist,
|
||||||
rdatalist_size,
|
rdatalist_size,
|
||||||
¤t_list,
|
¤t_list,
|
||||||
@@ -503,7 +614,7 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
goto error_cleanup;
|
goto error_cleanup;
|
||||||
}
|
}
|
||||||
rdatalist = new_rdatalist;
|
rdatalist = new_rdatalist;
|
||||||
rdatalist_size += 32;
|
rdatalist_size += RDLSZ;
|
||||||
}
|
}
|
||||||
this = &rdatalist[rdlcount++];
|
this = &rdatalist[rdlcount++];
|
||||||
this->type = type;
|
this->type = type;
|
||||||
@@ -524,26 +635,49 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
ttl = this->ttl;
|
ttl = this->ttl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a rdata structure.
|
||||||
|
*/
|
||||||
if (rdcount == rdata_size) {
|
if (rdcount == rdata_size) {
|
||||||
new_rdata = grow_rdata(rdata_size + 512, rdata,
|
new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
|
||||||
rdata_size, ¤t_list,
|
rdata_size, ¤t_list,
|
||||||
&glue_list, mctx);
|
&glue_list, mctx);
|
||||||
if (new_rdata == NULL) {
|
if (new_rdata == NULL) {
|
||||||
result = DNS_R_NOMEMORY;
|
result = DNS_R_NOMEMORY;
|
||||||
goto error_cleanup;
|
goto error_cleanup;
|
||||||
}
|
}
|
||||||
rdata_size += 512;
|
rdata_size += RDSZ;
|
||||||
rdata = new_rdata;
|
rdata = new_rdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read rdata contents.
|
||||||
|
*/
|
||||||
result = dns_rdata_fromtext(&rdata[rdcount], rdclass, type,
|
result = dns_rdata_fromtext(&rdata[rdcount], rdclass, type,
|
||||||
lex, &origin_name, ISC_FALSE, &target,
|
lex, &origin_name, ISC_FALSE, &target,
|
||||||
callbacks);
|
callbacks);
|
||||||
if (result != DNS_R_SUCCESS)
|
if (result != DNS_R_SUCCESS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
ISC_LIST_PREPEND(this->rdata, &rdata[rdcount], link);
|
|
||||||
rdcount++;
|
/*
|
||||||
/* We must have at least 64k as rdlen is 16 bits. */
|
* If the new rdata is not on the list add it.
|
||||||
if (target.used > (64*1024)) {
|
*
|
||||||
|
* 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])) {
|
||||||
|
ISC_LIST_PREPEND(this->rdata, &rdata[rdcount], link);
|
||||||
|
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) {
|
||||||
result = commit(callbacks, ¤t_list,
|
result = commit(callbacks, ¤t_list,
|
||||||
¤t_name);
|
¤t_name);
|
||||||
if (result != DNS_R_SUCCESS)
|
if (result != DNS_R_SUCCESS)
|
||||||
@@ -562,6 +696,9 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
ISC_BUFFERTYPE_BINARY);
|
ISC_BUFFERTYPE_BINARY);
|
||||||
}
|
}
|
||||||
} while (!done);
|
} while (!done);
|
||||||
|
/*
|
||||||
|
* Commit what has not yet been committed.
|
||||||
|
*/
|
||||||
result = commit(callbacks, ¤t_list, ¤t_name);
|
result = commit(callbacks, ¤t_list, ¤t_name);
|
||||||
if (result != DNS_R_SUCCESS)
|
if (result != DNS_R_SUCCESS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@@ -597,6 +734,10 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin,
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Grow the slab of dns_rdatalist_t structures.
|
||||||
|
* Re-link glue and current list.
|
||||||
|
*/
|
||||||
static dns_rdatalist_t *
|
static dns_rdatalist_t *
|
||||||
grow_rdatalist(int new_len, dns_rdatalist_t *old, int old_len,
|
grow_rdatalist(int new_len, dns_rdatalist_t *old, int old_len,
|
||||||
rdatalist_head_t *current, rdatalist_head_t *glue,
|
rdatalist_head_t *current, rdatalist_head_t *glue,
|
||||||
@@ -643,6 +784,10 @@ grow_rdatalist(int new_len, dns_rdatalist_t *old, int old_len,
|
|||||||
return (new);
|
return (new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Grow the slab of rdata structs.
|
||||||
|
* Re-link the current and glue chains.
|
||||||
|
*/
|
||||||
static dns_rdata_t *
|
static dns_rdata_t *
|
||||||
grow_rdata(int new_len, dns_rdata_t *old, int old_len,
|
grow_rdata(int new_len, dns_rdata_t *old, int old_len,
|
||||||
rdatalist_head_t *current, rdatalist_head_t *glue,
|
rdatalist_head_t *current, rdatalist_head_t *glue,
|
||||||
@@ -658,7 +803,10 @@ grow_rdata(int new_len, dns_rdata_t *old, int old_len,
|
|||||||
if (new == NULL)
|
if (new == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
memset(new, 0, new_len * sizeof *new);
|
memset(new, 0, new_len * sizeof *new);
|
||||||
/* copy current relinking */
|
|
||||||
|
/*
|
||||||
|
* Copy current relinking.
|
||||||
|
*/
|
||||||
this = ISC_LIST_HEAD(*current);
|
this = ISC_LIST_HEAD(*current);
|
||||||
while (this != NULL) {
|
while (this != NULL) {
|
||||||
ISC_LIST_INIT(save);
|
ISC_LIST_INIT(save);
|
||||||
@@ -674,7 +822,10 @@ grow_rdata(int new_len, dns_rdata_t *old, int old_len,
|
|||||||
}
|
}
|
||||||
this = ISC_LIST_NEXT(this, link);
|
this = ISC_LIST_NEXT(this, link);
|
||||||
}
|
}
|
||||||
/* copy glue relinking */
|
|
||||||
|
/*
|
||||||
|
* Copy glue relinking.
|
||||||
|
*/
|
||||||
this = ISC_LIST_HEAD(*glue);
|
this = ISC_LIST_HEAD(*glue);
|
||||||
while (this != NULL) {
|
while (this != NULL) {
|
||||||
ISC_LIST_INIT(save);
|
ISC_LIST_INIT(save);
|
||||||
@@ -696,6 +847,11 @@ grow_rdata(int new_len, dns_rdata_t *old, int old_len,
|
|||||||
return (new);
|
return (new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert each element from a rdatalist_t to rdataset then call commit.
|
||||||
|
* Unlink each element as we go.
|
||||||
|
*/
|
||||||
|
|
||||||
static dns_result_t
|
static dns_result_t
|
||||||
commit(dns_rdatacallbacks_t *callbacks, rdatalist_head_t *head,
|
commit(dns_rdatacallbacks_t *callbacks, rdatalist_head_t *head,
|
||||||
dns_name_t *owner)
|
dns_name_t *owner)
|
||||||
@@ -716,6 +872,10 @@ commit(dns_rdatacallbacks_t *callbacks, rdatalist_head_t *head,
|
|||||||
return (DNS_R_SUCCESS);
|
return (DNS_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns ISC_TRUE if one of the NS rdata's contains 'owner'.
|
||||||
|
*/
|
||||||
|
|
||||||
static isc_boolean_t
|
static isc_boolean_t
|
||||||
is_glue(rdatalist_head_t *head, dns_name_t *owner) {
|
is_glue(rdatalist_head_t *head, dns_name_t *owner) {
|
||||||
dns_rdatalist_t *this;
|
dns_rdatalist_t *this;
|
||||||
@@ -744,3 +904,71 @@ is_glue(rdatalist_head_t *head, dns_name_t *owner) {
|
|||||||
}
|
}
|
||||||
return (ISC_FALSE);
|
return (ISC_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert BIND 8.x ttl representation to a number.
|
||||||
|
* Returns ISC_TRUE is string contained a valid string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static isc_boolean_t
|
||||||
|
bind_ttl(char *s, isc_uint32_t *ttl) {
|
||||||
|
isc_uint32_t tmp = 0;
|
||||||
|
unsigned long n;
|
||||||
|
char *e;
|
||||||
|
|
||||||
|
do {
|
||||||
|
n = strtoul(s, &e, 10);
|
||||||
|
if (s == e)
|
||||||
|
return (ISC_FALSE);
|
||||||
|
switch (*e) {
|
||||||
|
case 'w':
|
||||||
|
case 'W':
|
||||||
|
tmp += n * 7 * 24 * 3600;
|
||||||
|
s = e + 1;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
tmp += n * 24 * 3600;
|
||||||
|
s = e + 1;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
case 'H':
|
||||||
|
tmp += n * 3600;
|
||||||
|
s = e + 1;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
tmp += n * 60;
|
||||||
|
s = e + 1;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
tmp += n * 60;
|
||||||
|
s = e + 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return (ISC_FALSE);
|
||||||
|
}
|
||||||
|
} while (*s != 0);
|
||||||
|
if (tmp > 0x7fffffffUL)
|
||||||
|
tmp = 0;
|
||||||
|
*ttl = tmp;
|
||||||
|
return (ISC_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user