2 * Copyright (C) 2004-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or 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.
24 #include <isc/event.h>
26 #include <isc/magic.h>
28 #include <isc/print.h>
29 #include <isc/serial.h>
30 #include <isc/stdio.h>
31 #include <isc/stdtime.h>
32 #include <isc/string.h>
36 #include <dns/callbacks.h>
37 #include <dns/events.h>
38 #include <dns/fixedname.h>
39 #include <dns/master.h>
41 #include <dns/rdata.h>
42 #include <dns/rdataclass.h>
43 #include <dns/rdatalist.h>
44 #include <dns/rdataset.h>
45 #include <dns/rdatastruct.h>
46 #include <dns/rdatatype.h>
47 #include <dns/result.h>
53 * Grow the number of dns_rdatalist_t (#RDLSZ) and dns_rdata_t (#RDSZ) structures
54 * by these sizes when we need to.
57 /*% RDLSZ reflects the number of different types with the same name expected. */
60 * RDSZ reflects the number of rdata expected at a give name that can fit into
69 * Target buffer size and minimum target size.
70 * MINTSIZ must be big enough to hold the largest rdata record.
74 #define TSIZ (128*1024)
76 * max message size - header - root - type - class - ttl - rdlen
78 #define MINTSIZ DNS_RDATA_MAXLENGTH
80 * Size for tokens in the presentation format,
81 * The largest tokens are the base64 blocks in KEY and CERT records,
82 * Largest key allowed is about 1372 bytes but
83 * there is no fixed upper bound on CERT records.
84 * 2K is too small for some X.509s, 8K is overkill.
86 #define TOKENSIZ (8*1024)
89 * Buffers sizes for $GENERATE.
91 #define DNS_MASTER_LHS 2048
92 #define DNS_MASTER_RHS MINTSIZ
94 typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
96 typedef struct dns_incctx dns_incctx_t;
99 * Master file load state.
105 dns_masterformat_t format;
107 dns_rdatacallbacks_t *callbacks;
109 dns_loaddonefunc_t done;
113 isc_result_t (*openfile)(dns_loadctx_t *lctx,
114 const char *filename);
115 isc_result_t (*load)(dns_loadctx_t *lctx);
117 /* Members specific to the text format: */
119 isc_boolean_t keep_lex;
120 unsigned int options;
121 isc_boolean_t ttl_known;
122 isc_boolean_t default_ttl_known;
123 isc_boolean_t warn_1035;
124 isc_boolean_t warn_tcr;
125 isc_boolean_t warn_sigexpired;
126 isc_boolean_t seen_include;
128 isc_uint32_t default_ttl;
129 dns_rdataclass_t zclass;
130 dns_fixedname_t fixed_top;
131 dns_name_t *top; /*%< top of zone */
133 /* Members specific to the raw format: */
137 /* Which fixed buffers we are using? */
138 unsigned int loop_cnt; /*% records per quantum,
140 isc_boolean_t canceled;
144 isc_uint32_t references;
150 dns_incctx_t *parent;
154 dns_fixedname_t fixed[NBUFS]; /* working buffers */
155 unsigned int in_use[NBUFS]; /* covert to bitmap? */
159 isc_boolean_t origin_changed;
161 unsigned int glue_line;
162 unsigned int current_line;
165 #define DNS_LCTX_MAGIC ISC_MAGIC('L','c','t','x')
166 #define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
168 #define DNS_AS_STR(t) ((t).value.as_textregion.base)
171 openfile_text(dns_loadctx_t *lctx, const char *master_file);
174 openfile_raw(dns_loadctx_t *lctx, const char *master_file);
177 load_text(dns_loadctx_t *lctx);
180 load_raw(dns_loadctx_t *lctx);
183 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx);
186 commit(dns_rdatacallbacks_t *, dns_loadctx_t *, rdatalist_head_t *,
187 dns_name_t *, const char *, unsigned int);
190 is_glue(rdatalist_head_t *, dns_name_t *);
192 static dns_rdatalist_t *
193 grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *,
194 rdatalist_head_t *, isc_mem_t *mctx);
197 grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *,
201 load_quantum(isc_task_t *task, isc_event_t *event);
204 task_send(dns_loadctx_t *lctx);
207 loadctx_destroy(dns_loadctx_t *lctx);
209 #define GETTOKEN(lexer, options, token, eol) \
211 result = gettoken(lexer, options, token, eol, callbacks); \
213 case ISC_R_SUCCESS: \
215 case ISC_R_UNEXPECTED: \
216 goto insist_and_cleanup; \
218 if (MANYERRS(lctx, result)) { \
219 SETRESULT(lctx, result); \
221 read_till_eol = ISC_TRUE; \
224 goto log_and_cleanup; \
226 if ((token)->type == isc_tokentype_special) { \
227 result = DNS_R_SYNTAX; \
228 if (MANYERRS(lctx, result)) { \
229 SETRESULT(lctx, result); \
231 read_till_eol = ISC_TRUE; \
234 goto log_and_cleanup; \
240 result = commit(callbacks, lctx, ¤t_list, \
241 ictx->current, source, ictx->current_line); \
242 if (MANYERRS(lctx, result)) { \
243 SETRESULT(lctx, result); \
244 } else if (result != ISC_R_SUCCESS) \
245 goto insist_and_cleanup; \
246 result = commit(callbacks, lctx, &glue_list, \
247 ictx->glue, source, ictx->glue_line); \
248 if (MANYERRS(lctx, result)) { \
249 SETRESULT(lctx, result); \
250 } else if (result != ISC_R_SUCCESS) \
251 goto insist_and_cleanup; \
254 isc_buffer_init(&target, target_mem, target_size); \
255 rdcount_save = rdcount; \
256 rdlcount_save = rdlcount; \
259 #define WARNUNEXPECTEDEOF(lexer) \
261 if (isc_lex_isfile(lexer)) \
262 (*callbacks->warn)(callbacks, \
263 "%s: file does not end with newline", \
269 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE); \
270 if (token.type != isc_tokentype_eol) { \
271 isc_lex_ungettoken(lctx->lex, &token); \
272 result = DNS_R_EXTRATOKEN; \
273 if (MANYERRS(lctx, result)) { \
274 SETRESULT(lctx, result); \
276 read_till_eol = ISC_TRUE; \
278 } else if (result != ISC_R_SUCCESS) \
279 goto log_and_cleanup; \
283 #define MANYERRS(lctx, result) \
284 ((result != ISC_R_SUCCESS) && \
285 (result != ISC_R_IOERROR) && \
286 ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
288 #define SETRESULT(lctx, r) \
290 if ((lctx)->result == ISC_R_SUCCESS) \
291 (lctx)->result = r; \
294 #define LOGITFILE(result, filename) \
295 if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \
296 result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \
297 result == ISC_R_NOPERM) \
298 (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \
299 "dns_master_load", source, line, \
300 filename, dns_result_totext(result)); \
303 #define LOGIT(result) \
304 if (result == ISC_R_NOMEMORY) \
305 (*callbacks->error)(callbacks, "dns_master_load: %s", \
306 dns_result_totext(result)); \
308 (*callbacks->error)(callbacks, "%s: %s:%lu: %s", \
310 source, line, dns_result_totext(result))
313 static unsigned char in_addr_arpa_data[] = "\007IN-ADDR\004ARPA";
314 static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 };
315 static const dns_name_t in_addr_arpa =
318 in_addr_arpa_data, 14, 3,
319 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
320 in_addr_arpa_offsets, NULL,
321 {(void *)-1, (void *)-1},
325 static unsigned char ip6_int_data[] = "\003IP6\003INT";
326 static unsigned char ip6_int_offsets[] = { 0, 4, 8 };
327 static const dns_name_t ip6_int =
331 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
332 ip6_int_offsets, NULL,
333 {(void *)-1, (void *)-1},
337 static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA";
338 static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
339 static const dns_name_t ip6_arpa =
342 ip6_arpa_data, 10, 3,
343 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
344 ip6_arpa_offsets, NULL,
345 {(void *)-1, (void *)-1},
350 static inline isc_result_t
351 gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token,
352 isc_boolean_t eol, dns_rdatacallbacks_t *callbacks)
356 options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE |
358 result = isc_lex_gettoken(lex, options, token);
359 if (result != ISC_R_SUCCESS) {
362 return (ISC_R_NOMEMORY);
364 (*callbacks->error)(callbacks,
365 "dns_master_load: %s:%lu:"
366 " isc_lex_gettoken() failed: %s",
367 isc_lex_getsourcename(lex),
368 isc_lex_getsourceline(lex),
369 isc_result_totext(result));
375 if (token->type == isc_tokentype_eol ||
376 token->type == isc_tokentype_eof) {
377 (*callbacks->error)(callbacks,
378 "dns_master_load: %s:%lu: unexpected end of %s",
379 isc_lex_getsourcename(lex),
380 isc_lex_getsourceline(lex),
384 return (ISC_R_UNEXPECTEDEND);
386 return (ISC_R_SUCCESS);
391 dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
393 REQUIRE(target != NULL && *target == NULL);
394 REQUIRE(DNS_LCTX_VALID(source));
397 INSIST(source->references > 0);
398 source->references++;
399 INSIST(source->references != 0); /* Overflow? */
400 UNLOCK(&source->lock);
406 dns_loadctx_detach(dns_loadctx_t **lctxp) {
408 isc_boolean_t need_destroy = ISC_FALSE;
410 REQUIRE(lctxp != NULL);
412 REQUIRE(DNS_LCTX_VALID(lctx));
415 INSIST(lctx->references > 0);
417 if (lctx->references == 0)
418 need_destroy = ISC_TRUE;
422 loadctx_destroy(lctx);
427 incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
428 dns_incctx_t *parent;
431 parent = ictx->parent;
434 isc_mem_put(mctx, ictx, sizeof(*ictx));
436 if (parent != NULL) {
443 loadctx_destroy(dns_loadctx_t *lctx) {
447 REQUIRE(DNS_LCTX_VALID(lctx));
450 if (lctx->inc != NULL)
451 incctx_destroy(lctx->mctx, lctx->inc);
453 if (lctx->f != NULL) {
454 result = isc_stdio_close(lctx->f);
455 if (result != ISC_R_SUCCESS) {
456 UNEXPECTED_ERROR(__FILE__, __LINE__,
457 "isc_stdio_close() failed: %s",
458 isc_result_totext(result));
462 /* isc_lex_destroy() will close all open streams */
463 if (lctx->lex != NULL && !lctx->keep_lex)
464 isc_lex_destroy(&lctx->lex);
466 if (lctx->task != NULL)
467 isc_task_detach(&lctx->task);
468 DESTROYLOCK(&lctx->lock);
470 isc_mem_attach(lctx->mctx, &mctx);
471 isc_mem_detach(&lctx->mctx);
472 isc_mem_put(mctx, lctx, sizeof(*lctx));
473 isc_mem_detach(&mctx);
477 incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
482 ictx = isc_mem_get(mctx, sizeof(*ictx));
484 return (ISC_R_NOMEMORY);
486 for (i = 0; i < NBUFS; i++) {
487 dns_fixedname_init(&ictx->fixed[i]);
488 ictx->in_use[i] = ISC_FALSE;
491 ictx->origin_in_use = 0;
492 ictx->origin = dns_fixedname_name(&ictx->fixed[ictx->origin_in_use]);
493 ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
494 dns_name_toregion(origin, &r);
495 dns_name_fromregion(ictx->origin, &r);
498 ictx->current = NULL;
499 ictx->glue_in_use = -1;
500 ictx->current_in_use = -1;
502 ictx->drop = ISC_FALSE;
504 ictx->current_line = 0;
507 return (ISC_R_SUCCESS);
511 loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
512 unsigned int options, isc_uint32_t resign, dns_name_t *top,
513 dns_rdataclass_t zclass, dns_name_t *origin,
514 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
515 dns_loaddonefunc_t done, void *done_arg, isc_lex_t *lex,
516 dns_loadctx_t **lctxp)
521 isc_lexspecials_t specials;
523 REQUIRE(lctxp != NULL && *lctxp == NULL);
524 REQUIRE(callbacks != NULL);
525 REQUIRE(callbacks->add != NULL);
526 REQUIRE(callbacks->error != NULL);
527 REQUIRE(callbacks->warn != NULL);
528 REQUIRE(mctx != NULL);
529 REQUIRE(dns_name_isabsolute(top));
530 REQUIRE(dns_name_isabsolute(origin));
531 REQUIRE((task == NULL && done == NULL) ||
532 (task != NULL && done != NULL));
534 lctx = isc_mem_get(mctx, sizeof(*lctx));
536 return (ISC_R_NOMEMORY);
537 result = isc_mutex_init(&lctx->lock);
538 if (result != ISC_R_SUCCESS) {
539 isc_mem_put(mctx, lctx, sizeof(*lctx));
544 result = incctx_create(mctx, origin, &lctx->inc);
545 if (result != ISC_R_SUCCESS)
548 lctx->format = format;
552 case dns_masterformat_text:
553 lctx->openfile = openfile_text;
554 lctx->load = load_text;
556 case dns_masterformat_raw:
557 lctx->openfile = openfile_raw;
558 lctx->load = load_raw;
564 lctx->keep_lex = ISC_TRUE;
567 result = isc_lex_create(mctx, TOKENSIZ, &lctx->lex);
568 if (result != ISC_R_SUCCESS)
570 lctx->keep_lex = ISC_FALSE;
571 memset(specials, 0, sizeof(specials));
576 isc_lex_setspecials(lctx->lex, specials);
577 isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE);
580 lctx->ttl_known = ISC_FALSE;
582 lctx->default_ttl_known = ISC_FALSE;
583 lctx->default_ttl = 0;
584 lctx->warn_1035 = ISC_TRUE; /* XXX Argument? */
585 lctx->warn_tcr = ISC_TRUE; /* XXX Argument? */
586 lctx->warn_sigexpired = ISC_TRUE; /* XXX Argument? */
587 lctx->options = options;
588 lctx->seen_include = ISC_FALSE;
589 lctx->zclass = zclass;
590 lctx->resign = resign;
591 lctx->result = ISC_R_SUCCESS;
593 dns_fixedname_init(&lctx->fixed_top);
594 lctx->top = dns_fixedname_name(&lctx->fixed_top);
595 dns_name_toregion(top, &r);
596 dns_name_fromregion(lctx->top, &r);
599 lctx->first = ISC_TRUE;
601 lctx->loop_cnt = (done != NULL) ? 100 : 0;
602 lctx->callbacks = callbacks;
605 isc_task_attach(task, &lctx->task);
607 lctx->done_arg = done_arg;
608 lctx->canceled = ISC_FALSE;
610 isc_mem_attach(mctx, &lctx->mctx);
611 lctx->references = 1; /* Implicit attach. */
612 lctx->magic = DNS_LCTX_MAGIC;
614 return (ISC_R_SUCCESS);
617 incctx_destroy(mctx, lctx->inc);
619 isc_mem_put(mctx, lctx, sizeof(*lctx));
623 static const char *hex = "0123456789abcdef0123456789ABCDEF";
626 * Convert value into a nibble sequence from least significant to most
627 * significant nibble. Zero fill upper most significant nibbles if
628 * required to make the width.
630 * Returns the number of characters that should have been written without
631 * counting the terminating NUL.
634 nibbles(char *numbuf, size_t length, unsigned int width, char mode, int value) {
635 unsigned int count = 0;
638 * This reserve space for the NUL string terminator.
645 char val = hex[(value & 0x0f) + ((mode == 'n') ? 0 : 16)];
656 * If width is non zero then we need to add a label seperator.
657 * If value is non zero then we need to add another label and
658 * that requires a label seperator.
660 if (width > 0 || value != 0) {
670 } while (value != 0 || width > 0);
675 genname(char *name, int it, char *buffer, size_t length) {
676 char fmt[sizeof("%04000000000d")];
684 isc_boolean_t nibblemode;
687 r.length = (unsigned int)length;
689 while (*name != '\0') {
694 return (ISC_R_NOSPACE);
696 isc_textregion_consume(&r, 1);
699 nibblemode = ISC_FALSE;
701 /* Get format specifier. */
703 n = sscanf(name, "{%d,%u,%1[doxXnN]}",
704 &delta, &width, mode);
709 n = snprintf(fmt, sizeof(fmt),
713 if (mode[0] == 'n' || mode[0] == 'N')
714 nibblemode = ISC_TRUE;
715 n = snprintf(fmt, sizeof(fmt),
716 "%%0%u%c", width, mode[0]);
719 return (DNS_R_SYNTAX);
721 if (n >= sizeof(fmt))
722 return (ISC_R_NOSPACE);
723 /* Skip past closing brace. */
724 while (*name != '\0' && *name++ != '}')
728 n = nibbles(numbuf, sizeof(numbuf), width,
729 mode[0], it + delta);
731 n = snprintf(numbuf, sizeof(numbuf), fmt,
733 if (n >= sizeof(numbuf))
734 return (ISC_R_NOSPACE);
736 while (*cp != '\0') {
738 return (ISC_R_NOSPACE);
740 isc_textregion_consume(&r, 1);
742 } else if (*name == '\\') {
744 return (ISC_R_NOSPACE);
746 isc_textregion_consume(&r, 1);
750 return (ISC_R_NOSPACE);
752 isc_textregion_consume(&r, 1);
755 return (ISC_R_NOSPACE);
757 isc_textregion_consume(&r, 1);
761 return (ISC_R_NOSPACE);
763 return (ISC_R_SUCCESS);
767 openfile_text(dns_loadctx_t *lctx, const char *master_file) {
768 return (isc_lex_openfile(lctx->lex, master_file));
772 openfile_raw(dns_loadctx_t *lctx, const char *master_file) {
775 result = isc_stdio_open(master_file, "rb", &lctx->f);
776 if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
777 UNEXPECTED_ERROR(__FILE__, __LINE__,
778 "isc_stdio_open() failed: %s",
779 isc_result_totext(result));
786 generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
787 const char *source, unsigned int line)
789 char *target_mem = NULL;
792 dns_fixedname_t ownerfixed;
794 dns_rdata_t rdata = DNS_RDATA_INIT;
795 dns_rdatacallbacks_t *callbacks;
796 dns_rdatalist_t rdatalist;
797 dns_rdatatype_t type;
798 rdatalist_head_t head;
800 int target_size = MINTSIZ; /* only one rdata at a time */
805 unsigned int start, stop, step, i;
809 callbacks = lctx->callbacks;
810 dns_fixedname_init(&ownerfixed);
811 owner = dns_fixedname_name(&ownerfixed);
814 target_mem = isc_mem_get(lctx->mctx, target_size);
815 rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_RHS);
816 lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_LHS);
817 if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) {
818 result = ISC_R_NOMEMORY;
821 isc_buffer_init(&target, target_mem, target_size);
823 n = sscanf(range, "%u-%u/%u", &start, &stop, &step);
824 if (n < 2 || stop < start) {
825 (*callbacks->error)(callbacks,
826 "%s: %s:%lu: invalid range '%s'",
827 "$GENERATE", source, line, range);
828 result = DNS_R_SYNTAX;
838 r.length = strlen(gtype);
839 result = dns_rdatatype_fromtext(&type, &r);
840 if (result != ISC_R_SUCCESS) {
841 (*callbacks->error)(callbacks,
842 "%s: %s:%lu: unknown RR type '%s'",
843 "$GENERATE", source, line, gtype);
847 ISC_LIST_INIT(rdatalist.rdata);
848 ISC_LINK_INIT(&rdatalist, link);
849 for (i = start; i <= stop; i += step) {
850 result = genname(lhs, i, lhsbuf, DNS_MASTER_LHS);
851 if (result != ISC_R_SUCCESS)
853 result = genname(rhs, i, rhsbuf, DNS_MASTER_RHS);
854 if (result != ISC_R_SUCCESS)
857 isc_buffer_init(&buffer, lhsbuf, strlen(lhsbuf));
858 isc_buffer_add(&buffer, strlen(lhsbuf));
859 isc_buffer_setactive(&buffer, strlen(lhsbuf));
860 result = dns_name_fromtext(owner, &buffer, ictx->origin,
862 if (result != ISC_R_SUCCESS)
865 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
866 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
867 (lctx->options & DNS_MASTER_KEY) == 0 &&
868 !dns_name_issubdomain(owner, lctx->top))
870 char namebuf[DNS_NAME_FORMATSIZE];
871 dns_name_format(owner, namebuf, sizeof(namebuf));
873 * Ignore out-of-zone data.
875 (*callbacks->warn)(callbacks,
877 "ignoring out-of-zone data (%s)",
878 source, line, namebuf);
882 isc_buffer_init(&buffer, rhsbuf, strlen(rhsbuf));
883 isc_buffer_add(&buffer, strlen(rhsbuf));
884 isc_buffer_setactive(&buffer, strlen(rhsbuf));
886 result = isc_lex_openbuffer(lctx->lex, &buffer);
887 if (result != ISC_R_SUCCESS)
890 isc_buffer_init(&target, target_mem, target_size);
891 result = dns_rdata_fromtext(&rdata, lctx->zclass, type,
892 lctx->lex, ictx->origin, 0,
893 lctx->mctx, &target, callbacks);
894 RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
895 if (result != ISC_R_SUCCESS)
898 rdatalist.type = type;
899 rdatalist.covers = 0;
900 rdatalist.rdclass = lctx->zclass;
901 rdatalist.ttl = lctx->ttl;
902 ISC_LIST_PREPEND(head, &rdatalist, link);
903 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
904 result = commit(callbacks, lctx, &head, owner, source, line);
905 ISC_LIST_UNLINK(rdatalist.rdata, &rdata, link);
906 if (result != ISC_R_SUCCESS)
908 dns_rdata_reset(&rdata);
910 result = ISC_R_SUCCESS;
914 if (result == ISC_R_NOMEMORY)
915 (*callbacks->error)(callbacks, "$GENERATE: %s",
916 dns_result_totext(result));
918 (*callbacks->error)(callbacks, "$GENERATE: %s:%lu: %s",
919 source, line, dns_result_totext(result));
922 INSIST(result != ISC_R_SUCCESS);
925 if (target_mem != NULL)
926 isc_mem_put(lctx->mctx, target_mem, target_size);
928 isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_LHS);
930 isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_RHS);
935 limit_ttl(dns_rdatacallbacks_t *callbacks, const char *source, unsigned int line,
938 if (*ttlp > 0x7fffffffUL) {
939 (callbacks->warn)(callbacks,
941 "$TTL %lu > MAXTTL, "
951 check_ns(dns_loadctx_t *lctx, isc_token_t *token, const char *source,
955 isc_result_t result = ISC_R_SUCCESS;
956 void (*callback)(struct dns_rdatacallbacks *, const char *, ...);
958 if ((lctx->options & DNS_MASTER_FATALNS) != 0)
959 callback = lctx->callbacks->error;
961 callback = lctx->callbacks->warn;
963 if (token->type == isc_tokentype_string) {
965 struct in6_addr addr6;
967 tmp = isc_mem_strdup(lctx->mctx, DNS_AS_STR(*token));
969 return (ISC_R_NOMEMORY);
971 * Catch both "1.2.3.4" and "1.2.3.4."
973 if (tmp[strlen(tmp) - 1] == '.')
974 tmp[strlen(tmp) - 1] = '\0';
975 if (inet_aton(tmp, &addr) == 1 ||
976 inet_pton(AF_INET6, tmp, &addr6) == 1)
977 result = DNS_R_NSISADDRESS;
979 if (result != ISC_R_SUCCESS)
980 (*callback)(lctx->callbacks, "%s:%lu: NS record '%s' "
981 "appears to be an address",
982 source, line, DNS_AS_STR(*token));
984 isc_mem_free(lctx->mctx, tmp);
989 check_wildcard(dns_incctx_t *ictx, const char *source, unsigned long line,
990 dns_rdatacallbacks_t *callbacks)
994 name = (ictx->glue != NULL) ? ictx->glue : ictx->current;
995 if (dns_name_internalwildcard(name)) {
996 char namebuf[DNS_NAME_FORMATSIZE];
998 dns_name_format(name, namebuf, sizeof(namebuf));
999 (*callbacks->warn)(callbacks, "%s:%lu: warning: ownername "
1000 "'%s' contains an non-terminal wildcard",
1001 source, line, namebuf);
1006 load_text(dns_loadctx_t *lctx) {
1007 dns_rdataclass_t rdclass;
1008 dns_rdatatype_t type, covers;
1009 isc_uint32_t ttl_offset = 0;
1010 dns_name_t *new_name;
1011 isc_boolean_t current_has_delegation = ISC_FALSE;
1012 isc_boolean_t done = ISC_FALSE;
1013 isc_boolean_t finish_origin = ISC_FALSE;
1014 isc_boolean_t finish_include = ISC_FALSE;
1015 isc_boolean_t read_till_eol = ISC_FALSE;
1016 isc_boolean_t initialws;
1017 char *include_file = NULL;
1019 isc_result_t result = ISC_R_UNEXPECTED;
1020 rdatalist_head_t glue_list;
1021 rdatalist_head_t current_list;
1022 dns_rdatalist_t *this;
1023 dns_rdatalist_t *rdatalist = NULL;
1024 dns_rdatalist_t *new_rdatalist;
1026 int rdlcount_save = 0;
1027 int rdatalist_size = 0;
1028 isc_buffer_t buffer;
1029 isc_buffer_t target;
1030 isc_buffer_t target_ft;
1031 isc_buffer_t target_save;
1032 dns_rdata_t *rdata = NULL;
1033 dns_rdata_t *new_rdata;
1035 int rdcount_save = 0;
1037 unsigned char *target_mem = NULL;
1038 int target_size = TSIZ;
1040 unsigned int loop_cnt = 0;
1042 dns_rdatacallbacks_t *callbacks;
1048 const char *source = "";
1049 unsigned long line = 0;
1050 isc_boolean_t explicit_ttl;
1052 char classname1[DNS_RDATACLASS_FORMATSIZE];
1053 char classname2[DNS_RDATACLASS_FORMATSIZE];
1054 unsigned int options = 0;
1056 REQUIRE(DNS_LCTX_VALID(lctx));
1057 callbacks = lctx->callbacks;
1061 ISC_LIST_INIT(glue_list);
1062 ISC_LIST_INIT(current_list);
1064 isc_stdtime_get(&now);
1067 * Allocate target_size of buffer space. This is greater than twice
1068 * the maximum individual RR data size.
1070 target_mem = isc_mem_get(mctx, target_size);
1071 if (target_mem == NULL) {
1072 result = ISC_R_NOMEMORY;
1073 goto log_and_cleanup;
1075 isc_buffer_init(&target, target_mem, target_size);
1076 target_save = target;
1078 if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0)
1079 options |= DNS_RDATA_CHECKNAMES;
1080 if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0)
1081 options |= DNS_RDATA_CHECKNAMESFAIL;
1082 if ((lctx->options & DNS_MASTER_CHECKMX) != 0)
1083 options |= DNS_RDATA_CHECKMX;
1084 if ((lctx->options & DNS_MASTER_CHECKMXFAIL) != 0)
1085 options |= DNS_RDATA_CHECKMXFAIL;
1086 source = isc_lex_getsourcename(lctx->lex);
1088 initialws = ISC_FALSE;
1089 line = isc_lex_getsourceline(lctx->lex);
1090 GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS | ISC_LEXOPT_QSTRING,
1092 line = isc_lex_getsourceline(lctx->lex);
1094 if (token.type == isc_tokentype_eof) {
1096 WARNUNEXPECTEDEOF(lctx->lex);
1097 /* Pop the include stack? */
1098 if (ictx->parent != NULL) {
1100 lctx->inc = ictx->parent;
1101 ictx->parent = NULL;
1102 incctx_destroy(lctx->mctx, ictx);
1103 RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
1104 line = isc_lex_getsourceline(lctx->lex);
1105 source = isc_lex_getsourcename(lctx->lex);
1114 if (token.type == isc_tokentype_eol) {
1115 read_till_eol = ISC_FALSE;
1116 continue; /* blank line */
1122 if (token.type == isc_tokentype_initialws) {
1124 * Still working on the same name.
1126 initialws = ISC_TRUE;
1127 } else if (token.type == isc_tokentype_string ||
1128 token.type == isc_tokentype_qstring) {
1133 * "$ORIGIN" and "$INCLUDE" can both take domain names.
1134 * The processing of "$ORIGIN" and "$INCLUDE" extends
1135 * across the normal domain name processing.
1138 if (strcasecmp(DNS_AS_STR(token), "$ORIGIN") == 0) {
1139 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1140 finish_origin = ISC_TRUE;
1141 } else if (strcasecmp(DNS_AS_STR(token),
1143 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1145 dns_ttl_fromtext(&token.value.as_textregion,
1147 if (MANYERRS(lctx, result)) {
1148 SETRESULT(lctx, result);
1150 } else if (result != ISC_R_SUCCESS)
1151 goto insist_and_cleanup;
1152 limit_ttl(callbacks, source, line, &lctx->ttl);
1153 lctx->default_ttl = lctx->ttl;
1154 lctx->default_ttl_known = ISC_TRUE;
1157 } else if (strcasecmp(DNS_AS_STR(token),
1160 if ((lctx->options & DNS_MASTER_NOINCLUDE)
1163 (callbacks->error)(callbacks,
1164 "%s: %s:%lu: $INCLUDE not allowed",
1167 result = DNS_R_REFUSED;
1168 goto insist_and_cleanup;
1170 if (ttl_offset != 0) {
1171 (callbacks->error)(callbacks,
1172 "%s: %s:%lu: $INCLUDE "
1173 "may not be used with $DATE",
1176 result = DNS_R_SYNTAX;
1177 goto insist_and_cleanup;
1179 GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
1181 if (include_file != NULL)
1182 isc_mem_free(mctx, include_file);
1183 include_file = isc_mem_strdup(mctx,
1185 if (include_file == NULL) {
1186 result = ISC_R_NOMEMORY;
1187 goto log_and_cleanup;
1189 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE);
1191 if (token.type == isc_tokentype_eol ||
1192 token.type == isc_tokentype_eof) {
1193 if (token.type == isc_tokentype_eof)
1194 WARNUNEXPECTEDEOF(lctx->lex);
1195 isc_lex_ungettoken(lctx->lex, &token);
1199 result = pushfile(include_file,
1200 ictx->origin, lctx);
1201 if (MANYERRS(lctx, result)) {
1202 SETRESULT(lctx, result);
1203 LOGITFILE(result, include_file);
1205 } else if (result != ISC_R_SUCCESS) {
1206 LOGITFILE(result, include_file);
1207 goto insist_and_cleanup;
1211 isc_lex_getsourcename(lctx->lex);
1212 line = isc_lex_getsourceline(lctx->lex);
1217 * There is an origin field. Fall through
1218 * to domain name processing code and do
1219 * the actual inclusion later.
1221 finish_include = ISC_TRUE;
1222 } else if (strcasecmp(DNS_AS_STR(token),
1224 isc_int64_t dump_time64;
1225 isc_stdtime_t dump_time, current_time;
1226 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1227 isc_stdtime_get(¤t_time);
1228 result = dns_time64_fromtext(DNS_AS_STR(token),
1230 if (MANYERRS(lctx, result)) {
1231 SETRESULT(lctx, result);
1234 } else if (result != ISC_R_SUCCESS)
1235 goto log_and_cleanup;
1236 dump_time = (isc_stdtime_t)dump_time64;
1237 if (dump_time != dump_time64) {
1238 UNEXPECTED_ERROR(__FILE__, __LINE__,
1239 "%s: %s:%lu: $DATE outside epoch",
1240 "dns_master_load", source, line);
1241 result = ISC_R_UNEXPECTED;
1242 goto insist_and_cleanup;
1244 if (dump_time > current_time) {
1245 UNEXPECTED_ERROR(__FILE__, __LINE__,
1247 "$DATE in future, using current date",
1248 "dns_master_load", source, line);
1249 dump_time = current_time;
1251 ttl_offset = current_time - dump_time;
1254 } else if (strcasecmp(DNS_AS_STR(token),
1255 "$GENERATE") == 0) {
1260 isc_mem_free(mctx, range);
1262 isc_mem_free(mctx, lhs);
1264 isc_mem_free(mctx, gtype);
1266 isc_mem_free(mctx, rhs);
1267 range = lhs = gtype = rhs = NULL;
1269 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1270 range = isc_mem_strdup(mctx,
1272 if (range == NULL) {
1273 result = ISC_R_NOMEMORY;
1274 goto log_and_cleanup;
1277 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1278 lhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1280 result = ISC_R_NOMEMORY;
1281 goto log_and_cleanup;
1284 explicit_ttl = ISC_FALSE;
1286 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1287 if (dns_rdataclass_fromtext(&rdclass,
1288 &token.value.as_textregion)
1290 GETTOKEN(lctx->lex, 0, &token,
1294 if (dns_ttl_fromtext(&token.value.as_textregion,
1297 limit_ttl(callbacks, source, line,
1299 lctx->ttl_known = ISC_TRUE;
1300 explicit_ttl = ISC_TRUE;
1301 GETTOKEN(lctx->lex, 0, &token,
1306 dns_rdataclass_fromtext(&rdclass,
1307 &token.value.as_textregion)
1309 GETTOKEN(lctx->lex, 0, &token,
1312 gtype = isc_mem_strdup(mctx,
1314 if (gtype == NULL) {
1315 result = ISC_R_NOMEMORY;
1316 goto log_and_cleanup;
1319 GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING,
1321 rhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1323 result = ISC_R_NOMEMORY;
1324 goto log_and_cleanup;
1326 if (!lctx->ttl_known &&
1327 !lctx->default_ttl_known) {
1328 (*callbacks->error)(callbacks,
1329 "%s: %s:%lu: no TTL specified",
1330 "dns_master_load", source, line);
1331 result = DNS_R_NOTTL;
1332 if (MANYERRS(lctx, result)) {
1333 SETRESULT(lctx, result);
1335 } else if (result != ISC_R_SUCCESS)
1336 goto insist_and_cleanup;
1337 } else if (!explicit_ttl &&
1338 lctx->default_ttl_known) {
1339 lctx->ttl = lctx->default_ttl;
1342 * If the class specified does not match the
1343 * zone's class print out a error message and
1346 if (rdclass != 0 && rdclass != lctx->zclass) {
1349 result = generate(lctx, range, lhs, gtype, rhs,
1351 if (MANYERRS(lctx, result)) {
1352 SETRESULT(lctx, result);
1353 } else if (result != ISC_R_SUCCESS)
1354 goto insist_and_cleanup;
1357 } else if (strncasecmp(DNS_AS_STR(token),
1359 (callbacks->error)(callbacks,
1361 "unknown $ directive '%s'",
1362 "dns_master_load", source, line,
1364 result = DNS_R_SYNTAX;
1365 if (MANYERRS(lctx, result)) {
1366 SETRESULT(lctx, result);
1367 } else if (result != ISC_R_SUCCESS)
1368 goto insist_and_cleanup;
1372 * Normal processing resumes.
1374 * Find a free name buffer.
1376 for (new_in_use = 0; new_in_use < NBUFS; new_in_use++)
1377 if (!ictx->in_use[new_in_use])
1379 INSIST(new_in_use < NBUFS);
1380 dns_fixedname_init(&ictx->fixed[new_in_use]);
1381 new_name = dns_fixedname_name(&ictx->fixed[new_in_use]);
1382 isc_buffer_init(&buffer, token.value.as_region.base,
1383 token.value.as_region.length);
1384 isc_buffer_add(&buffer, token.value.as_region.length);
1385 isc_buffer_setactive(&buffer,
1386 token.value.as_region.length);
1387 result = dns_name_fromtext(new_name, &buffer,
1388 ictx->origin, 0, NULL);
1389 if (MANYERRS(lctx, result)) {
1390 SETRESULT(lctx, result);
1392 read_till_eol = ISC_TRUE;
1394 } else if (result != ISC_R_SUCCESS)
1395 goto log_and_cleanup;
1398 * Finish $ORIGIN / $INCLUDE processing if required.
1400 if (finish_origin) {
1401 if (ictx->origin_in_use != -1)
1402 ictx->in_use[ictx->origin_in_use] =
1404 ictx->origin_in_use = new_in_use;
1405 ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
1406 ictx->origin = new_name;
1407 ictx->origin_changed = ISC_TRUE;
1408 finish_origin = ISC_FALSE;
1412 if (finish_include) {
1413 finish_include = ISC_FALSE;
1414 result = pushfile(include_file, new_name, lctx);
1415 if (MANYERRS(lctx, result)) {
1416 SETRESULT(lctx, result);
1417 LOGITFILE(result, include_file);
1419 } else if (result != ISC_R_SUCCESS) {
1420 LOGITFILE(result, include_file);
1421 goto insist_and_cleanup;
1424 source = isc_lex_getsourcename(lctx->lex);
1425 line = isc_lex_getsourceline(lctx->lex);
1431 * "$" Processing Finished
1435 * If we are processing glue and the new name does
1436 * not match the current glue name, commit the glue
1437 * and pop stacks leaving us in 'normal' processing
1438 * state. Linked lists are undone by commit().
1440 if (ictx->glue != NULL &&
1441 dns_name_compare(ictx->glue, new_name) != 0) {
1442 result = commit(callbacks, lctx, &glue_list,
1445 if (MANYERRS(lctx, result)) {
1446 SETRESULT(lctx, result);
1447 } else if (result != ISC_R_SUCCESS)
1448 goto insist_and_cleanup;
1449 if (ictx->glue_in_use != -1)
1450 ictx->in_use[ictx->glue_in_use] =
1452 ictx->glue_in_use = -1;
1454 rdcount = rdcount_save;
1455 rdlcount = rdlcount_save;
1456 target = target_save;
1460 * If we are in 'normal' processing state and the new
1461 * name does not match the current name, see if the
1462 * new name is for glue and treat it as such,
1463 * otherwise we have a new name so commit what we
1466 if ((ictx->glue == NULL) && (ictx->current == NULL ||
1467 dns_name_compare(ictx->current, new_name) != 0)) {
1468 if (current_has_delegation &&
1469 is_glue(¤t_list, new_name)) {
1470 rdcount_save = rdcount;
1471 rdlcount_save = rdlcount;
1472 target_save = target;
1473 ictx->glue = new_name;
1474 ictx->glue_in_use = new_in_use;
1475 ictx->in_use[ictx->glue_in_use] =
1478 result = commit(callbacks, lctx,
1482 ictx->current_line);
1483 if (MANYERRS(lctx, result)) {
1484 SETRESULT(lctx, result);
1485 } else if (result != ISC_R_SUCCESS)
1486 goto insist_and_cleanup;
1489 if (ictx->current_in_use != -1)
1490 ictx->in_use[ictx->current_in_use] =
1492 ictx->current_in_use = new_in_use;
1493 ictx->in_use[ictx->current_in_use] =
1495 ictx->current = new_name;
1496 current_has_delegation = ISC_FALSE;
1497 isc_buffer_init(&target, target_mem,
1501 * Check for internal wildcards.
1503 if ((lctx->options & DNS_MASTER_CHECKWILDCARD)
1505 check_wildcard(ictx, source, line,
1509 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
1510 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
1511 (lctx->options & DNS_MASTER_KEY) == 0 &&
1512 !dns_name_issubdomain(new_name, lctx->top))
1514 char namebuf[DNS_NAME_FORMATSIZE];
1515 dns_name_format(new_name, namebuf,
1518 * Ignore out-of-zone data.
1520 (*callbacks->warn)(callbacks,
1522 "ignoring out-of-zone data (%s)",
1523 source, line, namebuf);
1524 ictx->drop = ISC_TRUE;
1526 ictx->drop = ISC_FALSE;
1528 UNEXPECTED_ERROR(__FILE__, __LINE__,
1529 "%s:%lu: isc_lex_gettoken() returned "
1530 "unexpected token type (%d)",
1531 source, line, token.type);
1532 result = ISC_R_UNEXPECTED;
1533 if (MANYERRS(lctx, result)) {
1534 SETRESULT(lctx, result);
1537 } else if (result != ISC_R_SUCCESS)
1538 goto insist_and_cleanup;
1542 * Find TTL, class and type. Both TTL and class are optional
1543 * and may occur in any order if they exist. TTL and class
1544 * come before type which must exist.
1546 * [<TTL>] [<class>] <type> <RDATA>
1547 * [<class>] [<TTL>] <type> <RDATA>
1553 GETTOKEN(lctx->lex, 0, &token, initialws);
1556 if (token.type == isc_tokentype_eol) {
1557 read_till_eol = ISC_FALSE;
1558 continue; /* blank line */
1561 if (token.type == isc_tokentype_eof) {
1562 WARNUNEXPECTEDEOF(lctx->lex);
1563 read_till_eol = ISC_FALSE;
1564 isc_lex_ungettoken(lctx->lex, &token);
1568 if (ictx->current == NULL) {
1569 (*callbacks->error)(callbacks,
1570 "%s:%lu: no current owner name",
1572 result = DNS_R_NOOWNER;
1573 if (MANYERRS(lctx, result)) {
1574 SETRESULT(lctx, result);
1575 read_till_eol = ISC_TRUE;
1577 } else if (result != ISC_R_SUCCESS)
1578 goto insist_and_cleanup;
1581 if (ictx->origin_changed) {
1582 char cbuf[DNS_NAME_FORMATSIZE];
1583 char obuf[DNS_NAME_FORMATSIZE];
1584 dns_name_format(ictx->current, cbuf,
1586 dns_name_format(ictx->origin, obuf,
1588 (*callbacks->warn)(callbacks,
1589 "%s:%lu: record with inherited "
1590 "owner (%s) immediately after "
1591 "$ORIGIN (%s)", source, line,
1596 ictx->origin_changed = ISC_FALSE;
1598 if (dns_rdataclass_fromtext(&rdclass,
1599 &token.value.as_textregion)
1601 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1603 explicit_ttl = ISC_FALSE;
1604 if (dns_ttl_fromtext(&token.value.as_textregion, &lctx->ttl)
1606 limit_ttl(callbacks, source, line, &lctx->ttl);
1607 explicit_ttl = ISC_TRUE;
1608 lctx->ttl_known = ISC_TRUE;
1609 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1612 if (token.type != isc_tokentype_string) {
1613 UNEXPECTED_ERROR(__FILE__, __LINE__,
1614 "isc_lex_gettoken() returned unexpected token type");
1615 result = ISC_R_UNEXPECTED;
1616 if (MANYERRS(lctx, result)) {
1617 SETRESULT(lctx, result);
1618 read_till_eol = ISC_TRUE;
1620 } else if (result != ISC_R_SUCCESS)
1621 goto insist_and_cleanup;
1625 dns_rdataclass_fromtext(&rdclass,
1626 &token.value.as_textregion)
1628 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1630 if (token.type != isc_tokentype_string) {
1631 UNEXPECTED_ERROR(__FILE__, __LINE__,
1632 "isc_lex_gettoken() returned unexpected token type");
1633 result = ISC_R_UNEXPECTED;
1634 if (MANYERRS(lctx, result)) {
1635 SETRESULT(lctx, result);
1636 read_till_eol = ISC_TRUE;
1638 } else if (result != ISC_R_SUCCESS)
1639 goto insist_and_cleanup;
1642 result = dns_rdatatype_fromtext(&type,
1643 &token.value.as_textregion);
1644 if (result != ISC_R_SUCCESS) {
1645 (*callbacks->warn)(callbacks,
1646 "%s:%lu: unknown RR type '%.*s'",
1648 token.value.as_textregion.length,
1649 token.value.as_textregion.base);
1650 if (MANYERRS(lctx, result)) {
1651 SETRESULT(lctx, result);
1652 read_till_eol = ISC_TRUE;
1654 } else if (result != ISC_R_SUCCESS)
1655 goto insist_and_cleanup;
1659 * If the class specified does not match the zone's class
1660 * print out a error message and exit.
1662 if (rdclass != 0 && rdclass != lctx->zclass) {
1665 dns_rdataclass_format(rdclass, classname1,
1666 sizeof(classname1));
1667 dns_rdataclass_format(lctx->zclass, classname2,
1668 sizeof(classname2));
1669 (*callbacks->error)(callbacks,
1670 "%s:%lu: class '%s' != "
1673 classname1, classname2);
1674 result = DNS_R_BADCLASS;
1675 if (MANYERRS(lctx, result)) {
1676 SETRESULT(lctx, result);
1677 read_till_eol = ISC_TRUE;
1679 } else if (result != ISC_R_SUCCESS)
1680 goto insist_and_cleanup;
1683 if (type == dns_rdatatype_ns && ictx->glue == NULL)
1684 current_has_delegation = ISC_TRUE;
1687 * RFC1123: MD and MF are not allowed to be loaded from
1690 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
1691 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
1692 (type == dns_rdatatype_md || type == dns_rdatatype_mf)) {
1693 char typename[DNS_RDATATYPE_FORMATSIZE];
1695 result = DNS_R_OBSOLETE;
1697 dns_rdatatype_format(type, typename, sizeof(typename));
1698 (*callbacks->error)(callbacks,
1699 "%s:%lu: %s '%s': %s",
1702 dns_result_totext(result));
1703 if (MANYERRS(lctx, result)) {
1704 SETRESULT(lctx, result);
1706 goto insist_and_cleanup;
1710 * Find a rdata structure.
1712 if (rdcount == rdata_size) {
1713 new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
1714 rdata_size, ¤t_list,
1716 if (new_rdata == NULL) {
1717 result = ISC_R_NOMEMORY;
1718 goto log_and_cleanup;
1725 * Peek at the NS record.
1727 if (type == dns_rdatatype_ns &&
1728 lctx->zclass == dns_rdataclass_in &&
1729 (lctx->options & DNS_MASTER_CHECKNS) != 0) {
1731 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1732 result = check_ns(lctx, &token, source, line);
1733 isc_lex_ungettoken(lctx->lex, &token);
1734 if ((lctx->options & DNS_MASTER_FATALNS) != 0) {
1735 if (MANYERRS(lctx, result)) {
1736 SETRESULT(lctx, result);
1737 } else if (result != ISC_R_SUCCESS)
1738 goto insist_and_cleanup;
1745 options &= ~DNS_RDATA_CHECKREVERSE;
1746 if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0) {
1750 name = (ictx->glue != NULL) ? ictx->glue :
1752 ok = dns_rdata_checkowner(name, lctx->zclass, type,
1755 char namebuf[DNS_NAME_FORMATSIZE];
1757 dns_name_format(name, namebuf, sizeof(namebuf));
1758 result = DNS_R_BADOWNERNAME;
1759 desc = dns_result_totext(result);
1760 if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0) {
1761 (*callbacks->error)(callbacks,
1765 if (MANYERRS(lctx, result)) {
1766 SETRESULT(lctx, result);
1767 } else if (result != ISC_R_SUCCESS)
1770 (*callbacks->warn)(callbacks,
1776 if (type == dns_rdatatype_ptr &&
1777 (dns_name_issubdomain(name, &in_addr_arpa) ||
1778 dns_name_issubdomain(name, &ip6_arpa) ||
1779 dns_name_issubdomain(name, &ip6_int)))
1780 options |= DNS_RDATA_CHECKREVERSE;
1784 * Read rdata contents.
1786 dns_rdata_init(&rdata[rdcount]);
1788 result = dns_rdata_fromtext(&rdata[rdcount], lctx->zclass,
1789 type, lctx->lex, ictx->origin,
1790 options, lctx->mctx, &target,
1792 if (MANYERRS(lctx, result)) {
1793 SETRESULT(lctx, result);
1795 } else if (result != ISC_R_SUCCESS)
1796 goto insist_and_cleanup;
1803 if (type == dns_rdatatype_soa &&
1804 (lctx->options & DNS_MASTER_ZONE) != 0 &&
1805 dns_name_compare(ictx->current, lctx->top) != 0) {
1806 char namebuf[DNS_NAME_FORMATSIZE];
1807 dns_name_format(ictx->current, namebuf,
1809 (*callbacks->error)(callbacks, "%s:%lu: SOA "
1810 "record not at top of zone (%s)",
1811 source, line, namebuf);
1812 result = DNS_R_NOTZONETOP;
1813 if (MANYERRS(lctx, result)) {
1814 SETRESULT(lctx, result);
1815 read_till_eol = ISC_TRUE;
1818 } else if (result != ISC_R_SUCCESS)
1819 goto insist_and_cleanup;
1823 if (type == dns_rdatatype_rrsig ||
1824 type == dns_rdatatype_sig)
1825 covers = dns_rdata_covers(&rdata[rdcount]);
1829 if (!lctx->ttl_known && !lctx->default_ttl_known) {
1830 if (type == dns_rdatatype_soa) {
1831 (*callbacks->warn)(callbacks,
1832 "%s:%lu: no TTL specified; "
1833 "using SOA MINTTL instead",
1835 lctx->ttl = dns_soa_getminimum(&rdata[rdcount]);
1836 limit_ttl(callbacks, source, line, &lctx->ttl);
1837 lctx->default_ttl = lctx->ttl;
1838 lctx->default_ttl_known = ISC_TRUE;
1839 } else if ((lctx->options & DNS_MASTER_HINT) != 0) {
1841 * Zero TTL's are fine for hints.
1844 lctx->default_ttl = lctx->ttl;
1845 lctx->default_ttl_known = ISC_TRUE;
1847 (*callbacks->warn)(callbacks,
1848 "%s:%lu: no TTL specified; "
1851 result = DNS_R_NOTTL;
1852 if (MANYERRS(lctx, result)) {
1853 SETRESULT(lctx, result);
1856 goto insist_and_cleanup;
1859 } else if (!explicit_ttl && lctx->default_ttl_known) {
1860 lctx->ttl = lctx->default_ttl;
1861 } else if (!explicit_ttl && lctx->warn_1035) {
1862 (*callbacks->warn)(callbacks,
1864 "using RFC1035 TTL semantics",
1866 lctx->warn_1035 = ISC_FALSE;
1869 if (type == dns_rdatatype_rrsig && lctx->warn_sigexpired) {
1870 dns_rdata_rrsig_t sig;
1871 result = dns_rdata_tostruct(&rdata[rdcount], &sig,
1873 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1874 if (isc_serial_lt(sig.timeexpire, now)) {
1875 (*callbacks->warn)(callbacks,
1877 "signature has expired",
1879 lctx->warn_sigexpired = ISC_FALSE;
1883 if ((type == dns_rdatatype_sig || type == dns_rdatatype_nxt) &&
1884 lctx->warn_tcr && (lctx->options & DNS_MASTER_ZONE) != 0 &&
1885 (lctx->options & DNS_MASTER_SLAVE) == 0) {
1886 (*callbacks->warn)(callbacks, "%s:%lu: old style DNSSEC "
1887 " zone detected", source, line);
1888 lctx->warn_tcr = ISC_FALSE;
1891 if ((lctx->options & DNS_MASTER_AGETTL) != 0) {
1893 * Adjust the TTL for $DATE. If the RR has already
1894 * expired, ignore it.
1896 if (lctx->ttl < ttl_offset)
1898 lctx->ttl -= ttl_offset;
1902 * Find type in rdatalist.
1903 * If it does not exist create new one and prepend to list
1904 * as this will minimise list traversal.
1906 if (ictx->glue != NULL)
1907 this = ISC_LIST_HEAD(glue_list);
1909 this = ISC_LIST_HEAD(current_list);
1911 while (this != NULL) {
1912 if (this->type == type && this->covers == covers)
1914 this = ISC_LIST_NEXT(this, link);
1918 if (rdlcount == rdatalist_size) {
1920 grow_rdatalist(rdatalist_size + RDLSZ,
1926 if (new_rdatalist == NULL) {
1927 result = ISC_R_NOMEMORY;
1928 goto log_and_cleanup;
1930 rdatalist = new_rdatalist;
1931 rdatalist_size += RDLSZ;
1933 this = &rdatalist[rdlcount++];
1935 this->covers = covers;
1936 this->rdclass = lctx->zclass;
1937 this->ttl = lctx->ttl;
1938 ISC_LIST_INIT(this->rdata);
1939 if (ictx->glue != NULL)
1940 ISC_LIST_INITANDPREPEND(glue_list, this, link);
1942 ISC_LIST_INITANDPREPEND(current_list, this,
1944 } else if (this->ttl != lctx->ttl) {
1945 (*callbacks->warn)(callbacks,
1947 "TTL set to prior TTL (%lu)",
1948 source, line, this->ttl);
1949 lctx->ttl = this->ttl;
1952 ISC_LIST_APPEND(this->rdata, &rdata[rdcount], link);
1953 if (ictx->glue != NULL)
1954 ictx->glue_line = line;
1956 ictx->current_line = line;
1960 * We must have at least 64k as rdlen is 16 bits.
1961 * If we don't commit everything we have so far.
1963 if ((target.length - target.used) < MINTSIZ)
1967 } while (!done && (lctx->loop_cnt == 0 || loop_cnt++ < lctx->loop_cnt));
1970 * Commit what has not yet been committed.
1972 result = commit(callbacks, lctx, ¤t_list, ictx->current,
1973 source, ictx->current_line);
1974 if (MANYERRS(lctx, result)) {
1975 SETRESULT(lctx, result);
1976 } else if (result != ISC_R_SUCCESS)
1977 goto insist_and_cleanup;
1978 result = commit(callbacks, lctx, &glue_list, ictx->glue,
1979 source, ictx->glue_line);
1980 if (MANYERRS(lctx, result)) {
1981 SETRESULT(lctx, result);
1982 } else if (result != ISC_R_SUCCESS)
1983 goto insist_and_cleanup;
1986 INSIST(lctx->done != NULL && lctx->task != NULL);
1987 result = DNS_R_CONTINUE;
1988 } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) {
1989 result = lctx->result;
1990 } else if (result == ISC_R_SUCCESS && lctx->seen_include)
1991 result = DNS_R_SEENINCLUDE;
1998 INSIST(result != ISC_R_SUCCESS);
2001 while ((this = ISC_LIST_HEAD(current_list)) != NULL)
2002 ISC_LIST_UNLINK(current_list, this, link);
2003 while ((this = ISC_LIST_HEAD(glue_list)) != NULL)
2004 ISC_LIST_UNLINK(glue_list, this, link);
2005 if (rdatalist != NULL)
2006 isc_mem_put(mctx, rdatalist,
2007 rdatalist_size * sizeof(*rdatalist));
2009 isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
2010 if (target_mem != NULL)
2011 isc_mem_put(mctx, target_mem, target_size);
2012 if (include_file != NULL)
2013 isc_mem_free(mctx, include_file);
2015 isc_mem_free(mctx, range);
2017 isc_mem_free(mctx, lhs);
2019 isc_mem_free(mctx, gtype);
2021 isc_mem_free(mctx, rhs);
2026 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) {
2027 isc_result_t result;
2029 dns_incctx_t *new = NULL;
2033 REQUIRE(master_file != NULL);
2034 REQUIRE(DNS_LCTX_VALID(lctx));
2037 lctx->seen_include = ISC_TRUE;
2039 result = incctx_create(lctx->mctx, origin, &new);
2040 if (result != ISC_R_SUCCESS)
2043 /* Set current domain. */
2044 if (ictx->glue != NULL || ictx->current != NULL) {
2045 for (new_in_use = 0; new_in_use < NBUFS; new_in_use++)
2046 if (!new->in_use[new_in_use])
2048 INSIST(new_in_use < NBUFS);
2049 new->current_in_use = new_in_use;
2051 dns_fixedname_name(&new->fixed[new->current_in_use]);
2052 new->in_use[new->current_in_use] = ISC_TRUE;
2053 dns_name_toregion((ictx->glue != NULL) ?
2054 ictx->glue : ictx->current, &r);
2055 dns_name_fromregion(new->current, &r);
2056 new->drop = ictx->drop;
2059 result = (lctx->openfile)(lctx, master_file);
2060 if (result != ISC_R_SUCCESS)
2064 return (ISC_R_SUCCESS);
2068 incctx_destroy(lctx->mctx, new);
2072 static inline isc_result_t
2073 read_and_check(isc_boolean_t do_read, isc_buffer_t *buffer,
2074 size_t len, FILE *f)
2076 isc_result_t result;
2079 INSIST(isc_buffer_availablelength(buffer) >= len);
2080 result = isc_stdio_read(isc_buffer_used(buffer), 1, len,
2082 if (result != ISC_R_SUCCESS)
2084 isc_buffer_add(buffer, (unsigned int)len);
2085 } else if (isc_buffer_remaininglength(buffer) < len)
2086 return (ISC_R_RANGE);
2088 return (ISC_R_SUCCESS);
2092 load_raw(dns_loadctx_t *lctx) {
2093 isc_result_t result = ISC_R_SUCCESS;
2094 isc_boolean_t done = ISC_FALSE;
2095 unsigned int loop_cnt = 0;
2096 dns_rdatacallbacks_t *callbacks;
2097 unsigned char namebuf[DNS_NAME_MAXWIRE];
2098 dns_fixedname_t fixed;
2100 rdatalist_head_t head, dummy;
2101 dns_rdatalist_t rdatalist;
2102 isc_mem_t *mctx = lctx->mctx;
2103 dns_rdata_t *rdata = NULL;
2104 unsigned int rdata_size = 0;
2105 int target_size = TSIZ;
2106 isc_buffer_t target, buf;
2107 unsigned char *target_mem = NULL;
2108 dns_decompress_t dctx;
2110 REQUIRE(DNS_LCTX_VALID(lctx));
2111 callbacks = lctx->callbacks;
2112 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
2115 dns_masterrawheader_t header;
2116 isc_uint32_t format, version, dumptime;
2117 size_t hdrlen = sizeof(format) + sizeof(version) +
2120 INSIST(hdrlen <= sizeof(header));
2121 isc_buffer_init(&target, &header, sizeof(header));
2123 result = isc_stdio_read(&header, 1, hdrlen, lctx->f, NULL);
2124 if (result != ISC_R_SUCCESS) {
2125 UNEXPECTED_ERROR(__FILE__, __LINE__,
2126 "isc_stdio_read failed: %s",
2127 isc_result_totext(result));
2130 isc_buffer_add(&target, hdrlen);
2131 format = isc_buffer_getuint32(&target);
2132 if (format != dns_masterformat_raw) {
2133 (*callbacks->error)(callbacks,
2135 "file format mismatch");
2136 return (ISC_R_NOTIMPLEMENTED);
2139 version = isc_buffer_getuint32(&target);
2140 if (version > DNS_RAWFORMAT_VERSION) {
2141 (*callbacks->error)(callbacks,
2143 "unsupported file format version");
2144 return (ISC_R_NOTIMPLEMENTED);
2147 /* Empty read: currently, we do not use dumptime */
2148 dumptime = isc_buffer_getuint32(&target);
2151 lctx->first = ISC_FALSE;
2154 ISC_LIST_INIT(head);
2155 ISC_LIST_INIT(dummy);
2156 dns_rdatalist_init(&rdatalist);
2159 * Allocate target_size of buffer space. This is greater than twice
2160 * the maximum individual RR data size.
2162 target_mem = isc_mem_get(mctx, target_size);
2163 if (target_mem == NULL) {
2164 result = ISC_R_NOMEMORY;
2167 isc_buffer_init(&target, target_mem, target_size);
2169 dns_fixedname_init(&fixed);
2170 name = dns_fixedname_name(&fixed);
2173 * In the following loop, we regard any error fatal regardless of
2174 * whether "MANYERRORS" is set in the context option. This is because
2175 * normal errors should already have been checked at creation time.
2176 * Besides, it is very unlikely that we can recover from an error
2177 * in this format, and so trying to continue parsing erroneous data
2178 * does not really make sense.
2181 (lctx->loop_cnt == 0 || loop_cnt < lctx->loop_cnt);
2183 unsigned int i, rdcount;
2184 isc_uint16_t namelen;
2185 isc_uint32_t totallen;
2186 size_t minlen, readlen;
2187 isc_boolean_t sequential_read = ISC_FALSE;
2189 /* Read the data length */
2190 isc_buffer_clear(&target);
2191 INSIST(isc_buffer_availablelength(&target) >=
2193 result = isc_stdio_read(target.base, 1, sizeof(totallen),
2195 if (result == ISC_R_EOF) {
2196 result = ISC_R_SUCCESS;
2200 if (result != ISC_R_SUCCESS)
2202 isc_buffer_add(&target, sizeof(totallen));
2203 totallen = isc_buffer_getuint32(&target);
2205 * Validation: the input data must at least contain the common
2208 minlen = sizeof(totallen) + sizeof(isc_uint16_t) +
2209 sizeof(isc_uint16_t) + sizeof(isc_uint16_t) +
2210 sizeof(isc_uint32_t) + sizeof(isc_uint32_t);
2211 if (totallen < minlen) {
2212 result = ISC_R_RANGE;
2215 totallen -= sizeof(totallen);
2217 isc_buffer_clear(&target);
2218 if (totallen > isc_buffer_availablelength(&target)) {
2220 * The default buffer size should typically be large
2221 * enough to store the entire RRset. We could try to
2222 * allocate enough space if this is not the case, but
2223 * it might cause a hazardous result when "totallen"
2224 * is forged. Thus, we'd rather take an inefficient
2225 * but robust approach in this atypical case: read
2226 * data step by step, and commit partial data when
2227 * necessary. Note that the buffer must be large
2228 * enough to store the "header part", owner name, and
2229 * at least one rdata (however large it is).
2231 sequential_read = ISC_TRUE;
2232 readlen = minlen - sizeof(totallen);
2235 * Typical case. We can read the whole RRset at once
2236 * with the default buffer.
2240 result = isc_stdio_read(target.base, 1, readlen,
2242 if (result != ISC_R_SUCCESS)
2244 isc_buffer_add(&target, (unsigned int)readlen);
2246 /* Construct RRset headers */
2247 rdatalist.rdclass = isc_buffer_getuint16(&target);
2248 rdatalist.type = isc_buffer_getuint16(&target);
2249 rdatalist.covers = isc_buffer_getuint16(&target);
2250 rdatalist.ttl = isc_buffer_getuint32(&target);
2251 rdcount = isc_buffer_getuint32(&target);
2253 result = ISC_R_RANGE;
2256 INSIST(isc_buffer_consumedlength(&target) <= readlen);
2258 /* Owner name: length followed by name */
2259 result = read_and_check(sequential_read, &target,
2260 sizeof(namelen), lctx->f);
2261 if (result != ISC_R_SUCCESS)
2263 namelen = isc_buffer_getuint16(&target);
2264 if (namelen > sizeof(namebuf)) {
2265 result = ISC_R_RANGE;
2269 result = read_and_check(sequential_read, &target, namelen,
2271 if (result != ISC_R_SUCCESS)
2274 isc_buffer_setactive(&target, (unsigned int)namelen);
2275 result = dns_name_fromwire(name, &target, &dctx, 0, NULL);
2276 if (result != ISC_R_SUCCESS)
2279 /* Rdata contents. */
2280 if (rdcount > rdata_size) {
2281 dns_rdata_t *new_rdata = NULL;
2283 new_rdata = grow_rdata(rdcount + RDSZ, rdata,
2286 if (new_rdata == NULL) {
2287 result = ISC_R_NOMEMORY;
2290 rdata_size = rdcount + RDSZ;
2295 for (i = 0; i < rdcount; i++) {
2298 dns_rdata_init(&rdata[i]);
2300 if (sequential_read &&
2301 isc_buffer_availablelength(&target) < MINTSIZ) {
2304 INSIST(i > 0); /* detect an infinite loop */
2306 /* Partial Commit. */
2307 ISC_LIST_APPEND(head, &rdatalist, link);
2308 result = commit(callbacks, lctx, &head, name,
2310 for (j = 0; j < i; j++) {
2311 ISC_LIST_UNLINK(rdatalist.rdata,
2313 dns_rdata_reset(&rdata[j]);
2315 if (result != ISC_R_SUCCESS)
2318 /* Rewind the buffer and continue */
2319 isc_buffer_clear(&target);
2327 result = read_and_check(sequential_read, &target,
2328 sizeof(rdlen), lctx->f);
2329 if (result != ISC_R_SUCCESS)
2331 rdlen = isc_buffer_getuint16(&target);
2334 result = read_and_check(sequential_read, &target,
2336 if (result != ISC_R_SUCCESS)
2338 isc_buffer_setactive(&target, (unsigned int)rdlen);
2340 * It is safe to have the source active region and
2341 * the target available region be the same if
2342 * decompression is disabled (see dctx above) and we
2343 * are not downcasing names (options == 0).
2345 isc_buffer_init(&buf, isc_buffer_current(&target),
2346 (unsigned int)rdlen);
2347 result = dns_rdata_fromwire(&rdata[i],
2349 rdatalist.type, &target,
2351 if (result != ISC_R_SUCCESS)
2353 ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link);
2357 * Sanity check. Still having remaining space is not
2358 * necessarily critical, but it very likely indicates broken
2359 * or malformed data.
2361 if (isc_buffer_remaininglength(&target) != 0) {
2362 result = ISC_R_RANGE;
2366 ISC_LIST_APPEND(head, &rdatalist, link);
2368 /* Commit this RRset. rdatalist will be unlinked. */
2369 result = commit(callbacks, lctx, &head, name, NULL, 0);
2371 for (i = 0; i < rdcount; i++) {
2372 ISC_LIST_UNLINK(rdatalist.rdata, &rdata[i], link);
2373 dns_rdata_reset(&rdata[i]);
2376 if (result != ISC_R_SUCCESS)
2381 INSIST(lctx->done != NULL && lctx->task != NULL);
2382 result = DNS_R_CONTINUE;
2383 } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS)
2384 result = lctx->result;
2388 isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
2389 if (target_mem != NULL)
2390 isc_mem_put(mctx, target_mem, target_size);
2391 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE) {
2392 (*callbacks->error)(callbacks, "dns_master_load: %s",
2393 dns_result_totext(result));
2400 dns_master_loadfile(const char *master_file, dns_name_t *top,
2402 dns_rdataclass_t zclass, unsigned int options,
2403 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2405 return (dns_master_loadfile3(master_file, top, origin, zclass, options,
2406 0, callbacks, mctx, dns_masterformat_text));
2410 dns_master_loadfile2(const char *master_file, dns_name_t *top,
2412 dns_rdataclass_t zclass, unsigned int options,
2413 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
2414 dns_masterformat_t format)
2416 return (dns_master_loadfile3(master_file, top, origin, zclass, options,
2417 0, callbacks, mctx, format));
2421 dns_master_loadfile3(const char *master_file, dns_name_t *top,
2422 dns_name_t *origin, dns_rdataclass_t zclass,
2423 unsigned int options, isc_uint32_t resign,
2424 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
2425 dns_masterformat_t format)
2427 dns_loadctx_t *lctx = NULL;
2428 isc_result_t result;
2430 result = loadctx_create(format, mctx, options, resign, top, zclass,
2431 origin, callbacks, NULL, NULL, NULL, NULL,
2433 if (result != ISC_R_SUCCESS)
2436 result = (lctx->openfile)(lctx, master_file);
2437 if (result != ISC_R_SUCCESS)
2440 result = (lctx->load)(lctx);
2441 INSIST(result != DNS_R_CONTINUE);
2444 dns_loadctx_detach(&lctx);
2449 dns_master_loadfileinc(const char *master_file, dns_name_t *top,
2450 dns_name_t *origin, dns_rdataclass_t zclass,
2451 unsigned int options, dns_rdatacallbacks_t *callbacks,
2452 isc_task_t *task, dns_loaddonefunc_t done,
2453 void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx)
2455 return (dns_master_loadfileinc3(master_file, top, origin, zclass,
2456 options, 0, callbacks, task, done,
2457 done_arg, lctxp, mctx,
2458 dns_masterformat_text));
2462 dns_master_loadfileinc2(const char *master_file, dns_name_t *top,
2463 dns_name_t *origin, dns_rdataclass_t zclass,
2464 unsigned int options, dns_rdatacallbacks_t *callbacks,
2465 isc_task_t *task, dns_loaddonefunc_t done,
2466 void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx,
2467 dns_masterformat_t format)
2469 return (dns_master_loadfileinc3(master_file, top, origin, zclass,
2470 options, 0, callbacks, task, done,
2471 done_arg, lctxp, mctx, format));
2475 dns_master_loadfileinc3(const char *master_file, dns_name_t *top,
2476 dns_name_t *origin, dns_rdataclass_t zclass,
2477 unsigned int options, isc_uint32_t resign,
2478 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2479 dns_loaddonefunc_t done, void *done_arg,
2480 dns_loadctx_t **lctxp, isc_mem_t *mctx,
2481 dns_masterformat_t format)
2483 dns_loadctx_t *lctx = NULL;
2484 isc_result_t result;
2486 REQUIRE(task != NULL);
2487 REQUIRE(done != NULL);
2489 result = loadctx_create(format, mctx, options, resign, top, zclass,
2490 origin, callbacks, task, done, done_arg, NULL,
2492 if (result != ISC_R_SUCCESS)
2495 result = (lctx->openfile)(lctx, master_file);
2496 if (result != ISC_R_SUCCESS)
2499 result = task_send(lctx);
2500 if (result == ISC_R_SUCCESS) {
2501 dns_loadctx_attach(lctx, lctxp);
2502 return (DNS_R_CONTINUE);
2506 dns_loadctx_detach(&lctx);
2511 dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
2512 dns_rdataclass_t zclass, unsigned int options,
2513 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2515 isc_result_t result;
2516 dns_loadctx_t *lctx = NULL;
2518 REQUIRE(stream != NULL);
2520 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2521 zclass, origin, callbacks, NULL, NULL, NULL,
2523 if (result != ISC_R_SUCCESS)
2526 result = isc_lex_openstream(lctx->lex, stream);
2527 if (result != ISC_R_SUCCESS)
2530 result = (lctx->load)(lctx);
2531 INSIST(result != DNS_R_CONTINUE);
2535 dns_loadctx_detach(&lctx);
2540 dns_master_loadstreaminc(FILE *stream, dns_name_t *top, dns_name_t *origin,
2541 dns_rdataclass_t zclass, unsigned int options,
2542 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2543 dns_loaddonefunc_t done, void *done_arg,
2544 dns_loadctx_t **lctxp, isc_mem_t *mctx)
2546 isc_result_t result;
2547 dns_loadctx_t *lctx = NULL;
2549 REQUIRE(stream != NULL);
2550 REQUIRE(task != NULL);
2551 REQUIRE(done != NULL);
2553 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2554 zclass, origin, callbacks, task, done,
2555 done_arg, NULL, &lctx);
2556 if (result != ISC_R_SUCCESS)
2559 result = isc_lex_openstream(lctx->lex, stream);
2560 if (result != ISC_R_SUCCESS)
2563 result = task_send(lctx);
2564 if (result == ISC_R_SUCCESS) {
2565 dns_loadctx_attach(lctx, lctxp);
2566 return (DNS_R_CONTINUE);
2571 dns_loadctx_detach(&lctx);
2576 dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top,
2577 dns_name_t *origin, dns_rdataclass_t zclass,
2578 unsigned int options,
2579 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2581 isc_result_t result;
2582 dns_loadctx_t *lctx = NULL;
2584 REQUIRE(buffer != NULL);
2586 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2587 zclass, origin, callbacks, NULL, NULL, NULL,
2589 if (result != ISC_R_SUCCESS)
2592 result = isc_lex_openbuffer(lctx->lex, buffer);
2593 if (result != ISC_R_SUCCESS)
2596 result = (lctx->load)(lctx);
2597 INSIST(result != DNS_R_CONTINUE);
2600 dns_loadctx_detach(&lctx);
2605 dns_master_loadbufferinc(isc_buffer_t *buffer, dns_name_t *top,
2606 dns_name_t *origin, dns_rdataclass_t zclass,
2607 unsigned int options,
2608 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2609 dns_loaddonefunc_t done, void *done_arg,
2610 dns_loadctx_t **lctxp, isc_mem_t *mctx)
2612 isc_result_t result;
2613 dns_loadctx_t *lctx = NULL;
2615 REQUIRE(buffer != NULL);
2616 REQUIRE(task != NULL);
2617 REQUIRE(done != NULL);
2619 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2620 zclass, origin, callbacks, task, done,
2621 done_arg, NULL, &lctx);
2622 if (result != ISC_R_SUCCESS)
2625 result = isc_lex_openbuffer(lctx->lex, buffer);
2626 if (result != ISC_R_SUCCESS)
2629 result = task_send(lctx);
2630 if (result == ISC_R_SUCCESS) {
2631 dns_loadctx_attach(lctx, lctxp);
2632 return (DNS_R_CONTINUE);
2636 dns_loadctx_detach(&lctx);
2641 dns_master_loadlexer(isc_lex_t *lex, dns_name_t *top,
2642 dns_name_t *origin, dns_rdataclass_t zclass,
2643 unsigned int options,
2644 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2646 isc_result_t result;
2647 dns_loadctx_t *lctx = NULL;
2649 REQUIRE(lex != NULL);
2651 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2652 zclass, origin, callbacks, NULL, NULL, NULL,
2654 if (result != ISC_R_SUCCESS)
2657 result = (lctx->load)(lctx);
2658 INSIST(result != DNS_R_CONTINUE);
2660 dns_loadctx_detach(&lctx);
2665 dns_master_loadlexerinc(isc_lex_t *lex, dns_name_t *top,
2666 dns_name_t *origin, dns_rdataclass_t zclass,
2667 unsigned int options,
2668 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2669 dns_loaddonefunc_t done, void *done_arg,
2670 dns_loadctx_t **lctxp, isc_mem_t *mctx)
2672 isc_result_t result;
2673 dns_loadctx_t *lctx = NULL;
2675 REQUIRE(lex != NULL);
2676 REQUIRE(task != NULL);
2677 REQUIRE(done != NULL);
2679 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2680 zclass, origin, callbacks, task, done,
2681 done_arg, lex, &lctx);
2682 if (result != ISC_R_SUCCESS)
2685 result = task_send(lctx);
2686 if (result == ISC_R_SUCCESS) {
2687 dns_loadctx_attach(lctx, lctxp);
2688 return (DNS_R_CONTINUE);
2691 dns_loadctx_detach(&lctx);
2696 * Grow the slab of dns_rdatalist_t structures.
2697 * Re-link glue and current list.
2699 static dns_rdatalist_t *
2700 grow_rdatalist(int new_len, dns_rdatalist_t *old, int old_len,
2701 rdatalist_head_t *current, rdatalist_head_t *glue,
2704 dns_rdatalist_t *new;
2706 ISC_LIST(dns_rdatalist_t) save;
2707 dns_rdatalist_t *this;
2709 new = isc_mem_get(mctx, new_len * sizeof(*new));
2713 ISC_LIST_INIT(save);
2714 while ((this = ISC_LIST_HEAD(*current)) != NULL) {
2715 ISC_LIST_UNLINK(*current, this, link);
2716 ISC_LIST_APPEND(save, this, link);
2718 while ((this = ISC_LIST_HEAD(save)) != NULL) {
2719 ISC_LIST_UNLINK(save, this, link);
2720 INSIST(rdlcount < new_len);
2721 new[rdlcount] = *this;
2722 ISC_LIST_APPEND(*current, &new[rdlcount], link);
2726 ISC_LIST_INIT(save);
2727 while ((this = ISC_LIST_HEAD(*glue)) != NULL) {
2728 ISC_LIST_UNLINK(*glue, this, link);
2729 ISC_LIST_APPEND(save, this, link);
2731 while ((this = ISC_LIST_HEAD(save)) != NULL) {
2732 ISC_LIST_UNLINK(save, this, link);
2733 INSIST(rdlcount < new_len);
2734 new[rdlcount] = *this;
2735 ISC_LIST_APPEND(*glue, &new[rdlcount], link);
2739 INSIST(rdlcount == old_len);
2741 isc_mem_put(mctx, old, old_len * sizeof(*old));
2746 * Grow the slab of rdata structs.
2747 * Re-link the current and glue chains.
2749 static dns_rdata_t *
2750 grow_rdata(int new_len, dns_rdata_t *old, int old_len,
2751 rdatalist_head_t *current, rdatalist_head_t *glue,
2756 ISC_LIST(dns_rdata_t) save;
2757 dns_rdatalist_t *this;
2760 new = isc_mem_get(mctx, new_len * sizeof(*new));
2763 memset(new, 0, new_len * sizeof(*new));
2766 * Copy current relinking.
2768 this = ISC_LIST_HEAD(*current);
2769 while (this != NULL) {
2770 ISC_LIST_INIT(save);
2771 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
2772 ISC_LIST_UNLINK(this->rdata, rdata, link);
2773 ISC_LIST_APPEND(save, rdata, link);
2775 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
2776 ISC_LIST_UNLINK(save, rdata, link);
2777 INSIST(rdcount < new_len);
2778 new[rdcount] = *rdata;
2779 ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
2782 this = ISC_LIST_NEXT(this, link);
2786 * Copy glue relinking.
2788 this = ISC_LIST_HEAD(*glue);
2789 while (this != NULL) {
2790 ISC_LIST_INIT(save);
2791 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
2792 ISC_LIST_UNLINK(this->rdata, rdata, link);
2793 ISC_LIST_APPEND(save, rdata, link);
2795 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
2796 ISC_LIST_UNLINK(save, rdata, link);
2797 INSIST(rdcount < new_len);
2798 new[rdcount] = *rdata;
2799 ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
2802 this = ISC_LIST_NEXT(this, link);
2804 INSIST(rdcount == old_len || rdcount == 0);
2806 isc_mem_put(mctx, old, old_len * sizeof(*old));
2811 resign_fromlist(dns_rdatalist_t *this, isc_uint32_t resign) {
2813 dns_rdata_rrsig_t sig;
2816 rdata = ISC_LIST_HEAD(this->rdata);
2817 INSIST(rdata != NULL);
2818 (void)dns_rdata_tostruct(rdata, &sig, NULL);
2819 when = sig.timeexpire - resign;
2821 rdata = ISC_LIST_NEXT(rdata, link);
2822 while (rdata != NULL) {
2823 (void)dns_rdata_tostruct(rdata, &sig, NULL);
2824 if (sig.timeexpire - resign < when)
2825 when = sig.timeexpire - resign;
2826 rdata = ISC_LIST_NEXT(rdata, link);
2832 * Convert each element from a rdatalist_t to rdataset then call commit.
2833 * Unlink each element as we go.
2837 commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
2838 rdatalist_head_t *head, dns_name_t *owner,
2839 const char *source, unsigned int line)
2841 dns_rdatalist_t *this;
2842 dns_rdataset_t dataset;
2843 isc_result_t result;
2844 char namebuf[DNS_NAME_FORMATSIZE];
2845 void (*error)(struct dns_rdatacallbacks *, const char *, ...);
2847 this = ISC_LIST_HEAD(*head);
2848 error = callbacks->error;
2851 return (ISC_R_SUCCESS);
2853 dns_rdataset_init(&dataset);
2854 RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset)
2856 dataset.trust = dns_trust_ultimate;
2858 * If this is a secure dynamic zone set the re-signing time.
2860 if (dataset.type == dns_rdatatype_rrsig &&
2861 (lctx->options & DNS_MASTER_RESIGN) != 0) {
2862 dataset.attributes |= DNS_RDATASETATTR_RESIGN;
2863 dns_name_format(owner, namebuf, sizeof(namebuf));
2864 dataset.resign = resign_fromlist(this, lctx->resign);
2866 result = ((*callbacks->add)(callbacks->add_private, owner,
2868 if (result == ISC_R_NOMEMORY) {
2869 (*error)(callbacks, "dns_master_load: %s",
2870 dns_result_totext(result));
2871 } else if (result != ISC_R_SUCCESS) {
2872 dns_name_format(owner, namebuf, sizeof(namebuf));
2873 if (source != NULL) {
2874 (*error)(callbacks, "%s: %s:%lu: %s: %s",
2875 "dns_master_load", source, line,
2876 namebuf, dns_result_totext(result));
2878 (*error)(callbacks, "%s: %s: %s",
2879 "dns_master_load", namebuf,
2880 dns_result_totext(result));
2883 if (MANYERRS(lctx, result))
2884 SETRESULT(lctx, result);
2885 else if (result != ISC_R_SUCCESS)
2887 ISC_LIST_UNLINK(*head, this, link);
2888 this = ISC_LIST_HEAD(*head);
2889 } while (this != NULL);
2890 return (ISC_R_SUCCESS);
2894 * Returns ISC_TRUE if one of the NS rdata's contains 'owner'.
2897 static isc_boolean_t
2898 is_glue(rdatalist_head_t *head, dns_name_t *owner) {
2899 dns_rdatalist_t *this;
2901 isc_region_t region;
2907 this = ISC_LIST_HEAD(*head);
2908 while (this != NULL) {
2909 if (this->type == dns_rdatatype_ns)
2911 this = ISC_LIST_NEXT(this, link);
2916 rdata = ISC_LIST_HEAD(this->rdata);
2917 while (rdata != NULL) {
2918 dns_name_init(&name, NULL);
2919 dns_rdata_toregion(rdata, ®ion);
2920 dns_name_fromregion(&name, ®ion);
2921 if (dns_name_compare(&name, owner) == 0)
2923 rdata = ISC_LIST_NEXT(rdata, link);
2929 load_quantum(isc_task_t *task, isc_event_t *event) {
2930 isc_result_t result;
2931 dns_loadctx_t *lctx;
2933 REQUIRE(event != NULL);
2934 lctx = event->ev_arg;
2935 REQUIRE(DNS_LCTX_VALID(lctx));
2938 result = ISC_R_CANCELED;
2940 result = (lctx->load)(lctx);
2941 if (result == DNS_R_CONTINUE) {
2942 event->ev_arg = lctx;
2943 isc_task_send(task, &event);
2945 (lctx->done)(lctx->done_arg, result);
2946 isc_event_free(&event);
2947 dns_loadctx_detach(&lctx);
2952 task_send(dns_loadctx_t *lctx) {
2955 event = isc_event_allocate(lctx->mctx, NULL,
2956 DNS_EVENT_MASTERQUANTUM,
2957 load_quantum, lctx, sizeof(*event));
2959 return (ISC_R_NOMEMORY);
2960 isc_task_send(lctx->task, &event);
2961 return (ISC_R_SUCCESS);
2965 dns_loadctx_cancel(dns_loadctx_t *lctx) {
2966 REQUIRE(DNS_LCTX_VALID(lctx));
2969 lctx->canceled = ISC_TRUE;
2970 UNLOCK(&lctx->lock);