diff --git a/bin/tests/.cvsignore b/bin/tests/.cvsignore index b065c9c783..f30b5d28db 100644 --- a/bin/tests/.cvsignore +++ b/bin/tests/.cvsignore @@ -9,3 +9,5 @@ task_test timer_test wire_test rdata_test +master_test +rbt_test diff --git a/bin/tests/Makefile.in b/bin/tests/Makefile.in index dbbeb9ce25..d5dbeb8ec3 100644 --- a/bin/tests/Makefile.in +++ b/bin/tests/Makefile.in @@ -23,7 +23,8 @@ TARGETS = lex_test \ rbt_test \ rdata_test \ rwlock_test \ - wire_test + wire_test \ + master_test @BIND9_MAKE_RULES@ @@ -57,5 +58,8 @@ rwlock_test: rwlock_test.o ../../lib/isc/libisc.a ../../lib/dns/libdns.a wire_test: wire_test.o ../../lib/isc/libisc.a ../../lib/dns/libdns.a ${CC} -o $@ wire_test.o ${LIBS} +master_test: master_test.o ../../lib/isc/libisc.a ../../lib/dns/libdns.a + ${CC} -o $@ master_test.o ${LIBS} + clean distclean:: rm -f ${TARGETS} diff --git a/bin/tests/master_test.c b/bin/tests/master_test.c new file mode 100644 index 0000000000..3a4975eab9 --- /dev/null +++ b/bin/tests/master_test.c @@ -0,0 +1,72 @@ +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +dns_result_t print_dataset(dns_name_t *owner, dns_rdataset_t *dataset); + +isc_mem_t *mctx; + +dns_result_t +print_dataset(dns_name_t *owner, dns_rdataset_t *dataset) { + char buf[64*1024]; + isc_buffer_t target; + dns_result_t result; + + isc_buffer_init(&target, buf, 64*1024, ISC_BUFFERTYPE_TEXT); + result = dns_rdataset_totext(dataset, owner, ISC_FALSE, &target); + if (result == DNS_R_SUCCESS) + fprintf(stdout, "%.*s\n", (int)target.used, + (char*)target.base); + else + fprintf(stdout, "dns_rdataset_totext: %s\n", + dns_result_totext(result)); + + return (DNS_R_SUCCESS); +} + +int +main(int argc, char *argv[]) { + dns_result_t result; + dns_name_t origin; + isc_buffer_t source; + isc_buffer_t target; + unsigned char name_buf[255]; + + argc = argc; + + RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); + + if (argv[1]) { + isc_buffer_init(&source, argv[1], strlen(argv[1]), + ISC_BUFFERTYPE_TEXT); + isc_buffer_add(&source, strlen(argv[1])); + isc_buffer_setactive(&source, strlen(argv[1])); + isc_buffer_init(&target, name_buf, 255, ISC_BUFFERTYPE_BINARY); + dns_name_init(&origin, NULL); + result = dns_name_fromtext(&origin, &source, dns_rootname, + ISC_FALSE, &target); + if (result != DNS_R_SUCCESS) { + fprintf(stdout, "dns_name_fromtext: %s\n", + dns_result_totext(result)); + exit(1); + } + + + result = dns_load_master(argv[1], &origin, 1, + print_dataset, mctx); + fprintf(stdout, "dns_load_master: %s\n", + dns_result_totext(result)); + } + exit(0); +} diff --git a/lib/dns/master.c b/lib/dns/master.c index 078d9b6d08..cc3e6e4655 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -68,7 +68,14 @@ dns_load_master(char *master_file, dns_name_t *origin, int rdcount_save = 0; int rdata_size = 0; unsigned char *target_mem = NULL; - int target_size = 64*1024; + int target_size = 128*1024; + unsigned char name_buf[5][255]; + isc_boolean_t name_in_use[5]; + int glue_in_use = -1; + int current_in_use = -1; + int new_in_use; + isc_buffer_t name; + isc_lexspecials_t specials; dns_name_init(¤t_name, NULL); dns_name_init(&glue_name, NULL); @@ -79,9 +86,17 @@ dns_load_master(char *master_file, dns_name_t *origin, if (isc_lex_create(mctx, 256, &lex) != ISC_R_SUCCESS) goto cleanup; + memset(specials, 0, sizeof specials); + specials['('] = 1; + specials[')'] = 1; + specials['"'] = 1; + isc_lex_setspecials(lex, specials); + isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE); + if (isc_lex_openfile(lex, master_file) != ISC_R_SUCCESS) goto cleanup; + target_mem = isc_mem_get(mctx, target_size); if (target_mem == NULL) { result = DNS_R_NOSPACE; @@ -90,6 +105,7 @@ dns_load_master(char *master_file, dns_name_t *origin, isc_buffer_init(&target, target_mem, target_size, ISC_BUFFERTYPE_BINARY); target_save = target; + memset(name_in_use, 0, 5 * sizeof(isc_boolean_t)); do { options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_INITIALWS | ISC_LEXOPT_DNSMULTILINE; @@ -117,6 +133,12 @@ dns_load_master(char *master_file, dns_name_t *origin, /* XXX "$" Support */ + for (new_in_use = 0; new_in_use < 5 ; new_in_use++) + if (!name_in_use[new_in_use]) + break; + INSIST(new_in_use < 5); + isc_buffer_init(&name, &name_buf[new_in_use][0], 255, + ISC_BUFFERTYPE_BINARY); dns_name_init(&new_name, NULL); isc_buffer_init(&buffer, token.value.as_region.base, token.value.as_region.length, @@ -124,9 +146,8 @@ dns_load_master(char *master_file, dns_name_t *origin, isc_buffer_add(&buffer, token.value.as_region.length); isc_buffer_setactive(&buffer, token.value.as_region.length); - /* XXX name memory */ result = dns_name_fromtext(&new_name, &buffer, - origin, ISC_FALSE, &target); + origin, ISC_FALSE, &name); if (result != DNS_R_SUCCESS) goto cleanup; @@ -139,6 +160,8 @@ dns_load_master(char *master_file, dns_name_t *origin, &glue_name, callback); if (result != DNS_R_SUCCESS) goto cleanup; + if (glue_in_use != -1) + name_in_use[glue_in_use] = ISC_FALSE; dns_name_invalidate(&glue_name); in_glue = ISC_FALSE; rdcount = rdcount_save; @@ -155,6 +178,8 @@ dns_load_master(char *master_file, dns_name_t *origin, rdlcount_save = rdlcount; target_save = target; glue_name = new_name; + glue_in_use = new_in_use; + name_in_use[glue_in_use] = ISC_TRUE; } else { result = commit(¤t_list, ¤t_name, @@ -163,9 +188,17 @@ dns_load_master(char *master_file, dns_name_t *origin, goto cleanup; rdcount = 0; rdlcount = 0; + 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; current_name = new_name; current_known = ISC_TRUE; current_has_delegation = ISC_FALSE; + isc_buffer_init(&target, target_mem, + target_size, + ISC_BUFFERTYPE_BINARY); } } } else { @@ -234,7 +267,7 @@ dns_load_master(char *master_file, dns_name_t *origin, else this = ISC_LIST_HEAD(current_list); - while ((this = ISC_LIST_HEAD(current_list)) != NULL) { + while (this != NULL) { if (this->type == type) break; this = ISC_LIST_NEXT(this, link); @@ -283,6 +316,21 @@ dns_load_master(char *master_file, dns_name_t *origin, goto cleanup; ISC_LIST_PREPEND(this->rdata, &rdata[rdcount], link); rdcount++; + /* We must have at least 64k as rdlen is 61 bits. */ + if (target.used > (64*1024)) { + result = commit(¤t_list, ¤t_name, callback); + if (result != DNS_R_SUCCESS) + goto cleanup; + result = commit(&glue_list, &glue_name, callback); + if (result != DNS_R_SUCCESS) + goto cleanup; + rdcount = 0; + rdlcount = 0; + in_glue = ISC_FALSE; + current_has_delegation = ISC_FALSE; + isc_buffer_init(&target, target_mem, target_size, + ISC_BUFFERTYPE_BINARY); + } } while (!done); result = commit(¤t_list, ¤t_name, callback); if (result != DNS_R_SUCCESS) @@ -452,6 +500,7 @@ is_glue(rdatalist_head_t *head, dns_name_t *owner) { dns_name_fromregion(&name, ®ion); if (dns_name_compare(&name, owner) == 0) return (ISC_TRUE); + rdata = ISC_LIST_NEXT(rdata, link); } return (ISC_FALSE); }