2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: master.c,v 1.122.2.9 2004/03/09 06:11:03 marka Exp $ */
22 #include <isc/event.h>
24 #include <isc/magic.h>
26 #include <isc/print.h>
27 #include <isc/serial.h>
28 #include <isc/stdtime.h>
29 #include <isc/string.h>
33 #include <dns/callbacks.h>
34 #include <dns/events.h>
35 #include <dns/fixedname.h>
36 #include <dns/master.h>
38 #include <dns/rdata.h>
39 #include <dns/rdataclass.h>
40 #include <dns/rdatalist.h>
41 #include <dns/rdataset.h>
42 #include <dns/rdatastruct.h>
43 #include <dns/rdatatype.h>
44 #include <dns/result.h>
50 * Grow the number of dns_rdatalist_t (RDLSZ) and dns_rdata_t (RDSZ) structures
51 * by these sizes when we need to.
53 * RDLSZ reflects the number of different types with the same name expected.
54 * RDSZ reflects the number of rdata expected at a give name that can fit into
65 * Target buffer size and minimum target size.
66 * MINTSIZ must be big enough to hold the largest rdata record.
70 #define TSIZ (128*1024)
72 * max message size - header - root - type - class - ttl - rdlen
74 #define MINTSIZ (65535 - 12 - 1 - 2 - 2 - 4 - 2)
76 * Size for tokens in the presentation format,
77 * The largest tokens are the base64 blocks in KEY and CERT records,
78 * Largest key allowed is about 1372 bytes but
79 * there is no fixed upper bound on CERT records.
80 * 2K is too small for some X.509s, 8K is overkill.
82 #define TOKENSIZ (8*1024)
84 #define DNS_MASTER_BUFSZ 2048
86 typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
88 typedef struct dns_incctx dns_incctx_t;
91 * Master file load state.
98 dns_rdatacallbacks_t *callbacks;
100 dns_loaddonefunc_t done;
102 unsigned int options;
103 isc_boolean_t ttl_known;
104 isc_boolean_t default_ttl_known;
105 isc_boolean_t warn_1035;
106 isc_boolean_t warn_sigexpired;
107 isc_boolean_t seen_include;
109 isc_uint32_t default_ttl;
110 dns_rdataclass_t zclass;
111 dns_fixedname_t fixed_top;
112 dns_name_t *top; /* top of zone */
113 /* Which fixed buffers we are using? */
114 unsigned int loop_cnt; /* records per quantum,
116 isc_boolean_t canceled;
120 isc_uint32_t references;
125 dns_incctx_t *parent;
129 dns_fixedname_t fixed[NBUFS]; /* working buffers */
130 unsigned int in_use[NBUFS]; /* covert to bitmap? */
135 unsigned int glue_line;
136 unsigned int current_line;
139 #define DNS_LCTX_MAGIC ISC_MAGIC('L','c','t','x')
140 #define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
143 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx);
146 commit(dns_rdatacallbacks_t *, dns_loadctx_t *, rdatalist_head_t *,
147 dns_name_t *, const char *, unsigned int);
150 is_glue(rdatalist_head_t *, dns_name_t *);
152 static dns_rdatalist_t *
153 grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *,
154 rdatalist_head_t *, isc_mem_t *mctx);
157 grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *,
161 load_quantum(isc_task_t *task, isc_event_t *event);
164 task_send(dns_loadctx_t *lctx);
167 loadctx_destroy(dns_loadctx_t *lctx);
169 #define GETTOKEN(lexer, options, token, eol) \
171 result = gettoken(lexer, options, token, eol, callbacks); \
173 case ISC_R_SUCCESS: \
175 case ISC_R_UNEXPECTED: \
176 goto insist_and_cleanup; \
178 if (MANYERRS(lctx, result)) { \
179 SETRESULT(lctx, result); \
181 read_till_eol = ISC_TRUE; \
184 goto log_and_cleanup; \
186 if ((token)->type == isc_tokentype_special) { \
187 result = DNS_R_SYNTAX; \
188 if (MANYERRS(lctx, result)) { \
189 SETRESULT(lctx, result); \
191 read_till_eol = ISC_TRUE; \
194 goto log_and_cleanup; \
200 result = commit(callbacks, lctx, ¤t_list, \
201 ictx->current, source, ictx->current_line); \
202 if (MANYERRS(lctx, result)) { \
203 SETRESULT(lctx, result); \
204 } else if (result != ISC_R_SUCCESS) \
205 goto insist_and_cleanup; \
206 result = commit(callbacks, lctx, &glue_list, \
207 ictx->glue, source, ictx->glue_line); \
208 if (MANYERRS(lctx, result)) { \
209 SETRESULT(lctx, result); \
210 } else if (result != ISC_R_SUCCESS) \
211 goto insist_and_cleanup; \
214 isc_buffer_init(&target, target_mem, target_size); \
215 rdcount_save = rdcount; \
216 rdlcount_save = rdlcount; \
219 #define WARNUNEXPECTEDEOF(lexer) \
221 if (isc_lex_isfile(lexer)) \
222 (*callbacks->warn)(callbacks, \
223 "%s: file does not end with newline", \
229 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE); \
230 if (token.type != isc_tokentype_eol) { \
231 isc_lex_ungettoken(lctx->lex, &token); \
232 result = DNS_R_EXTRATOKEN; \
233 if (MANYERRS(lctx, result)) { \
234 SETRESULT(lctx, result); \
236 read_till_eol = ISC_TRUE; \
238 } else if (result != ISC_R_SUCCESS) \
239 goto log_and_cleanup; \
243 #define MANYERRS(lctx, result) \
244 ((result != ISC_R_SUCCESS) && \
245 ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
247 #define SETRESULT(lctx, r) \
249 if ((lctx)->result == ISC_R_SUCCESS) \
250 (lctx)->result = r; \
253 #define LOGITFILE(result, filename) \
254 if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \
255 result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \
256 result == ISC_R_NOPERM) \
257 (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \
258 "dns_master_load", source, line, \
259 filename, dns_result_totext(result)); \
262 #define LOGIT(result) \
263 if (result == ISC_R_NOMEMORY) \
264 (*callbacks->error)(callbacks, "dns_master_load: %s", \
265 dns_result_totext(result)); \
267 (*callbacks->error)(callbacks, "%s: %s:%lu: %s", \
269 source, line, dns_result_totext(result))
271 static inline isc_result_t
272 gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token,
273 isc_boolean_t eol, dns_rdatacallbacks_t *callbacks)
277 options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE |
279 result = isc_lex_gettoken(lex, options, token);
280 if (result != ISC_R_SUCCESS) {
283 return (ISC_R_NOMEMORY);
285 (*callbacks->error)(callbacks,
286 "dns_master_load: %s:%lu:"
287 " isc_lex_gettoken() failed: %s",
288 isc_lex_getsourcename(lex),
289 isc_lex_getsourceline(lex),
290 isc_result_totext(result));
296 if (token->type == isc_tokentype_eol ||
297 token->type == isc_tokentype_eof) {
298 (*callbacks->error)(callbacks,
299 "dns_master_load: %s:%lu: unexpected end of %s",
300 isc_lex_getsourcename(lex),
301 isc_lex_getsourceline(lex),
305 return (ISC_R_UNEXPECTEDEND);
307 return (ISC_R_SUCCESS);
312 dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
314 REQUIRE(target != NULL && *target == NULL);
315 REQUIRE(DNS_LCTX_VALID(source));
318 INSIST(source->references > 0);
319 source->references++;
320 INSIST(source->references != 0); /* Overflow? */
321 UNLOCK(&source->lock);
327 dns_loadctx_detach(dns_loadctx_t **lctxp) {
329 isc_boolean_t need_destroy = ISC_FALSE;
331 REQUIRE(lctxp != NULL);
333 REQUIRE(DNS_LCTX_VALID(lctx));
336 INSIST(lctx->references > 0);
338 if (lctx->references == 0)
339 need_destroy = ISC_TRUE;
343 loadctx_destroy(lctx);
348 incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
349 dns_incctx_t *parent;
352 parent = ictx->parent;
355 isc_mem_put(mctx, ictx, sizeof *ictx);
357 if (parent != NULL) {
364 loadctx_destroy(dns_loadctx_t *lctx) {
367 REQUIRE(DNS_LCTX_VALID(lctx));
370 if (lctx->inc != NULL)
371 incctx_destroy(lctx->mctx, lctx->inc);
373 if (lctx->lex != NULL) {
374 /* isc_lex_destroy() will close all open streams */
375 isc_lex_destroy(&lctx->lex);
377 if (lctx->task != NULL)
378 isc_task_detach(&lctx->task);
379 DESTROYLOCK(&lctx->lock);
381 isc_mem_attach(lctx->mctx, &mctx);
382 isc_mem_detach(&lctx->mctx);
383 isc_mem_put(mctx, lctx, sizeof(*lctx));
384 isc_mem_detach(&mctx);
388 incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
393 ictx = isc_mem_get(mctx, sizeof *ictx);
395 return (ISC_R_NOMEMORY);
397 for (i = 0; i < NBUFS; i++) {
398 dns_fixedname_init(&ictx->fixed[i]);
399 ictx->in_use[i] = ISC_FALSE;
402 ictx->origin_in_use = 0;
403 ictx->origin = dns_fixedname_name(&ictx->fixed[ictx->origin_in_use]);
404 ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
405 dns_name_toregion(origin, &r);
406 dns_name_fromregion(ictx->origin, &r);
409 ictx->current = NULL;
410 ictx->glue_in_use = -1;
411 ictx->current_in_use = -1;
413 ictx->drop = ISC_FALSE;
415 ictx->current_line = 0;
418 return (ISC_R_SUCCESS);
422 loadctx_create(isc_mem_t *mctx, unsigned int options, dns_name_t *top,
423 dns_rdataclass_t zclass, dns_name_t *origin,
424 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
425 dns_loaddonefunc_t done, void *done_arg,
426 dns_loadctx_t **lctxp)
431 isc_lexspecials_t specials;
433 REQUIRE(lctxp != NULL && *lctxp == NULL);
434 REQUIRE(callbacks != NULL);
435 REQUIRE(callbacks->add != NULL);
436 REQUIRE(callbacks->error != NULL);
437 REQUIRE(callbacks->warn != NULL);
438 REQUIRE(mctx != NULL);
439 REQUIRE(dns_name_isabsolute(top));
440 REQUIRE(dns_name_isabsolute(origin));
441 REQUIRE((task == NULL && done == NULL) ||
442 (task != NULL && done != NULL));
444 lctx = isc_mem_get(mctx, sizeof(*lctx));
446 return (ISC_R_NOMEMORY);
447 result = isc_mutex_init(&lctx->lock);
448 if (result != ISC_R_SUCCESS) {
449 isc_mem_put(mctx, lctx, sizeof *lctx);
450 UNEXPECTED_ERROR(__FILE__, __LINE__,
451 "isc_mutex_init() failed: %s",
452 isc_result_totext(result));
453 return (ISC_R_UNEXPECTED);
457 result = incctx_create(mctx, origin, &lctx->inc);
458 if (result != ISC_R_SUCCESS)
462 result = isc_lex_create(mctx, TOKENSIZ, &lctx->lex);
463 if (result != ISC_R_SUCCESS)
465 memset(specials, 0, sizeof specials);
469 isc_lex_setspecials(lctx->lex, specials);
470 isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE);
472 lctx->ttl_known = ISC_FALSE;
474 lctx->default_ttl_known = ISC_FALSE;
475 lctx->default_ttl = 0;
476 lctx->warn_1035 = ISC_TRUE; /* XXX Argument? */
477 lctx->warn_sigexpired = ISC_TRUE; /* XXX Argument? */
478 lctx->options = options;
479 lctx->seen_include = ISC_FALSE;
480 lctx->zclass = zclass;
481 lctx->result = ISC_R_SUCCESS;
483 dns_fixedname_init(&lctx->fixed_top);
484 lctx->top = dns_fixedname_name(&lctx->fixed_top);
485 dns_name_toregion(top, &r);
486 dns_name_fromregion(lctx->top, &r);
488 lctx->loop_cnt = (done != NULL) ? 100 : 0;
489 lctx->callbacks = callbacks;
492 isc_task_attach(task, &lctx->task);
494 lctx->done_arg = done_arg;
495 lctx->canceled = ISC_FALSE;
497 isc_mem_attach(mctx, &lctx->mctx);
498 lctx->references = 1; /* Implicit attach. */
499 lctx->magic = DNS_LCTX_MAGIC;
501 return (ISC_R_SUCCESS);
504 incctx_destroy(mctx, lctx->inc);
506 isc_mem_put(mctx, lctx, sizeof(*lctx));
511 genname(char *name, int it, char *buffer, size_t length) {
512 char fmt[sizeof("%04000000000d")];
524 while (*name != '\0') {
529 return (ISC_R_NOSPACE);
531 isc_textregion_consume(&r, 1);
535 /* Get format specifier. */
537 n = sscanf(name, "{%d,%u,%1[doxX]}",
538 &delta, &width, mode);
543 n = snprintf(fmt, sizeof(fmt),
547 n = snprintf(fmt, sizeof(fmt),
548 "%%0%u%c", width, mode[0]);
551 return (DNS_R_SYNTAX);
553 if (n >= sizeof(fmt))
554 return (ISC_R_NOSPACE);
555 /* Skip past closing brace. */
556 while (*name != '\0' && *name++ != '}')
559 n = snprintf(numbuf, sizeof(numbuf), fmt, it + delta);
560 if (n >= sizeof(numbuf))
561 return (ISC_R_NOSPACE);
563 while (*cp != '\0') {
565 return (ISC_R_NOSPACE);
567 isc_textregion_consume(&r, 1);
569 } else if (*name == '\\') {
571 return (ISC_R_NOSPACE);
573 isc_textregion_consume(&r, 1);
577 return (ISC_R_NOSPACE);
579 isc_textregion_consume(&r, 1);
582 return (ISC_R_NOSPACE);
584 isc_textregion_consume(&r, 1);
588 return (ISC_R_NOSPACE);
590 return (ISC_R_SUCCESS);
594 generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
595 const char *source, unsigned int line)
597 char *target_mem = NULL;
600 dns_fixedname_t ownerfixed;
602 dns_rdata_t rdata = DNS_RDATA_INIT;
603 dns_rdatacallbacks_t *callbacks;
604 dns_rdatalist_t rdatalist;
605 dns_rdatatype_t type;
606 rdatalist_head_t head;
608 int target_size = MINTSIZ; /* only one rdata at a time */
613 unsigned int start, stop, step, i;
617 callbacks = lctx->callbacks;
618 dns_fixedname_init(&ownerfixed);
619 owner = dns_fixedname_name(&ownerfixed);
622 target_mem = isc_mem_get(lctx->mctx, target_size);
623 rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_BUFSZ);
624 lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_BUFSZ);
625 if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) {
626 result = ISC_R_NOMEMORY;
629 isc_buffer_init(&target, target_mem, target_size);
631 n = sscanf(range, "%u-%u/%u", &start, &stop, &step);
632 if (n < 2 || stop < start) {
633 (*callbacks->error)(callbacks,
634 "%s: %s:%lu: invalid range '%s'",
635 "$GENERATE", source, line, range);
636 result = DNS_R_SYNTAX;
646 r.length = strlen(gtype);
647 result = dns_rdatatype_fromtext(&type, &r);
648 if (result != ISC_R_SUCCESS) {
649 (*callbacks->error)(callbacks,
650 "%s: %s:%lu: unknown RR type '%s'",
651 "$GENERATE", source, line, gtype);
656 case dns_rdatatype_ns:
657 case dns_rdatatype_ptr:
658 case dns_rdatatype_cname:
659 case dns_rdatatype_dname:
662 case dns_rdatatype_a:
663 case dns_rdatatype_aaaa:
664 if (lctx->zclass == dns_rdataclass_in ||
665 lctx->zclass == dns_rdataclass_hs)
669 (*callbacks->error)(callbacks,
670 "%s: %s:%lu: unsupported type '%s'",
671 "$GENERATE", source, line, gtype);
672 result = ISC_R_NOTIMPLEMENTED;
676 ISC_LIST_INIT(rdatalist.rdata);
677 ISC_LINK_INIT(&rdatalist, link);
678 for (i = start; i <= stop; i += step) {
679 result = genname(lhs, i, lhsbuf, DNS_MASTER_BUFSZ);
680 if (result != ISC_R_SUCCESS)
682 result = genname(rhs, i, rhsbuf, DNS_MASTER_BUFSZ);
683 if (result != ISC_R_SUCCESS)
686 isc_buffer_init(&buffer, lhsbuf, strlen(lhsbuf));
687 isc_buffer_add(&buffer, strlen(lhsbuf));
688 isc_buffer_setactive(&buffer, strlen(lhsbuf));
689 result = dns_name_fromtext(owner, &buffer, ictx->origin,
691 if (result != ISC_R_SUCCESS)
694 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
695 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
696 !dns_name_issubdomain(owner, lctx->top))
698 char namebuf[DNS_NAME_FORMATSIZE];
699 dns_name_format(owner, namebuf, sizeof(namebuf));
701 * Ignore out-of-zone data.
703 (*callbacks->warn)(callbacks,
704 "dns_master_load: %s:%lu: "
705 "ignoring out-of-zone data (%s)",
706 source, line, namebuf);
710 isc_buffer_init(&buffer, rhsbuf, strlen(rhsbuf));
711 isc_buffer_add(&buffer, strlen(rhsbuf));
712 isc_buffer_setactive(&buffer, strlen(rhsbuf));
714 result = isc_lex_openbuffer(lctx->lex, &buffer);
715 if (result != ISC_R_SUCCESS)
718 isc_buffer_init(&target, target_mem, target_size);
719 result = dns_rdata_fromtext(&rdata, lctx->zclass, type,
720 lctx->lex, ictx->origin, ISC_FALSE,
721 lctx->mctx, &target, callbacks);
722 isc_lex_close(lctx->lex);
723 if (result != ISC_R_SUCCESS)
726 rdatalist.type = type;
727 rdatalist.covers = 0;
728 rdatalist.rdclass = lctx->zclass;
729 rdatalist.ttl = lctx->ttl;
730 ISC_LIST_PREPEND(head, &rdatalist, link);
731 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
732 result = commit(callbacks, lctx, &head, owner, source, line);
733 ISC_LIST_UNLINK(rdatalist.rdata, &rdata, link);
734 if (result != ISC_R_SUCCESS)
736 dns_rdata_reset(&rdata);
738 result = ISC_R_SUCCESS;
742 if (result == ISC_R_NOMEMORY)
743 (*callbacks->error)(callbacks, "$GENERATE: %s",
744 dns_result_totext(result));
746 (*callbacks->error)(callbacks, "$GENERATE: %s:%lu: %s",
747 source, line, dns_result_totext(result));
750 INSIST(result != ISC_R_SUCCESS);
753 if (target_mem != NULL)
754 isc_mem_put(lctx->mctx, target_mem, target_size);
756 isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_BUFSZ);
758 isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_BUFSZ);
763 limit_ttl(dns_rdatacallbacks_t *callbacks, const char *source, unsigned int line,
766 if (*ttlp > 0x7fffffffUL) {
767 (callbacks->warn)(callbacks,
769 "$TTL %lu > MAXTTL, "
779 load(dns_loadctx_t *lctx) {
780 dns_rdataclass_t rdclass;
781 dns_rdatatype_t type, covers;
782 isc_uint32_t ttl_offset = 0;
783 dns_name_t *new_name;
784 isc_boolean_t current_has_delegation = ISC_FALSE;
785 isc_boolean_t done = ISC_FALSE;
786 isc_boolean_t finish_origin = ISC_FALSE;
787 isc_boolean_t finish_include = ISC_FALSE;
788 isc_boolean_t read_till_eol = ISC_FALSE;
789 isc_boolean_t initialws;
790 char *include_file = NULL;
792 isc_result_t result = ISC_R_UNEXPECTED;
793 rdatalist_head_t glue_list;
794 rdatalist_head_t current_list;
795 dns_rdatalist_t *this;
796 dns_rdatalist_t *rdatalist = NULL;
797 dns_rdatalist_t *new_rdatalist;
799 int rdlcount_save = 0;
800 int rdatalist_size = 0;
803 isc_buffer_t target_ft;
804 isc_buffer_t target_save;
805 dns_rdata_t *rdata = NULL;
806 dns_rdata_t *new_rdata;
808 int rdcount_save = 0;
810 unsigned char *target_mem = NULL;
811 int target_size = TSIZ;
813 unsigned int loop_cnt = 0;
815 dns_rdatacallbacks_t *callbacks;
821 const char *source = "";
822 unsigned long line = 0;
823 isc_boolean_t explicit_ttl;
826 REQUIRE(DNS_LCTX_VALID(lctx));
827 callbacks = lctx->callbacks;
831 ISC_LIST_INIT(glue_list);
832 ISC_LIST_INIT(current_list);
834 isc_stdtime_get(&now);
837 * Allocate target_size of buffer space. This is greater than twice
838 * the maximum individual RR data size.
840 target_mem = isc_mem_get(mctx, target_size);
841 if (target_mem == NULL) {
842 result = ISC_R_NOMEMORY;
843 goto log_and_cleanup;
845 isc_buffer_init(&target, target_mem, target_size);
846 target_save = target;
848 source = isc_lex_getsourcename(lctx->lex);
850 initialws = ISC_FALSE;
851 line = isc_lex_getsourceline(lctx->lex);
852 GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS, &token, ISC_TRUE);
853 line = isc_lex_getsourceline(lctx->lex);
855 if (token.type == isc_tokentype_eof) {
857 WARNUNEXPECTEDEOF(lctx->lex);
858 /* Pop the include stack? */
859 if (ictx->parent != NULL) {
861 lctx->inc = ictx->parent;
863 incctx_destroy(lctx->mctx, ictx);
864 isc_lex_close(lctx->lex);
865 line = isc_lex_getsourceline(lctx->lex);
866 source = isc_lex_getsourcename(lctx->lex);
875 if (token.type == isc_tokentype_eol) {
876 read_till_eol = ISC_FALSE;
877 continue; /* blank line */
883 if (token.type == isc_tokentype_initialws) {
885 * Still working on the same name.
887 initialws = ISC_TRUE;
888 } else if (token.type == isc_tokentype_string) {
893 * "$ORIGIN" and "$INCLUDE" can both take domain names.
894 * The processing of "$ORIGIN" and "$INCLUDE" extends
895 * across the normal domain name processing.
898 if (strcasecmp(token.value.as_pointer,
900 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
901 finish_origin = ISC_TRUE;
902 } else if (strcasecmp(token.value.as_pointer,
904 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
906 dns_ttl_fromtext(&token.value.as_textregion,
908 if (MANYERRS(lctx, result)) {
909 SETRESULT(lctx, result);
911 } else if (result != ISC_R_SUCCESS)
912 goto insist_and_cleanup;
913 limit_ttl(callbacks, source, line, &lctx->ttl);
914 lctx->default_ttl = lctx->ttl;
915 lctx->default_ttl_known = ISC_TRUE;
918 } else if (strcasecmp(token.value.as_pointer,
921 if ((lctx->options & DNS_MASTER_NOINCLUDE) != 0) {
922 (callbacks->error)(callbacks,
923 "%s: %s:%lu: $INCLUDE not allowed",
926 result = DNS_R_REFUSED;
927 goto insist_and_cleanup;
929 if (ttl_offset != 0) {
930 (callbacks->error)(callbacks,
931 "%s: %s:%lu: $INCLUDE "
932 "may not be used with $DATE",
935 result = DNS_R_SYNTAX;
936 goto insist_and_cleanup;
938 GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
940 if (include_file != NULL)
941 isc_mem_free(mctx, include_file);
942 include_file = isc_mem_strdup(mctx,
943 token.value.as_pointer);
944 if (include_file == NULL) {
945 result = ISC_R_NOMEMORY;
946 goto log_and_cleanup;
948 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE);
950 if (token.type == isc_tokentype_eol ||
951 token.type == isc_tokentype_eof) {
952 if (token.type == isc_tokentype_eof)
953 WARNUNEXPECTEDEOF(lctx->lex);
954 isc_lex_ungettoken(lctx->lex, &token);
958 result = pushfile(include_file,
960 if (MANYERRS(lctx, result)) {
961 SETRESULT(lctx, result);
962 LOGITFILE(result, include_file);
964 } else if (result != ISC_R_SUCCESS) {
965 LOGITFILE(result, include_file);
966 goto insist_and_cleanup;
969 line = isc_lex_getsourceline(lctx->lex);
971 isc_lex_getsourcename(lctx->lex);
975 * There is an origin field. Fall through
976 * to domain name processing code and do
977 * the actual inclusion later.
979 finish_include = ISC_TRUE;
980 } else if (strcasecmp(token.value.as_pointer,
982 isc_int64_t dump_time64;
983 isc_stdtime_t dump_time, current_time;
984 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
985 isc_stdtime_get(¤t_time);
986 result = dns_time64_fromtext(token.value.
987 as_pointer, &dump_time64);
988 if (MANYERRS(lctx, result)) {
989 SETRESULT(lctx, result);
992 } else if (result != ISC_R_SUCCESS)
993 goto log_and_cleanup;
994 dump_time = (isc_stdtime_t)dump_time64;
995 if (dump_time != dump_time64) {
996 UNEXPECTED_ERROR(__FILE__, __LINE__,
997 "%s: %s:%lu: $DATE outside epoch",
998 "dns_master_load", source, line);
999 result = ISC_R_UNEXPECTED;
1000 goto insist_and_cleanup;
1002 if (dump_time > current_time) {
1003 UNEXPECTED_ERROR(__FILE__, __LINE__,
1005 "$DATE in future, using current date",
1006 "dns_master_load", source, line);
1007 dump_time = current_time;
1009 ttl_offset = current_time - dump_time;
1012 } else if (strcasecmp(token.value.as_pointer,
1013 "$GENERATE") == 0) {
1015 * Use default ttl if known otherwise
1018 if (!lctx->ttl_known &&
1019 !lctx->default_ttl_known) {
1020 (*callbacks->error)(callbacks,
1021 "%s: %s:%lu: no TTL specified",
1022 "dns_master_load", source, line);
1023 result = DNS_R_NOTTL;
1024 if (MANYERRS(lctx, result)) {
1025 SETRESULT(lctx, result);
1027 } else if (result != ISC_R_SUCCESS)
1028 goto insist_and_cleanup;
1029 } else if (lctx->default_ttl_known) {
1030 lctx->ttl = lctx->default_ttl;
1036 isc_mem_free(mctx, range);
1038 isc_mem_free(mctx, lhs);
1040 isc_mem_free(mctx, gtype);
1042 isc_mem_free(mctx, rhs);
1044 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1045 range = isc_mem_strdup(mctx,
1046 token.value.as_pointer);
1047 if (range == NULL) {
1048 result = ISC_R_NOMEMORY;
1049 goto log_and_cleanup;
1052 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1053 lhs = isc_mem_strdup(mctx,
1054 token.value.as_pointer);
1056 result = ISC_R_NOMEMORY;
1057 goto log_and_cleanup;
1060 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1061 gtype = isc_mem_strdup(mctx,
1062 token.value.as_pointer);
1063 if (gtype == NULL) {
1064 result = ISC_R_NOMEMORY;
1065 goto log_and_cleanup;
1068 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1069 rhs = isc_mem_strdup(mctx,
1070 token.value.as_pointer);
1072 result = ISC_R_NOMEMORY;
1073 goto log_and_cleanup;
1075 result = generate(lctx, range, lhs, gtype, rhs,
1077 if (MANYERRS(lctx, result)) {
1078 SETRESULT(lctx, result);
1079 } else if (result != ISC_R_SUCCESS)
1080 goto insist_and_cleanup;
1083 } else if (strncasecmp(token.value.as_pointer,
1085 (callbacks->error)(callbacks,
1087 "unknown $ directive '%s'",
1088 "dns_master_load", source, line,
1089 token.value.as_pointer);
1090 result = DNS_R_SYNTAX;
1091 if (MANYERRS(lctx, result)) {
1092 SETRESULT(lctx, result);
1093 } else if (result != ISC_R_SUCCESS)
1094 goto insist_and_cleanup;
1098 * Normal processing resumes.
1100 * Find a free name buffer.
1102 for (new_in_use = 0; new_in_use < NBUFS ; new_in_use++)
1103 if (!ictx->in_use[new_in_use])
1105 INSIST(new_in_use < NBUFS);
1106 dns_fixedname_init(&ictx->fixed[new_in_use]);
1107 new_name = dns_fixedname_name(&ictx->fixed[new_in_use]);
1108 isc_buffer_init(&buffer, token.value.as_region.base,
1109 token.value.as_region.length);
1110 isc_buffer_add(&buffer, token.value.as_region.length);
1111 isc_buffer_setactive(&buffer,
1112 token.value.as_region.length);
1113 result = dns_name_fromtext(new_name, &buffer,
1114 ictx->origin, ISC_FALSE, NULL);
1115 if (MANYERRS(lctx, result)) {
1116 SETRESULT(lctx, result);
1117 LOGITFILE(result, include_file);
1118 read_till_eol = ISC_TRUE;
1120 } else if (result != ISC_R_SUCCESS)
1121 goto log_and_cleanup;
1124 * Finish $ORIGIN / $INCLUDE processing if required.
1126 if (finish_origin) {
1127 if (ictx->origin_in_use != -1)
1128 ictx->in_use[ictx->origin_in_use] =
1130 ictx->origin_in_use = new_in_use;
1131 ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
1132 ictx->origin = new_name;
1133 finish_origin = ISC_FALSE;
1137 if (finish_include) {
1138 finish_include = ISC_FALSE;
1139 result = pushfile(include_file, new_name, lctx);
1140 if (MANYERRS(lctx, result)) {
1141 SETRESULT(lctx, result);
1142 LOGITFILE(result, include_file);
1144 } else if (result != ISC_R_SUCCESS) {
1145 LOGITFILE(result, include_file);
1146 goto insist_and_cleanup;
1149 line = isc_lex_getsourceline(lctx->lex);
1150 source = isc_lex_getsourcename(lctx->lex);
1155 * "$" Processing Finished
1159 * If we are processing glue and the new name does
1160 * not match the current glue name, commit the glue
1161 * and pop stacks leaving us in 'normal' processing
1162 * state. Linked lists are undone by commit().
1164 if (ictx->glue != NULL &&
1165 dns_name_compare(ictx->glue, new_name) != 0) {
1166 result = commit(callbacks, lctx, &glue_list,
1169 if (MANYERRS(lctx, result)) {
1170 SETRESULT(lctx, result);
1171 } else if (result != ISC_R_SUCCESS)
1172 goto insist_and_cleanup;
1173 if (ictx->glue_in_use != -1)
1174 ictx->in_use[ictx->glue_in_use] =
1176 ictx->glue_in_use = -1;
1178 rdcount = rdcount_save;
1179 rdlcount = rdlcount_save;
1180 target = target_save;
1184 * If we are in 'normal' processing state and the new
1185 * name does not match the current name, see if the
1186 * new name is for glue and treat it as such,
1187 * otherwise we have a new name so commit what we
1190 if ((ictx->glue == NULL) && (ictx->current == NULL ||
1191 dns_name_compare(ictx->current, new_name) != 0)) {
1192 if (current_has_delegation &&
1193 is_glue(¤t_list, new_name)) {
1194 rdcount_save = rdcount;
1195 rdlcount_save = rdlcount;
1196 target_save = target;
1197 ictx->glue = new_name;
1198 ictx->glue_in_use = new_in_use;
1199 ictx->in_use[ictx->glue_in_use] =
1202 result = commit(callbacks, lctx,
1206 ictx->current_line);
1207 if (MANYERRS(lctx, result)) {
1208 SETRESULT(lctx, result);
1209 } else if (result != ISC_R_SUCCESS)
1210 goto insist_and_cleanup;
1213 if (ictx->current_in_use != -1)
1214 ictx->in_use[ictx->current_in_use] =
1216 ictx->current_in_use = new_in_use;
1217 ictx->in_use[ictx->current_in_use] =
1219 ictx->current = new_name;
1220 current_has_delegation = ISC_FALSE;
1221 isc_buffer_init(&target, target_mem,
1225 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
1226 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
1227 !dns_name_issubdomain(new_name, lctx->top))
1229 char namebuf[DNS_NAME_FORMATSIZE];
1230 dns_name_format(new_name, namebuf,
1233 * Ignore out-of-zone data.
1235 (*callbacks->warn)(callbacks,
1236 "dns_master_load: %s:%lu: "
1237 "ignoring out-of-zone data (%s)",
1238 source, line, namebuf);
1239 ictx->drop = ISC_TRUE;
1241 ictx->drop = ISC_FALSE;
1243 UNEXPECTED_ERROR(__FILE__, __LINE__,
1244 "%s:%lu: isc_lex_gettoken() returned "
1245 "unexpeced token type (%d)",
1246 source, line, token.type);
1247 result = ISC_R_UNEXPECTED;
1248 if (MANYERRS(lctx, result)) {
1249 SETRESULT(lctx, result);
1252 } else if (result != ISC_R_SUCCESS)
1253 goto insist_and_cleanup;
1257 * Find TTL, class and type. Both TTL and class are optional
1258 * and may occur in any order if they exist. TTL and class
1259 * come before type which must exist.
1261 * [<TTL>] [<class>] <type> <RDATA>
1262 * [<class>] [<TTL>] <type> <RDATA>
1268 GETTOKEN(lctx->lex, 0, &token, initialws);
1271 if (token.type == isc_tokentype_eol) {
1272 read_till_eol = ISC_FALSE;
1273 continue; /* blank line */
1276 if (token.type == isc_tokentype_eof) {
1277 WARNUNEXPECTEDEOF(lctx->lex);
1278 read_till_eol = ISC_FALSE;
1279 isc_lex_ungettoken(lctx->lex, &token);
1283 if (ictx->current == NULL) {
1284 (*callbacks->error)(callbacks,
1285 "%s: %s:%lu: no current owner name",
1288 result = DNS_R_NOOWNER;
1289 if (MANYERRS(lctx, result)) {
1290 SETRESULT(lctx, result);
1291 read_till_eol = ISC_TRUE;
1293 } else if (result != ISC_R_SUCCESS)
1294 goto insist_and_cleanup;
1298 if (dns_rdataclass_fromtext(&rdclass,
1299 &token.value.as_textregion)
1301 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1303 explicit_ttl = ISC_FALSE;
1304 if (dns_ttl_fromtext(&token.value.as_textregion, &lctx->ttl)
1306 limit_ttl(callbacks, source, line, &lctx->ttl);
1307 explicit_ttl = ISC_TRUE;
1308 lctx->ttl_known = ISC_TRUE;
1309 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1312 if (token.type != isc_tokentype_string) {
1313 UNEXPECTED_ERROR(__FILE__, __LINE__,
1314 "isc_lex_gettoken() returned unexpected token type");
1315 result = ISC_R_UNEXPECTED;
1316 if (MANYERRS(lctx, result)) {
1317 SETRESULT(lctx, result);
1318 read_till_eol = ISC_TRUE;
1320 } else if (result != ISC_R_SUCCESS)
1321 goto insist_and_cleanup;
1325 dns_rdataclass_fromtext(&rdclass,
1326 &token.value.as_textregion)
1328 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1330 if (token.type != isc_tokentype_string) {
1331 UNEXPECTED_ERROR(__FILE__, __LINE__,
1332 "isc_lex_gettoken() returned unexpected token type");
1333 result = ISC_R_UNEXPECTED;
1334 if (MANYERRS(lctx, result)) {
1335 SETRESULT(lctx, result);
1336 read_till_eol = ISC_TRUE;
1338 } else if (result != ISC_R_SUCCESS)
1339 goto insist_and_cleanup;
1342 result = dns_rdatatype_fromtext(&type,
1343 &token.value.as_textregion);
1344 if (result != ISC_R_SUCCESS) {
1345 (*callbacks->warn)(callbacks,
1346 "%s: %s:%lu: unknown RR type '%.*s'",
1347 "dns_master_load", source, line,
1348 token.value.as_textregion.length,
1349 token.value.as_textregion.base);
1350 if (MANYERRS(lctx, result)) {
1351 SETRESULT(lctx, result);
1352 read_till_eol = ISC_TRUE;
1354 } else if (result != ISC_R_SUCCESS)
1355 goto insist_and_cleanup;
1359 * If the class specified does not match the zone's class
1360 * print out a error message and exit.
1362 if (rdclass != 0 && rdclass != lctx->zclass) {
1363 char classname1[DNS_RDATACLASS_FORMATSIZE];
1364 char classname2[DNS_RDATACLASS_FORMATSIZE];
1366 dns_rdataclass_format(rdclass, classname1,
1367 sizeof(classname1));
1368 dns_rdataclass_format(lctx->zclass, classname2,
1369 sizeof(classname2));
1370 (*callbacks->error)(callbacks,
1371 "%s: %s:%lu: class '%s' != "
1373 "dns_master_load", source, line,
1374 classname1, classname2);
1375 result = DNS_R_BADCLASS;
1376 if (MANYERRS(lctx, result)) {
1377 SETRESULT(lctx, result);
1378 read_till_eol = ISC_TRUE;
1380 } else if (result != ISC_R_SUCCESS)
1381 goto insist_and_cleanup;
1384 if (type == dns_rdatatype_ns && ictx->glue == NULL)
1385 current_has_delegation = ISC_TRUE;
1388 * Find a rdata structure.
1390 if (rdcount == rdata_size) {
1391 new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
1392 rdata_size, ¤t_list,
1394 if (new_rdata == NULL) {
1395 result = ISC_R_NOMEMORY;
1396 goto log_and_cleanup;
1403 * Read rdata contents.
1405 dns_rdata_init(&rdata[rdcount]);
1407 result = dns_rdata_fromtext(&rdata[rdcount], lctx->zclass,
1408 type, lctx->lex, ictx->origin,
1409 ISC_FALSE, lctx->mctx, &target,
1411 if (MANYERRS(lctx, result)) {
1412 SETRESULT(lctx, result);
1414 } else if (result != ISC_R_SUCCESS)
1415 goto insist_and_cleanup;
1422 if (type == dns_rdatatype_soa &&
1423 (lctx->options & DNS_MASTER_ZONE) != 0 &&
1424 dns_name_compare(ictx->current, lctx->top) != 0) {
1425 char namebuf[DNS_NAME_FORMATSIZE];
1426 dns_name_format(ictx->current, namebuf,
1428 (*callbacks->error)(callbacks,
1429 "dns_master_load: %s:%lu: SOA "
1430 "record not at top of zone (%s)",
1431 source, line, namebuf);
1432 result = DNS_R_NOTZONETOP;
1433 if (MANYERRS(lctx, result)) {
1434 SETRESULT(lctx, result);
1435 read_till_eol = ISC_TRUE;
1438 } else if (result != ISC_R_SUCCESS)
1439 goto insist_and_cleanup;
1443 if (type == dns_rdatatype_sig)
1444 covers = dns_rdata_covers(&rdata[rdcount]);
1448 if (!lctx->ttl_known && !lctx->default_ttl_known) {
1449 if (type == dns_rdatatype_soa) {
1450 (*callbacks->warn)(callbacks,
1451 "%s:%lu: no TTL specified; "
1452 "using SOA MINTTL instead",
1454 lctx->ttl = dns_soa_getminimum(&rdata[rdcount]);
1455 limit_ttl(callbacks, source, line, &lctx->ttl);
1456 lctx->default_ttl = lctx->ttl;
1457 lctx->default_ttl_known = ISC_TRUE;
1459 (*callbacks->warn)(callbacks,
1460 "%s:%lu: no TTL specified; "
1463 result = DNS_R_NOTTL;
1464 if (MANYERRS(lctx, result)) {
1465 SETRESULT(lctx, result);
1468 goto insist_and_cleanup;
1471 } else if (!explicit_ttl && lctx->default_ttl_known) {
1472 lctx->ttl = lctx->default_ttl;
1473 } else if (!explicit_ttl && lctx->warn_1035) {
1474 (*callbacks->warn)(callbacks,
1476 "using RFC 1035 TTL semantics",
1477 "dns_master_load", source, line);
1478 lctx->warn_1035 = ISC_FALSE;
1481 if (type == dns_rdatatype_sig && lctx->warn_sigexpired) {
1482 dns_rdata_sig_t sig;
1483 (void)dns_rdata_tostruct(&rdata[rdcount], &sig, NULL);
1484 if (isc_serial_lt(sig.timeexpire, now)) {
1485 (*callbacks->warn)(callbacks,
1487 "signature has expired",
1490 lctx->warn_sigexpired = ISC_FALSE;
1494 if ((lctx->options & DNS_MASTER_AGETTL) != 0) {
1496 * Adjust the TTL for $DATE. If the RR has already
1497 * expired, ignore it.
1499 if (lctx->ttl < ttl_offset)
1501 lctx->ttl -= ttl_offset;
1505 * Find type in rdatalist.
1506 * If it does not exist create new one and prepend to list
1507 * as this will mimimise list traversal.
1509 if (ictx->glue != NULL)
1510 this = ISC_LIST_HEAD(glue_list);
1512 this = ISC_LIST_HEAD(current_list);
1514 while (this != NULL) {
1515 if (this->type == type && this->covers == covers)
1517 this = ISC_LIST_NEXT(this, link);
1521 if (rdlcount == rdatalist_size) {
1523 grow_rdatalist(rdatalist_size + RDLSZ,
1529 if (new_rdatalist == NULL) {
1530 result = ISC_R_NOMEMORY;
1531 goto log_and_cleanup;
1533 rdatalist = new_rdatalist;
1534 rdatalist_size += RDLSZ;
1536 this = &rdatalist[rdlcount++];
1538 this->covers = covers;
1539 this->rdclass = lctx->zclass;
1540 this->ttl = lctx->ttl;
1541 ISC_LIST_INIT(this->rdata);
1542 if (ictx->glue != NULL)
1543 ISC_LIST_INITANDPREPEND(glue_list, this, link);
1545 ISC_LIST_INITANDPREPEND(current_list, this,
1547 } else if (this->ttl != lctx->ttl) {
1548 (*callbacks->warn)(callbacks,
1550 "TTL set to prior TTL (%lu)",
1552 source, line, this->ttl);
1553 lctx->ttl = this->ttl;
1556 ISC_LIST_APPEND(this->rdata, &rdata[rdcount], link);
1557 if (ictx->glue != NULL)
1558 ictx->glue_line = line;
1560 ictx->current_line = line;
1564 * We must have at least 64k as rdlen is 16 bits.
1565 * If we don't commit everything we have so far.
1567 if ((target.length - target.used) < MINTSIZ)
1571 } while (!done && (lctx->loop_cnt == 0 || loop_cnt++ < lctx->loop_cnt));
1574 * Commit what has not yet been committed.
1576 result = commit(callbacks, lctx, ¤t_list, ictx->current,
1577 source, ictx->current_line);
1578 if (MANYERRS(lctx, result)) {
1579 SETRESULT(lctx, result);
1580 } else if (result != ISC_R_SUCCESS)
1581 goto insist_and_cleanup;
1582 result = commit(callbacks, lctx, &glue_list, ictx->glue,
1583 source, ictx->glue_line);
1584 if (MANYERRS(lctx, result)) {
1585 SETRESULT(lctx, result);
1586 } else if (result != ISC_R_SUCCESS)
1587 goto insist_and_cleanup;
1590 INSIST(lctx->done != NULL && lctx->task != NULL);
1591 result = DNS_R_CONTINUE;
1592 } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) {
1593 result = lctx->result;
1594 } else if (result == ISC_R_SUCCESS && lctx->seen_include)
1595 result = DNS_R_SEENINCLUDE;
1602 INSIST(result != ISC_R_SUCCESS);
1605 while ((this = ISC_LIST_HEAD(current_list)) != NULL)
1606 ISC_LIST_UNLINK(current_list, this, link);
1607 while ((this = ISC_LIST_HEAD(glue_list)) != NULL)
1608 ISC_LIST_UNLINK(glue_list, this, link);
1609 if (rdatalist != NULL)
1610 isc_mem_put(mctx, rdatalist,
1611 rdatalist_size * sizeof *rdatalist);
1613 isc_mem_put(mctx, rdata, rdata_size * sizeof *rdata);
1614 if (target_mem != NULL)
1615 isc_mem_put(mctx, target_mem, target_size);
1616 if (include_file != NULL)
1617 isc_mem_free(mctx, include_file);
1619 isc_mem_free(mctx, range);
1621 isc_mem_free(mctx, lhs);
1623 isc_mem_free(mctx, gtype);
1625 isc_mem_free(mctx, rhs);
1630 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) {
1631 isc_result_t result;
1633 dns_incctx_t *new = NULL;
1637 REQUIRE(master_file != NULL);
1638 REQUIRE(DNS_LCTX_VALID(lctx));
1641 lctx->seen_include = ISC_TRUE;
1643 result = incctx_create(lctx->mctx, origin, &new);
1644 if (result != ISC_R_SUCCESS)
1647 /* Set current domain. */
1648 if (ictx->glue != NULL || ictx->current != NULL) {
1649 for (new_in_use = 0; new_in_use < NBUFS ; new_in_use++)
1650 if (!new->in_use[new_in_use])
1652 INSIST(new_in_use < NBUFS);
1653 new->current_in_use = new_in_use;
1655 dns_fixedname_name(&new->fixed[new->current_in_use]);
1656 new->in_use[new->current_in_use] = ISC_TRUE;
1657 dns_name_toregion((ictx->glue != NULL) ?
1658 ictx->glue : ictx->current, &r);
1659 dns_name_fromregion(new->current, &r);
1660 new->drop = ictx->drop;
1663 result = isc_lex_openfile(lctx->lex, master_file);
1664 if (result != ISC_R_SUCCESS)
1668 return (ISC_R_SUCCESS);
1672 incctx_destroy(lctx->mctx, new);
1677 dns_master_loadfile(const char *master_file, dns_name_t *top,
1679 dns_rdataclass_t zclass, unsigned int options,
1680 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
1682 dns_loadctx_t *lctx = NULL;
1683 isc_result_t result;
1685 result = loadctx_create(mctx, options, top, zclass, origin,
1686 callbacks, NULL, NULL, NULL, &lctx);
1687 if (result != ISC_R_SUCCESS)
1690 result = isc_lex_openfile(lctx->lex, master_file);
1691 if (result != ISC_R_SUCCESS)
1694 result = load(lctx);
1695 INSIST(result != DNS_R_CONTINUE);
1699 dns_loadctx_detach(&lctx);
1704 dns_master_loadfileinc(const char *master_file, dns_name_t *top,
1705 dns_name_t *origin, dns_rdataclass_t zclass,
1706 unsigned int options, dns_rdatacallbacks_t *callbacks,
1707 isc_task_t *task, dns_loaddonefunc_t done,
1708 void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx)
1710 dns_loadctx_t *lctx = NULL;
1711 isc_result_t result;
1713 REQUIRE(task != NULL);
1714 REQUIRE(done != NULL);
1716 result = loadctx_create(mctx, options, top, zclass, origin,
1717 callbacks, task, done, done_arg, &lctx);
1718 if (result != ISC_R_SUCCESS)
1721 result = isc_lex_openfile(lctx->lex, master_file);
1722 if (result != ISC_R_SUCCESS)
1725 result = task_send(lctx);
1726 if (result == ISC_R_SUCCESS) {
1727 dns_loadctx_attach(lctx, lctxp);
1728 return (DNS_R_CONTINUE);
1733 dns_loadctx_detach(&lctx);
1738 dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
1739 dns_rdataclass_t zclass, unsigned int options,
1740 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
1742 isc_result_t result;
1743 dns_loadctx_t *lctx = NULL;
1745 REQUIRE(stream != NULL);
1747 result = loadctx_create(mctx, options, top, zclass, origin,
1748 callbacks, NULL, NULL, NULL, &lctx);
1749 if (result != ISC_R_SUCCESS)
1752 result = isc_lex_openstream(lctx->lex, stream);
1753 if (result != ISC_R_SUCCESS)
1756 result = load(lctx);
1757 INSIST(result != DNS_R_CONTINUE);
1761 dns_loadctx_detach(&lctx);
1766 dns_master_loadstreaminc(FILE *stream, dns_name_t *top, dns_name_t *origin,
1767 dns_rdataclass_t zclass, unsigned int options,
1768 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
1769 dns_loaddonefunc_t done, void *done_arg,
1770 dns_loadctx_t **lctxp, isc_mem_t *mctx)
1772 isc_result_t result;
1773 dns_loadctx_t *lctx = NULL;
1775 REQUIRE(stream != NULL);
1776 REQUIRE(task != NULL);
1777 REQUIRE(done != NULL);
1779 result = loadctx_create(mctx, options, top, zclass, origin,
1780 callbacks, task, done, done_arg, &lctx);
1781 if (result != ISC_R_SUCCESS)
1784 result = isc_lex_openstream(lctx->lex, stream);
1785 if (result != ISC_R_SUCCESS)
1788 result = task_send(lctx);
1789 if (result == ISC_R_SUCCESS) {
1790 dns_loadctx_attach(lctx, lctxp);
1791 return (DNS_R_CONTINUE);
1796 dns_loadctx_detach(&lctx);
1801 dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top,
1802 dns_name_t *origin, dns_rdataclass_t zclass,
1803 unsigned int options,
1804 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
1806 isc_result_t result;
1807 dns_loadctx_t *lctx = NULL;
1809 REQUIRE(buffer != NULL);
1811 result = loadctx_create(mctx, options, top, zclass, origin,
1812 callbacks, NULL, NULL, NULL, &lctx);
1813 if (result != ISC_R_SUCCESS)
1816 result = isc_lex_openbuffer(lctx->lex, buffer);
1817 if (result != ISC_R_SUCCESS)
1820 result = load(lctx);
1821 INSIST(result != DNS_R_CONTINUE);
1825 dns_loadctx_detach(&lctx);
1830 dns_master_loadbufferinc(isc_buffer_t *buffer, dns_name_t *top,
1831 dns_name_t *origin, dns_rdataclass_t zclass,
1832 unsigned int options,
1833 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
1834 dns_loaddonefunc_t done, void *done_arg,
1835 dns_loadctx_t **lctxp, isc_mem_t *mctx)
1837 isc_result_t result;
1838 dns_loadctx_t *lctx = NULL;
1840 REQUIRE(buffer != NULL);
1841 REQUIRE(task != NULL);
1842 REQUIRE(done != NULL);
1844 result = loadctx_create(mctx, options, top, zclass, origin,
1845 callbacks, task, done, done_arg, &lctx);
1846 if (result != ISC_R_SUCCESS)
1849 result = isc_lex_openbuffer(lctx->lex, buffer);
1850 if (result != ISC_R_SUCCESS)
1853 result = task_send(lctx);
1854 if (result == ISC_R_SUCCESS) {
1855 dns_loadctx_attach(lctx, lctxp);
1856 return (DNS_R_CONTINUE);
1861 dns_loadctx_detach(&lctx);
1866 * Grow the slab of dns_rdatalist_t structures.
1867 * Re-link glue and current list.
1869 static dns_rdatalist_t *
1870 grow_rdatalist(int new_len, dns_rdatalist_t *old, int old_len,
1871 rdatalist_head_t *current, rdatalist_head_t *glue,
1874 dns_rdatalist_t *new;
1876 ISC_LIST(dns_rdatalist_t) save;
1877 dns_rdatalist_t *this;
1879 new = isc_mem_get(mctx, new_len * sizeof *new);
1883 ISC_LIST_INIT(save);
1884 this = ISC_LIST_HEAD(*current);
1885 while ((this = ISC_LIST_HEAD(*current)) != NULL) {
1886 ISC_LIST_UNLINK(*current, this, link);
1887 ISC_LIST_APPEND(save, this, link);
1889 while ((this = ISC_LIST_HEAD(save)) != NULL) {
1890 ISC_LIST_UNLINK(save, this, link);
1891 new[rdlcount] = *this;
1892 ISC_LIST_APPEND(*current, &new[rdlcount], link);
1896 ISC_LIST_INIT(save);
1897 this = ISC_LIST_HEAD(*glue);
1898 while ((this = ISC_LIST_HEAD(*glue)) != NULL) {
1899 ISC_LIST_UNLINK(*glue, this, link);
1900 ISC_LIST_APPEND(save, this, link);
1902 while ((this = ISC_LIST_HEAD(save)) != NULL) {
1903 ISC_LIST_UNLINK(save, this, link);
1904 new[rdlcount] = *this;
1905 ISC_LIST_APPEND(*glue, &new[rdlcount], link);
1909 INSIST(rdlcount == old_len);
1911 isc_mem_put(mctx, old, old_len * sizeof *old);
1916 * Grow the slab of rdata structs.
1917 * Re-link the current and glue chains.
1919 static dns_rdata_t *
1920 grow_rdata(int new_len, dns_rdata_t *old, int old_len,
1921 rdatalist_head_t *current, rdatalist_head_t *glue,
1926 ISC_LIST(dns_rdata_t) save;
1927 dns_rdatalist_t *this;
1930 new = isc_mem_get(mctx, new_len * sizeof *new);
1933 memset(new, 0, new_len * sizeof *new);
1936 * Copy current relinking.
1938 this = ISC_LIST_HEAD(*current);
1939 while (this != NULL) {
1940 ISC_LIST_INIT(save);
1941 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
1942 ISC_LIST_UNLINK(this->rdata, rdata, link);
1943 ISC_LIST_APPEND(save, rdata, link);
1945 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
1946 ISC_LIST_UNLINK(save, rdata, link);
1947 new[rdcount] = *rdata;
1948 ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
1951 this = ISC_LIST_NEXT(this, link);
1955 * Copy glue relinking.
1957 this = ISC_LIST_HEAD(*glue);
1958 while (this != NULL) {
1959 ISC_LIST_INIT(save);
1960 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
1961 ISC_LIST_UNLINK(this->rdata, rdata, link);
1962 ISC_LIST_APPEND(save, rdata, link);
1964 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
1965 ISC_LIST_UNLINK(save, rdata, link);
1966 new[rdcount] = *rdata;
1967 ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
1970 this = ISC_LIST_NEXT(this, link);
1972 INSIST(rdcount == old_len);
1974 isc_mem_put(mctx, old, old_len * sizeof *old);
1979 * Convert each element from a rdatalist_t to rdataset then call commit.
1980 * Unlink each element as we go.
1984 commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
1985 rdatalist_head_t *head, dns_name_t *owner,
1986 const char *source, unsigned int line)
1988 dns_rdatalist_t *this;
1989 dns_rdataset_t dataset;
1990 isc_result_t result;
1991 char namebuf[DNS_NAME_FORMATSIZE];
1992 void (*error)(struct dns_rdatacallbacks *, const char *, ...);
1993 void (*warn)(struct dns_rdatacallbacks *, const char *, ...);
1995 this = ISC_LIST_HEAD(*head);
1996 error = callbacks->error;
1997 warn = callbacks->warn;
2000 return (ISC_R_SUCCESS);
2002 dns_rdataset_init(&dataset);
2003 dns_rdatalist_tordataset(this, &dataset);
2004 dataset.trust = dns_trust_ultimate;
2005 result = ((*callbacks->add)(callbacks->add_private, owner,
2007 if (result == ISC_R_NOMEMORY) {
2008 (*error)(callbacks, "dns_master_load: %s",
2009 dns_result_totext(result));
2010 } else if (result != ISC_R_SUCCESS) {
2011 dns_name_format(owner, namebuf,
2013 (*error)(callbacks, "%s: %s:%lu: %s: %s",
2014 "dns_master_load", source, line,
2015 namebuf, dns_result_totext(result));
2017 if (MANYERRS(lctx, result))
2018 SETRESULT(lctx, result);
2019 else if (result != ISC_R_SUCCESS)
2021 ISC_LIST_UNLINK(*head, this, link);
2022 this = ISC_LIST_HEAD(*head);
2023 } while (this != NULL);
2024 return (ISC_R_SUCCESS);
2028 * Returns ISC_TRUE if one of the NS rdata's contains 'owner'.
2031 static isc_boolean_t
2032 is_glue(rdatalist_head_t *head, dns_name_t *owner) {
2033 dns_rdatalist_t *this;
2035 isc_region_t region;
2041 this = ISC_LIST_HEAD(*head);
2042 while (this != NULL) {
2043 if (this->type == dns_rdatatype_ns)
2045 this = ISC_LIST_NEXT(this, link);
2050 rdata = ISC_LIST_HEAD(this->rdata);
2051 while (rdata != NULL) {
2052 dns_name_init(&name, NULL);
2053 dns_rdata_toregion(rdata, ®ion);
2054 dns_name_fromregion(&name, ®ion);
2055 if (dns_name_compare(&name, owner) == 0)
2057 rdata = ISC_LIST_NEXT(rdata, link);
2063 load_quantum(isc_task_t *task, isc_event_t *event) {
2064 isc_result_t result;
2065 dns_loadctx_t *lctx;
2067 REQUIRE(event != NULL);
2068 lctx = event->ev_arg;
2069 REQUIRE(DNS_LCTX_VALID(lctx));
2072 result = ISC_R_CANCELED;
2074 result = load(lctx);
2075 if (result == DNS_R_CONTINUE) {
2076 event->ev_arg = lctx;
2077 isc_task_send(task, &event);
2079 (lctx->done)(lctx->done_arg, result);
2080 isc_event_free(&event);
2081 dns_loadctx_detach(&lctx);
2086 task_send(dns_loadctx_t *lctx) {
2089 event = isc_event_allocate(lctx->mctx, NULL,
2090 DNS_EVENT_MASTERQUANTUM,
2091 load_quantum, lctx, sizeof(*event));
2093 return (ISC_R_NOMEMORY);
2094 isc_task_send(lctx->task, &event);
2095 return (ISC_R_SUCCESS);
2099 dns_loadctx_cancel(dns_loadctx_t *lctx) {
2100 REQUIRE(DNS_LCTX_VALID(lctx));
2103 lctx->canceled = ISC_TRUE;
2104 UNLOCK(&lctx->lock);