2 * Copyright (C) 2004-2009, 2011-2016 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 #define CHECKNAMESFAIL(x) (((x) & DNS_MASTER_CHECKNAMESFAIL) != 0)
96 typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
98 typedef struct dns_incctx dns_incctx_t;
101 * Master file load state.
107 dns_masterformat_t format;
109 dns_rdatacallbacks_t *callbacks;
111 dns_loaddonefunc_t done;
115 isc_result_t (*openfile)(dns_loadctx_t *lctx,
116 const char *filename);
117 isc_result_t (*load)(dns_loadctx_t *lctx);
119 /* Members specific to the text format: */
121 isc_boolean_t keep_lex;
122 unsigned int options;
123 isc_boolean_t ttl_known;
124 isc_boolean_t default_ttl_known;
125 isc_boolean_t warn_1035;
126 isc_boolean_t warn_tcr;
127 isc_boolean_t warn_sigexpired;
128 isc_boolean_t seen_include;
130 isc_uint32_t default_ttl;
131 dns_rdataclass_t zclass;
132 dns_fixedname_t fixed_top;
133 dns_name_t *top; /*%< top of zone */
135 /* Members specific to the raw format: */
138 dns_masterrawheader_t header;
140 /* Which fixed buffers we are using? */
141 unsigned int loop_cnt; /*% records per quantum,
143 isc_boolean_t canceled;
147 isc_uint32_t references;
154 dns_incctx_t *parent;
158 dns_fixedname_t fixed[NBUFS]; /* working buffers */
159 unsigned int in_use[NBUFS]; /* covert to bitmap? */
163 isc_boolean_t origin_changed;
165 unsigned int glue_line;
166 unsigned int current_line;
169 #define DNS_LCTX_MAGIC ISC_MAGIC('L','c','t','x')
170 #define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
172 #define DNS_AS_STR(t) ((t).value.as_textregion.base)
175 openfile_text(dns_loadctx_t *lctx, const char *master_file);
178 openfile_raw(dns_loadctx_t *lctx, const char *master_file);
181 load_text(dns_loadctx_t *lctx);
184 load_raw(dns_loadctx_t *lctx);
187 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx);
190 commit(dns_rdatacallbacks_t *, dns_loadctx_t *, rdatalist_head_t *,
191 dns_name_t *, const char *, unsigned int);
194 is_glue(rdatalist_head_t *, dns_name_t *);
196 static dns_rdatalist_t *
197 grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *,
198 rdatalist_head_t *, isc_mem_t *mctx);
201 grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *,
205 load_quantum(isc_task_t *task, isc_event_t *event);
208 task_send(dns_loadctx_t *lctx);
211 loadctx_destroy(dns_loadctx_t *lctx);
213 #define GETTOKENERR(lexer, options, token, eol, err) \
215 result = gettoken(lexer, options, token, eol, callbacks); \
217 case ISC_R_SUCCESS: \
219 case ISC_R_UNEXPECTED: \
220 goto insist_and_cleanup; \
222 if (MANYERRS(lctx, result)) { \
223 SETRESULT(lctx, result); \
225 read_till_eol = ISC_TRUE; \
229 goto log_and_cleanup; \
231 if ((token)->type == isc_tokentype_special) { \
232 result = DNS_R_SYNTAX; \
233 if (MANYERRS(lctx, result)) { \
234 SETRESULT(lctx, result); \
236 read_till_eol = ISC_TRUE; \
239 goto log_and_cleanup; \
242 #define GETTOKEN(lexer, options, token, eol) \
243 GETTOKENERR(lexer, options, token, eol, {} )
247 result = commit(callbacks, lctx, ¤t_list, \
248 ictx->current, source, ictx->current_line); \
249 if (MANYERRS(lctx, result)) { \
250 SETRESULT(lctx, result); \
251 } else if (result != ISC_R_SUCCESS) \
252 goto insist_and_cleanup; \
253 result = commit(callbacks, lctx, &glue_list, \
254 ictx->glue, source, ictx->glue_line); \
255 if (MANYERRS(lctx, result)) { \
256 SETRESULT(lctx, result); \
257 } else if (result != ISC_R_SUCCESS) \
258 goto insist_and_cleanup; \
261 isc_buffer_init(&target, target_mem, target_size); \
262 rdcount_save = rdcount; \
263 rdlcount_save = rdlcount; \
266 #define WARNUNEXPECTEDEOF(lexer) \
268 if (isc_lex_isfile(lexer)) \
269 (*callbacks->warn)(callbacks, \
270 "%s: file does not end with newline", \
276 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE); \
277 if (token.type != isc_tokentype_eol) { \
278 isc_lex_ungettoken(lctx->lex, &token); \
279 result = DNS_R_EXTRATOKEN; \
280 if (MANYERRS(lctx, result)) { \
281 SETRESULT(lctx, result); \
283 read_till_eol = ISC_TRUE; \
285 } else if (result != ISC_R_SUCCESS) \
286 goto log_and_cleanup; \
290 #define MANYERRS(lctx, result) \
291 ((result != ISC_R_SUCCESS) && \
292 (result != ISC_R_IOERROR) && \
293 ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
295 #define SETRESULT(lctx, r) \
297 if ((lctx)->result == ISC_R_SUCCESS) \
298 (lctx)->result = r; \
301 #define LOGITFILE(result, filename) \
302 if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \
303 result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \
304 result == ISC_R_NOPERM) \
305 (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \
306 "dns_master_load", source, line, \
307 filename, dns_result_totext(result)); \
310 #define LOGIT(result) \
311 if (result == ISC_R_NOMEMORY) \
312 (*callbacks->error)(callbacks, "dns_master_load: %s", \
313 dns_result_totext(result)); \
315 (*callbacks->error)(callbacks, "%s: %s:%lu: %s", \
317 source, line, dns_result_totext(result))
320 static unsigned char in_addr_arpa_data[] = "\007IN-ADDR\004ARPA";
321 static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 };
322 static const dns_name_t in_addr_arpa =
325 in_addr_arpa_data, 14, 3,
326 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
327 in_addr_arpa_offsets, NULL,
328 {(void *)-1, (void *)-1},
332 static unsigned char ip6_int_data[] = "\003IP6\003INT";
333 static unsigned char ip6_int_offsets[] = { 0, 4, 8 };
334 static const dns_name_t ip6_int =
338 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
339 ip6_int_offsets, NULL,
340 {(void *)-1, (void *)-1},
344 static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA";
345 static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
346 static const dns_name_t ip6_arpa =
349 ip6_arpa_data, 10, 3,
350 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
351 ip6_arpa_offsets, NULL,
352 {(void *)-1, (void *)-1},
356 static inline isc_result_t
357 gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token,
358 isc_boolean_t eol, dns_rdatacallbacks_t *callbacks)
362 options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE |
364 result = isc_lex_gettoken(lex, options, token);
365 if (result != ISC_R_SUCCESS) {
368 return (ISC_R_NOMEMORY);
370 (*callbacks->error)(callbacks,
371 "dns_master_load: %s:%lu:"
372 " isc_lex_gettoken() failed: %s",
373 isc_lex_getsourcename(lex),
374 isc_lex_getsourceline(lex),
375 isc_result_totext(result));
381 if (token->type == isc_tokentype_eol ||
382 token->type == isc_tokentype_eof) {
383 unsigned long int line;
386 file = isc_lex_getsourcename(lex);
387 line = isc_lex_getsourceline(lex);
388 if (token->type == isc_tokentype_eol) {
393 (*callbacks->error)(callbacks,
394 "dns_master_load: %s:%lu: unexpected end of %s",
396 return (ISC_R_UNEXPECTEDEND);
398 return (ISC_R_SUCCESS);
403 dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
405 REQUIRE(target != NULL && *target == NULL);
406 REQUIRE(DNS_LCTX_VALID(source));
409 INSIST(source->references > 0);
410 source->references++;
411 INSIST(source->references != 0); /* Overflow? */
412 UNLOCK(&source->lock);
418 dns_loadctx_detach(dns_loadctx_t **lctxp) {
420 isc_boolean_t need_destroy = ISC_FALSE;
422 REQUIRE(lctxp != NULL);
424 REQUIRE(DNS_LCTX_VALID(lctx));
427 INSIST(lctx->references > 0);
429 if (lctx->references == 0)
430 need_destroy = ISC_TRUE;
434 loadctx_destroy(lctx);
439 incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
440 dns_incctx_t *parent;
443 parent = ictx->parent;
446 isc_mem_put(mctx, ictx, sizeof(*ictx));
448 if (parent != NULL) {
455 loadctx_destroy(dns_loadctx_t *lctx) {
459 REQUIRE(DNS_LCTX_VALID(lctx));
462 if (lctx->inc != NULL)
463 incctx_destroy(lctx->mctx, lctx->inc);
465 if (lctx->f != NULL) {
466 result = isc_stdio_close(lctx->f);
467 if (result != ISC_R_SUCCESS) {
468 UNEXPECTED_ERROR(__FILE__, __LINE__,
469 "isc_stdio_close() failed: %s",
470 isc_result_totext(result));
474 /* isc_lex_destroy() will close all open streams */
475 if (lctx->lex != NULL && !lctx->keep_lex)
476 isc_lex_destroy(&lctx->lex);
478 if (lctx->task != NULL)
479 isc_task_detach(&lctx->task);
480 DESTROYLOCK(&lctx->lock);
482 isc_mem_attach(lctx->mctx, &mctx);
483 isc_mem_detach(&lctx->mctx);
484 isc_mem_put(mctx, lctx, sizeof(*lctx));
485 isc_mem_detach(&mctx);
489 incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
494 ictx = isc_mem_get(mctx, sizeof(*ictx));
496 return (ISC_R_NOMEMORY);
498 for (i = 0; i < NBUFS; i++) {
499 dns_fixedname_init(&ictx->fixed[i]);
500 ictx->in_use[i] = ISC_FALSE;
503 ictx->origin_in_use = 0;
504 ictx->origin = dns_fixedname_name(&ictx->fixed[ictx->origin_in_use]);
505 ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
506 dns_name_toregion(origin, &r);
507 dns_name_fromregion(ictx->origin, &r);
510 ictx->current = NULL;
511 ictx->glue_in_use = -1;
512 ictx->current_in_use = -1;
514 ictx->drop = ISC_FALSE;
516 ictx->current_line = 0;
517 ictx->origin_changed = ISC_TRUE;
520 return (ISC_R_SUCCESS);
524 loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
525 unsigned int options, isc_uint32_t resign, dns_name_t *top,
526 dns_rdataclass_t zclass, dns_name_t *origin,
527 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
528 dns_loaddonefunc_t done, void *done_arg, isc_lex_t *lex,
529 dns_loadctx_t **lctxp)
534 isc_lexspecials_t specials;
536 REQUIRE(lctxp != NULL && *lctxp == NULL);
537 REQUIRE(callbacks != NULL);
538 REQUIRE(callbacks->add != NULL);
539 REQUIRE(callbacks->error != NULL);
540 REQUIRE(callbacks->warn != NULL);
541 REQUIRE(mctx != NULL);
542 REQUIRE(dns_name_isabsolute(top));
543 REQUIRE(dns_name_isabsolute(origin));
544 REQUIRE((task == NULL && done == NULL) ||
545 (task != NULL && done != NULL));
547 lctx = isc_mem_get(mctx, sizeof(*lctx));
549 return (ISC_R_NOMEMORY);
550 result = isc_mutex_init(&lctx->lock);
551 if (result != ISC_R_SUCCESS) {
552 isc_mem_put(mctx, lctx, sizeof(*lctx));
557 result = incctx_create(mctx, origin, &lctx->inc);
558 if (result != ISC_R_SUCCESS)
561 lctx->format = format;
565 case dns_masterformat_text:
566 lctx->openfile = openfile_text;
567 lctx->load = load_text;
569 case dns_masterformat_raw:
570 lctx->openfile = openfile_raw;
571 lctx->load = load_raw;
577 lctx->keep_lex = ISC_TRUE;
580 result = isc_lex_create(mctx, TOKENSIZ, &lctx->lex);
581 if (result != ISC_R_SUCCESS)
583 lctx->keep_lex = ISC_FALSE;
584 memset(specials, 0, sizeof(specials));
589 isc_lex_setspecials(lctx->lex, specials);
590 isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE);
593 lctx->ttl_known = ISC_TF((options & DNS_MASTER_NOTTL) != 0);
595 lctx->default_ttl_known = lctx->ttl_known;
596 lctx->default_ttl = 0;
597 lctx->warn_1035 = ISC_TRUE; /* XXX Argument? */
598 lctx->warn_tcr = ISC_TRUE; /* XXX Argument? */
599 lctx->warn_sigexpired = ISC_TRUE; /* XXX Argument? */
600 lctx->options = options;
601 lctx->seen_include = ISC_FALSE;
602 lctx->zclass = zclass;
603 lctx->resign = resign;
604 lctx->result = ISC_R_SUCCESS;
605 isc_stdtime_get(&lctx->now);
607 dns_fixedname_init(&lctx->fixed_top);
608 lctx->top = dns_fixedname_name(&lctx->fixed_top);
609 dns_name_toregion(top, &r);
610 dns_name_fromregion(lctx->top, &r);
613 lctx->first = ISC_TRUE;
614 dns_master_initrawheader(&lctx->header);
616 lctx->loop_cnt = (done != NULL) ? 100 : 0;
617 lctx->callbacks = callbacks;
620 isc_task_attach(task, &lctx->task);
622 lctx->done_arg = done_arg;
623 lctx->canceled = ISC_FALSE;
625 isc_mem_attach(mctx, &lctx->mctx);
626 lctx->references = 1; /* Implicit attach. */
627 lctx->magic = DNS_LCTX_MAGIC;
629 return (ISC_R_SUCCESS);
632 incctx_destroy(mctx, lctx->inc);
634 isc_mem_put(mctx, lctx, sizeof(*lctx));
638 static const char *hex = "0123456789abcdef0123456789ABCDEF";
641 * Convert value into a nibble sequence from least significant to most
642 * significant nibble. Zero fill upper most significant nibbles if
643 * required to make the width.
645 * Returns the number of characters that should have been written without
646 * counting the terminating NUL.
649 nibbles(char *numbuf, size_t length, unsigned int width, char mode, int value) {
650 unsigned int count = 0;
653 * This reserve space for the NUL string terminator.
660 char val = hex[(value & 0x0f) + ((mode == 'n') ? 0 : 16)];
671 * If width is non zero then we need to add a label seperator.
672 * If value is non zero then we need to add another label and
673 * that requires a label seperator.
675 if (width > 0 || value != 0) {
685 } while (value != 0 || width > 0);
690 genname(char *name, int it, char *buffer, size_t length) {
691 char fmt[sizeof("%04000000000d")];
699 isc_boolean_t nibblemode;
702 r.length = (unsigned int)length;
704 while (*name != '\0') {
709 return (ISC_R_NOSPACE);
711 isc_textregion_consume(&r, 1);
714 nibblemode = ISC_FALSE;
716 /* Get format specifier. */
718 n = sscanf(name, "{%d,%u,%1[doxXnN]}",
719 &delta, &width, mode);
724 n = snprintf(fmt, sizeof(fmt),
728 if (mode[0] == 'n' || mode[0] == 'N')
729 nibblemode = ISC_TRUE;
730 n = snprintf(fmt, sizeof(fmt),
731 "%%0%u%c", width, mode[0]);
734 return (DNS_R_SYNTAX);
736 if (n >= sizeof(fmt))
737 return (ISC_R_NOSPACE);
738 /* Skip past closing brace. */
739 while (*name != '\0' && *name++ != '}')
743 n = nibbles(numbuf, sizeof(numbuf), width,
744 mode[0], it + delta);
746 n = snprintf(numbuf, sizeof(numbuf), fmt,
748 if (n >= sizeof(numbuf))
749 return (ISC_R_NOSPACE);
751 while (*cp != '\0') {
753 return (ISC_R_NOSPACE);
755 isc_textregion_consume(&r, 1);
757 } else if (*name == '\\') {
759 return (ISC_R_NOSPACE);
761 isc_textregion_consume(&r, 1);
765 return (ISC_R_NOSPACE);
767 isc_textregion_consume(&r, 1);
770 return (ISC_R_NOSPACE);
772 isc_textregion_consume(&r, 1);
776 return (ISC_R_NOSPACE);
778 return (ISC_R_SUCCESS);
782 openfile_text(dns_loadctx_t *lctx, const char *master_file) {
783 return (isc_lex_openfile(lctx->lex, master_file));
787 openfile_raw(dns_loadctx_t *lctx, const char *master_file) {
790 result = isc_stdio_open(master_file, "rb", &lctx->f);
791 if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
792 UNEXPECTED_ERROR(__FILE__, __LINE__,
793 "isc_stdio_open() failed: %s",
794 isc_result_totext(result));
801 generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
802 const char *source, unsigned int line)
804 char *target_mem = NULL;
807 dns_fixedname_t ownerfixed;
809 dns_rdata_t rdata = DNS_RDATA_INIT;
810 dns_rdatacallbacks_t *callbacks;
811 dns_rdatalist_t rdatalist;
812 dns_rdatatype_t type;
813 rdatalist_head_t head;
814 int target_size = MINTSIZ; /* only one rdata at a time */
819 int i, n, start, stop, step = 0;
824 callbacks = lctx->callbacks;
825 dns_fixedname_init(&ownerfixed);
826 owner = dns_fixedname_name(&ownerfixed);
829 target_mem = isc_mem_get(lctx->mctx, target_size);
830 rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_RHS);
831 lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_LHS);
832 if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) {
833 result = ISC_R_NOMEMORY;
836 isc_buffer_init(&target, target_mem, target_size);
838 n = sscanf(range, "%d-%d%1[/]%d", &start, &stop, dummy, &step);
839 if ((n != 2 && n != 4) || (start < 0) || (stop < 0) ||
840 (n == 4 && step < 1) || (stop < start))
842 (*callbacks->error)(callbacks,
843 "%s: %s:%lu: invalid range '%s'",
844 "$GENERATE", source, line, range);
845 result = DNS_R_SYNTAX;
855 r.length = strlen(gtype);
856 result = dns_rdatatype_fromtext(&type, &r);
857 if (result != ISC_R_SUCCESS) {
858 (*callbacks->error)(callbacks,
859 "%s: %s:%lu: unknown RR type '%s'",
860 "$GENERATE", source, line, gtype);
864 for (i = start; i <= stop; i += step) {
865 result = genname(lhs, i, lhsbuf, DNS_MASTER_LHS);
866 if (result != ISC_R_SUCCESS)
868 result = genname(rhs, i, rhsbuf, DNS_MASTER_RHS);
869 if (result != ISC_R_SUCCESS)
872 isc_buffer_init(&buffer, lhsbuf, strlen(lhsbuf));
873 isc_buffer_add(&buffer, strlen(lhsbuf));
874 isc_buffer_setactive(&buffer, strlen(lhsbuf));
875 result = dns_name_fromtext(owner, &buffer, ictx->origin,
877 if (result != ISC_R_SUCCESS)
880 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
881 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
882 (lctx->options & DNS_MASTER_KEY) == 0 &&
883 !dns_name_issubdomain(owner, lctx->top))
885 char namebuf[DNS_NAME_FORMATSIZE];
886 dns_name_format(owner, namebuf, sizeof(namebuf));
888 * Ignore out-of-zone data.
890 (*callbacks->warn)(callbacks,
892 "ignoring out-of-zone data (%s)",
893 source, line, namebuf);
897 isc_buffer_init(&buffer, rhsbuf, strlen(rhsbuf));
898 isc_buffer_add(&buffer, strlen(rhsbuf));
899 isc_buffer_setactive(&buffer, strlen(rhsbuf));
901 result = isc_lex_openbuffer(lctx->lex, &buffer);
902 if (result != ISC_R_SUCCESS)
905 isc_buffer_init(&target, target_mem, target_size);
906 result = dns_rdata_fromtext(&rdata, lctx->zclass, type,
907 lctx->lex, ictx->origin, 0,
908 lctx->mctx, &target, callbacks);
909 RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
910 if (result != ISC_R_SUCCESS)
913 dns_rdatalist_init(&rdatalist);
914 rdatalist.type = type;
915 rdatalist.rdclass = lctx->zclass;
916 rdatalist.ttl = lctx->ttl;
917 ISC_LIST_PREPEND(head, &rdatalist, link);
918 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
919 result = commit(callbacks, lctx, &head, owner, source, line);
920 ISC_LIST_UNLINK(rdatalist.rdata, &rdata, link);
921 if (result != ISC_R_SUCCESS)
923 dns_rdata_reset(&rdata);
925 result = ISC_R_SUCCESS;
929 if (result == ISC_R_NOMEMORY)
930 (*callbacks->error)(callbacks, "$GENERATE: %s",
931 dns_result_totext(result));
933 (*callbacks->error)(callbacks, "$GENERATE: %s:%lu: %s",
934 source, line, dns_result_totext(result));
937 INSIST(result != ISC_R_SUCCESS);
940 if (target_mem != NULL)
941 isc_mem_put(lctx->mctx, target_mem, target_size);
943 isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_LHS);
945 isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_RHS);
950 limit_ttl(dns_rdatacallbacks_t *callbacks, const char *source, unsigned int line,
953 if (*ttlp > 0x7fffffffUL) {
954 (callbacks->warn)(callbacks,
956 "$TTL %lu > MAXTTL, "
966 check_ns(dns_loadctx_t *lctx, isc_token_t *token, const char *source,
970 isc_result_t result = ISC_R_SUCCESS;
971 void (*callback)(struct dns_rdatacallbacks *, const char *, ...);
973 if ((lctx->options & DNS_MASTER_FATALNS) != 0)
974 callback = lctx->callbacks->error;
976 callback = lctx->callbacks->warn;
978 if (token->type == isc_tokentype_string) {
980 struct in6_addr addr6;
982 tmp = isc_mem_strdup(lctx->mctx, DNS_AS_STR(*token));
984 return (ISC_R_NOMEMORY);
986 * Catch both "1.2.3.4" and "1.2.3.4."
988 if (tmp[strlen(tmp) - 1] == '.')
989 tmp[strlen(tmp) - 1] = '\0';
990 if (inet_aton(tmp, &addr) == 1 ||
991 inet_pton(AF_INET6, tmp, &addr6) == 1)
992 result = DNS_R_NSISADDRESS;
994 if (result != ISC_R_SUCCESS)
995 (*callback)(lctx->callbacks, "%s:%lu: NS record '%s' "
996 "appears to be an address",
997 source, line, DNS_AS_STR(*token));
999 isc_mem_free(lctx->mctx, tmp);
1004 check_wildcard(dns_incctx_t *ictx, const char *source, unsigned long line,
1005 dns_rdatacallbacks_t *callbacks)
1009 name = (ictx->glue != NULL) ? ictx->glue : ictx->current;
1010 if (dns_name_internalwildcard(name)) {
1011 char namebuf[DNS_NAME_FORMATSIZE];
1013 dns_name_format(name, namebuf, sizeof(namebuf));
1014 (*callbacks->warn)(callbacks, "%s:%lu: warning: ownername "
1015 "'%s' contains an non-terminal wildcard",
1016 source, line, namebuf);
1021 load_text(dns_loadctx_t *lctx) {
1022 dns_rdataclass_t rdclass;
1023 dns_rdatatype_t type, covers;
1024 isc_uint32_t ttl_offset = 0;
1025 dns_name_t *new_name;
1026 isc_boolean_t current_has_delegation = ISC_FALSE;
1027 isc_boolean_t done = ISC_FALSE;
1028 isc_boolean_t finish_origin = ISC_FALSE;
1029 isc_boolean_t finish_include = ISC_FALSE;
1030 isc_boolean_t read_till_eol = ISC_FALSE;
1031 isc_boolean_t initialws;
1032 char *include_file = NULL;
1034 isc_result_t result = ISC_R_UNEXPECTED;
1035 rdatalist_head_t glue_list;
1036 rdatalist_head_t current_list;
1037 dns_rdatalist_t *this;
1038 dns_rdatalist_t *rdatalist = NULL;
1039 dns_rdatalist_t *new_rdatalist;
1041 int rdlcount_save = 0;
1042 int rdatalist_size = 0;
1043 isc_buffer_t buffer;
1044 isc_buffer_t target;
1045 isc_buffer_t target_ft;
1046 isc_buffer_t target_save;
1047 dns_rdata_t *rdata = NULL;
1048 dns_rdata_t *new_rdata;
1050 int rdcount_save = 0;
1052 unsigned char *target_mem = NULL;
1053 int target_size = TSIZ;
1055 unsigned int loop_cnt = 0;
1057 dns_rdatacallbacks_t *callbacks;
1063 const char *source = "";
1064 unsigned long line = 0;
1065 isc_boolean_t explicit_ttl;
1066 char classname1[DNS_RDATACLASS_FORMATSIZE];
1067 char classname2[DNS_RDATACLASS_FORMATSIZE];
1068 unsigned int options = 0;
1070 REQUIRE(DNS_LCTX_VALID(lctx));
1071 callbacks = lctx->callbacks;
1075 ISC_LIST_INIT(glue_list);
1076 ISC_LIST_INIT(current_list);
1080 * Allocate target_size of buffer space. This is greater than twice
1081 * the maximum individual RR data size.
1083 target_mem = isc_mem_get(mctx, target_size);
1084 if (target_mem == NULL) {
1085 result = ISC_R_NOMEMORY;
1086 goto log_and_cleanup;
1088 isc_buffer_init(&target, target_mem, target_size);
1089 target_save = target;
1091 if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0)
1092 options |= DNS_RDATA_CHECKNAMES;
1093 if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0)
1094 options |= DNS_RDATA_CHECKNAMESFAIL;
1095 if ((lctx->options & DNS_MASTER_CHECKMX) != 0)
1096 options |= DNS_RDATA_CHECKMX;
1097 if ((lctx->options & DNS_MASTER_CHECKMXFAIL) != 0)
1098 options |= DNS_RDATA_CHECKMXFAIL;
1099 source = isc_lex_getsourcename(lctx->lex);
1101 initialws = ISC_FALSE;
1102 line = isc_lex_getsourceline(lctx->lex);
1103 GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS | ISC_LEXOPT_QSTRING,
1105 line = isc_lex_getsourceline(lctx->lex);
1107 if (token.type == isc_tokentype_eof) {
1109 WARNUNEXPECTEDEOF(lctx->lex);
1110 /* Pop the include stack? */
1111 if (ictx->parent != NULL) {
1113 lctx->inc = ictx->parent;
1114 ictx->parent = NULL;
1115 incctx_destroy(lctx->mctx, ictx);
1116 RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
1117 line = isc_lex_getsourceline(lctx->lex);
1119 source = isc_lex_getsourcename(lctx->lex);
1127 if (token.type == isc_tokentype_eol) {
1128 read_till_eol = ISC_FALSE;
1129 continue; /* blank line */
1135 if (token.type == isc_tokentype_initialws) {
1137 * Still working on the same name.
1139 initialws = ISC_TRUE;
1140 } else if (token.type == isc_tokentype_string ||
1141 token.type == isc_tokentype_qstring) {
1146 * "$ORIGIN" and "$INCLUDE" can both take domain names.
1147 * The processing of "$ORIGIN" and "$INCLUDE" extends
1148 * across the normal domain name processing.
1151 if (strcasecmp(DNS_AS_STR(token), "$ORIGIN") == 0) {
1152 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1153 finish_origin = ISC_TRUE;
1154 } else if (strcasecmp(DNS_AS_STR(token),
1156 GETTOKENERR(lctx->lex, 0, &token, ISC_FALSE,
1158 lctx->default_ttl_known = ISC_TRUE;);
1160 dns_ttl_fromtext(&token.value.as_textregion,
1162 if (MANYERRS(lctx, result)) {
1163 SETRESULT(lctx, result);
1165 } else if (result != ISC_R_SUCCESS)
1166 goto insist_and_cleanup;
1167 limit_ttl(callbacks, source, line, &lctx->ttl);
1168 lctx->default_ttl = lctx->ttl;
1169 lctx->default_ttl_known = ISC_TRUE;
1172 } else if (strcasecmp(DNS_AS_STR(token),
1175 if ((lctx->options & DNS_MASTER_NOINCLUDE)
1178 (callbacks->error)(callbacks,
1179 "%s: %s:%lu: $INCLUDE not allowed",
1182 result = DNS_R_REFUSED;
1183 goto insist_and_cleanup;
1185 if (ttl_offset != 0) {
1186 (callbacks->error)(callbacks,
1187 "%s: %s:%lu: $INCLUDE "
1188 "may not be used with $DATE",
1191 result = DNS_R_SYNTAX;
1192 goto insist_and_cleanup;
1194 GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
1196 if (include_file != NULL)
1197 isc_mem_free(mctx, include_file);
1198 include_file = isc_mem_strdup(mctx,
1200 if (include_file == NULL) {
1201 result = ISC_R_NOMEMORY;
1202 goto log_and_cleanup;
1204 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE);
1206 if (token.type == isc_tokentype_eol ||
1207 token.type == isc_tokentype_eof) {
1208 if (token.type == isc_tokentype_eof)
1209 WARNUNEXPECTEDEOF(lctx->lex);
1213 result = pushfile(include_file,
1214 ictx->origin, lctx);
1215 if (MANYERRS(lctx, result)) {
1216 SETRESULT(lctx, result);
1217 LOGITFILE(result, include_file);
1219 } else if (result != ISC_R_SUCCESS) {
1220 LOGITFILE(result, include_file);
1221 goto insist_and_cleanup;
1225 isc_lex_getsourcename(lctx->lex);
1226 line = isc_lex_getsourceline(lctx->lex);
1231 * There is an origin field. Fall through
1232 * to domain name processing code and do
1233 * the actual inclusion later.
1235 finish_include = ISC_TRUE;
1236 } else if (strcasecmp(DNS_AS_STR(token),
1238 isc_int64_t dump_time64;
1239 isc_stdtime_t dump_time, current_time;
1240 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1241 isc_stdtime_get(¤t_time);
1242 result = dns_time64_fromtext(DNS_AS_STR(token),
1244 if (MANYERRS(lctx, result)) {
1245 SETRESULT(lctx, result);
1248 } else if (result != ISC_R_SUCCESS)
1249 goto log_and_cleanup;
1250 dump_time = (isc_stdtime_t)dump_time64;
1251 if (dump_time != dump_time64) {
1252 UNEXPECTED_ERROR(__FILE__, __LINE__,
1253 "%s: %s:%lu: $DATE outside epoch",
1254 "dns_master_load", source, line);
1255 result = ISC_R_UNEXPECTED;
1256 goto insist_and_cleanup;
1258 if (dump_time > current_time) {
1259 UNEXPECTED_ERROR(__FILE__, __LINE__,
1261 "$DATE in future, using current date",
1262 "dns_master_load", source, line);
1263 dump_time = current_time;
1265 ttl_offset = current_time - dump_time;
1268 } else if (strcasecmp(DNS_AS_STR(token),
1269 "$GENERATE") == 0) {
1274 isc_mem_free(mctx, range);
1276 isc_mem_free(mctx, lhs);
1278 isc_mem_free(mctx, gtype);
1280 isc_mem_free(mctx, rhs);
1281 range = lhs = gtype = rhs = NULL;
1283 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1284 range = isc_mem_strdup(mctx,
1286 if (range == NULL) {
1287 result = ISC_R_NOMEMORY;
1288 goto log_and_cleanup;
1291 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1292 lhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1294 result = ISC_R_NOMEMORY;
1295 goto log_and_cleanup;
1298 explicit_ttl = ISC_FALSE;
1300 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1301 if (dns_rdataclass_fromtext(&rdclass,
1302 &token.value.as_textregion)
1304 GETTOKEN(lctx->lex, 0, &token,
1308 if (dns_ttl_fromtext(&token.value.as_textregion,
1311 limit_ttl(callbacks, source, line,
1313 lctx->ttl_known = ISC_TRUE;
1314 explicit_ttl = ISC_TRUE;
1315 GETTOKEN(lctx->lex, 0, &token,
1320 dns_rdataclass_fromtext(&rdclass,
1321 &token.value.as_textregion)
1323 GETTOKEN(lctx->lex, 0, &token,
1326 gtype = isc_mem_strdup(mctx,
1328 if (gtype == NULL) {
1329 result = ISC_R_NOMEMORY;
1330 goto log_and_cleanup;
1333 GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING,
1335 rhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1337 result = ISC_R_NOMEMORY;
1338 goto log_and_cleanup;
1340 if (!lctx->ttl_known &&
1341 !lctx->default_ttl_known) {
1342 (*callbacks->error)(callbacks,
1343 "%s: %s:%lu: no TTL specified",
1344 "dns_master_load", source, line);
1345 result = DNS_R_NOTTL;
1346 if (MANYERRS(lctx, result)) {
1347 SETRESULT(lctx, result);
1349 } else if (result != ISC_R_SUCCESS)
1350 goto insist_and_cleanup;
1351 } else if (!explicit_ttl &&
1352 lctx->default_ttl_known) {
1353 lctx->ttl = lctx->default_ttl;
1356 * If the class specified does not match the
1357 * zone's class print out a error message and
1360 if (rdclass != 0 && rdclass != lctx->zclass) {
1363 result = generate(lctx, range, lhs, gtype, rhs,
1365 if (MANYERRS(lctx, result)) {
1366 SETRESULT(lctx, result);
1367 } else if (result != ISC_R_SUCCESS)
1368 goto insist_and_cleanup;
1371 } else if (strncasecmp(DNS_AS_STR(token),
1373 (callbacks->error)(callbacks,
1375 "unknown $ directive '%s'",
1376 "dns_master_load", source, line,
1378 result = DNS_R_SYNTAX;
1379 if (MANYERRS(lctx, result)) {
1380 SETRESULT(lctx, result);
1381 } else if (result != ISC_R_SUCCESS)
1382 goto insist_and_cleanup;
1386 * Normal processing resumes.
1388 * Find a free name buffer.
1390 for (new_in_use = 0; new_in_use < NBUFS; new_in_use++)
1391 if (!ictx->in_use[new_in_use])
1393 INSIST(new_in_use < NBUFS);
1394 dns_fixedname_init(&ictx->fixed[new_in_use]);
1395 new_name = dns_fixedname_name(&ictx->fixed[new_in_use]);
1396 isc_buffer_init(&buffer, token.value.as_region.base,
1397 token.value.as_region.length);
1398 isc_buffer_add(&buffer, token.value.as_region.length);
1399 isc_buffer_setactive(&buffer,
1400 token.value.as_region.length);
1401 result = dns_name_fromtext(new_name, &buffer,
1402 ictx->origin, 0, NULL);
1403 if (MANYERRS(lctx, result)) {
1404 SETRESULT(lctx, result);
1406 read_till_eol = ISC_TRUE;
1408 } else if (result != ISC_R_SUCCESS)
1409 goto log_and_cleanup;
1412 * Finish $ORIGIN / $INCLUDE processing if required.
1414 if (finish_origin) {
1415 if (ictx->origin_in_use != -1)
1416 ictx->in_use[ictx->origin_in_use] =
1418 ictx->origin_in_use = new_in_use;
1419 ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
1420 ictx->origin = new_name;
1421 ictx->origin_changed = ISC_TRUE;
1422 finish_origin = ISC_FALSE;
1426 if (finish_include) {
1427 finish_include = ISC_FALSE;
1429 result = pushfile(include_file, new_name, lctx);
1430 if (MANYERRS(lctx, result)) {
1431 SETRESULT(lctx, result);
1432 LOGITFILE(result, include_file);
1434 } else if (result != ISC_R_SUCCESS) {
1435 LOGITFILE(result, include_file);
1436 goto insist_and_cleanup;
1439 ictx->origin_changed = ISC_TRUE;
1440 source = isc_lex_getsourcename(lctx->lex);
1441 line = isc_lex_getsourceline(lctx->lex);
1447 * "$" Processing Finished
1451 * If we are processing glue and the new name does
1452 * not match the current glue name, commit the glue
1453 * and pop stacks leaving us in 'normal' processing
1454 * state. Linked lists are undone by commit().
1456 if (ictx->glue != NULL &&
1457 dns_name_compare(ictx->glue, new_name) != 0) {
1458 result = commit(callbacks, lctx, &glue_list,
1461 if (MANYERRS(lctx, result)) {
1462 SETRESULT(lctx, result);
1463 } else if (result != ISC_R_SUCCESS)
1464 goto insist_and_cleanup;
1465 if (ictx->glue_in_use != -1)
1466 ictx->in_use[ictx->glue_in_use] =
1468 ictx->glue_in_use = -1;
1470 rdcount = rdcount_save;
1471 rdlcount = rdlcount_save;
1472 target = target_save;
1476 * If we are in 'normal' processing state and the new
1477 * name does not match the current name, see if the
1478 * new name is for glue and treat it as such,
1479 * otherwise we have a new name so commit what we
1482 if ((ictx->glue == NULL) && (ictx->current == NULL ||
1483 dns_name_compare(ictx->current, new_name) != 0)) {
1484 if (current_has_delegation &&
1485 is_glue(¤t_list, new_name)) {
1486 rdcount_save = rdcount;
1487 rdlcount_save = rdlcount;
1488 target_save = target;
1489 ictx->glue = new_name;
1490 ictx->glue_in_use = new_in_use;
1491 ictx->in_use[ictx->glue_in_use] =
1494 result = commit(callbacks, lctx,
1498 ictx->current_line);
1499 if (MANYERRS(lctx, result)) {
1500 SETRESULT(lctx, result);
1501 } else if (result != ISC_R_SUCCESS)
1502 goto insist_and_cleanup;
1505 if (ictx->current_in_use != -1)
1506 ictx->in_use[ictx->current_in_use] =
1508 ictx->current_in_use = new_in_use;
1509 ictx->in_use[ictx->current_in_use] =
1511 ictx->current = new_name;
1512 current_has_delegation = ISC_FALSE;
1513 isc_buffer_init(&target, target_mem,
1517 * Check for internal wildcards.
1519 if ((lctx->options & DNS_MASTER_CHECKWILDCARD)
1521 check_wildcard(ictx, source, line,
1525 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
1526 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
1527 (lctx->options & DNS_MASTER_KEY) == 0 &&
1528 !dns_name_issubdomain(new_name, lctx->top))
1530 char namebuf[DNS_NAME_FORMATSIZE];
1531 dns_name_format(new_name, namebuf,
1534 * Ignore out-of-zone data.
1536 (*callbacks->warn)(callbacks,
1538 "ignoring out-of-zone data (%s)",
1539 source, line, namebuf);
1540 ictx->drop = ISC_TRUE;
1542 ictx->drop = ISC_FALSE;
1544 UNEXPECTED_ERROR(__FILE__, __LINE__,
1545 "%s:%lu: isc_lex_gettoken() returned "
1546 "unexpected token type (%d)",
1547 source, line, token.type);
1548 result = ISC_R_UNEXPECTED;
1549 if (MANYERRS(lctx, result)) {
1550 SETRESULT(lctx, result);
1553 } else if (result != ISC_R_SUCCESS)
1554 goto insist_and_cleanup;
1558 * Find TTL, class and type. Both TTL and class are optional
1559 * and may occur in any order if they exist. TTL and class
1560 * come before type which must exist.
1562 * [<TTL>] [<class>] <type> <RDATA>
1563 * [<class>] [<TTL>] <type> <RDATA>
1569 GETTOKEN(lctx->lex, 0, &token, initialws);
1572 if (token.type == isc_tokentype_eol) {
1573 read_till_eol = ISC_FALSE;
1574 continue; /* blank line */
1577 if (token.type == isc_tokentype_eof) {
1578 WARNUNEXPECTEDEOF(lctx->lex);
1579 read_till_eol = ISC_FALSE;
1580 isc_lex_ungettoken(lctx->lex, &token);
1584 if (ictx->current == NULL) {
1585 (*callbacks->error)(callbacks,
1586 "%s:%lu: no current owner name",
1588 result = DNS_R_NOOWNER;
1589 if (MANYERRS(lctx, result)) {
1590 SETRESULT(lctx, result);
1591 read_till_eol = ISC_TRUE;
1593 } else if (result != ISC_R_SUCCESS)
1594 goto insist_and_cleanup;
1597 if (ictx->origin_changed) {
1598 char cbuf[DNS_NAME_FORMATSIZE];
1599 char obuf[DNS_NAME_FORMATSIZE];
1600 dns_name_format(ictx->current, cbuf,
1602 dns_name_format(ictx->origin, obuf,
1604 (*callbacks->warn)(callbacks,
1605 "%s:%lu: record with inherited "
1606 "owner (%s) immediately after "
1607 "$ORIGIN (%s)", source, line,
1612 ictx->origin_changed = ISC_FALSE;
1614 if (dns_rdataclass_fromtext(&rdclass,
1615 &token.value.as_textregion)
1617 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1619 explicit_ttl = ISC_FALSE;
1620 if (dns_ttl_fromtext(&token.value.as_textregion, &lctx->ttl)
1622 limit_ttl(callbacks, source, line, &lctx->ttl);
1623 explicit_ttl = ISC_TRUE;
1624 lctx->ttl_known = ISC_TRUE;
1625 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1628 if (token.type != isc_tokentype_string) {
1629 UNEXPECTED_ERROR(__FILE__, __LINE__,
1630 "isc_lex_gettoken() returned unexpected token type");
1631 result = ISC_R_UNEXPECTED;
1632 if (MANYERRS(lctx, result)) {
1633 SETRESULT(lctx, result);
1634 read_till_eol = ISC_TRUE;
1636 } else if (result != ISC_R_SUCCESS)
1637 goto insist_and_cleanup;
1641 dns_rdataclass_fromtext(&rdclass,
1642 &token.value.as_textregion)
1644 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1646 if (token.type != isc_tokentype_string) {
1647 UNEXPECTED_ERROR(__FILE__, __LINE__,
1648 "isc_lex_gettoken() returned unexpected token type");
1649 result = ISC_R_UNEXPECTED;
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;
1658 result = dns_rdatatype_fromtext(&type,
1659 &token.value.as_textregion);
1660 if (result != ISC_R_SUCCESS) {
1661 (*callbacks->warn)(callbacks,
1662 "%s:%lu: unknown RR type '%.*s'",
1664 token.value.as_textregion.length,
1665 token.value.as_textregion.base);
1666 if (MANYERRS(lctx, result)) {
1667 SETRESULT(lctx, result);
1668 read_till_eol = ISC_TRUE;
1670 } else if (result != ISC_R_SUCCESS)
1671 goto insist_and_cleanup;
1675 * If the class specified does not match the zone's class
1676 * print out a error message and exit.
1678 if (rdclass != 0 && rdclass != lctx->zclass) {
1681 dns_rdataclass_format(rdclass, classname1,
1682 sizeof(classname1));
1683 dns_rdataclass_format(lctx->zclass, classname2,
1684 sizeof(classname2));
1685 (*callbacks->error)(callbacks,
1686 "%s:%lu: class '%s' != "
1689 classname1, classname2);
1690 result = DNS_R_BADCLASS;
1691 if (MANYERRS(lctx, result)) {
1692 SETRESULT(lctx, result);
1693 read_till_eol = ISC_TRUE;
1695 } else if (result != ISC_R_SUCCESS)
1696 goto insist_and_cleanup;
1699 if (type == dns_rdatatype_ns && ictx->glue == NULL)
1700 current_has_delegation = ISC_TRUE;
1703 * RFC1123: MD and MF are not allowed to be loaded from
1706 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
1707 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
1708 (type == dns_rdatatype_md || type == dns_rdatatype_mf)) {
1709 char typename[DNS_RDATATYPE_FORMATSIZE];
1711 result = DNS_R_OBSOLETE;
1713 dns_rdatatype_format(type, typename, sizeof(typename));
1714 (*callbacks->error)(callbacks,
1715 "%s:%lu: %s '%s': %s",
1718 dns_result_totext(result));
1719 if (MANYERRS(lctx, result)) {
1720 SETRESULT(lctx, result);
1722 goto insist_and_cleanup;
1726 * Find a rdata structure.
1728 if (rdcount == rdata_size) {
1729 new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
1730 rdata_size, ¤t_list,
1732 if (new_rdata == NULL) {
1733 result = ISC_R_NOMEMORY;
1734 goto log_and_cleanup;
1741 * Peek at the NS record.
1743 if (type == dns_rdatatype_ns &&
1744 lctx->zclass == dns_rdataclass_in &&
1745 (lctx->options & DNS_MASTER_CHECKNS) != 0) {
1747 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1748 result = check_ns(lctx, &token, source, line);
1749 isc_lex_ungettoken(lctx->lex, &token);
1750 if ((lctx->options & DNS_MASTER_FATALNS) != 0) {
1751 if (MANYERRS(lctx, result)) {
1752 SETRESULT(lctx, result);
1753 } else if (result != ISC_R_SUCCESS)
1754 goto insist_and_cleanup;
1761 options &= ~DNS_RDATA_CHECKREVERSE;
1762 if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0) {
1766 name = (ictx->glue != NULL) ? ictx->glue :
1768 ok = dns_rdata_checkowner(name, lctx->zclass, type,
1771 char namebuf[DNS_NAME_FORMATSIZE];
1773 dns_name_format(name, namebuf, sizeof(namebuf));
1774 result = DNS_R_BADOWNERNAME;
1775 desc = dns_result_totext(result);
1776 if (CHECKNAMESFAIL(lctx->options) ||
1777 type == dns_rdatatype_nsec3) {
1778 (*callbacks->error)(callbacks,
1782 if (MANYERRS(lctx, result)) {
1783 SETRESULT(lctx, result);
1784 } else if (result != ISC_R_SUCCESS)
1787 (*callbacks->warn)(callbacks,
1793 if (type == dns_rdatatype_ptr &&
1794 !dns_name_isdnssd(name) &&
1795 (dns_name_issubdomain(name, &in_addr_arpa) ||
1796 dns_name_issubdomain(name, &ip6_arpa) ||
1797 dns_name_issubdomain(name, &ip6_int)))
1798 options |= DNS_RDATA_CHECKREVERSE;
1802 * Read rdata contents.
1804 dns_rdata_init(&rdata[rdcount]);
1806 result = dns_rdata_fromtext(&rdata[rdcount], lctx->zclass,
1807 type, lctx->lex, ictx->origin,
1808 options, lctx->mctx, &target,
1810 if (MANYERRS(lctx, result)) {
1811 SETRESULT(lctx, result);
1813 } else if (result != ISC_R_SUCCESS)
1814 goto insist_and_cleanup;
1821 if (type == dns_rdatatype_soa &&
1822 (lctx->options & DNS_MASTER_ZONE) != 0 &&
1823 dns_name_compare(ictx->current, lctx->top) != 0) {
1824 char namebuf[DNS_NAME_FORMATSIZE];
1825 dns_name_format(ictx->current, namebuf,
1827 (*callbacks->error)(callbacks, "%s:%lu: SOA "
1828 "record not at top of zone (%s)",
1829 source, line, namebuf);
1830 result = DNS_R_NOTZONETOP;
1831 if (MANYERRS(lctx, result)) {
1832 SETRESULT(lctx, result);
1833 read_till_eol = ISC_TRUE;
1836 } else if (result != ISC_R_SUCCESS)
1837 goto insist_and_cleanup;
1841 if (type == dns_rdatatype_rrsig ||
1842 type == dns_rdatatype_sig)
1843 covers = dns_rdata_covers(&rdata[rdcount]);
1847 if (!lctx->ttl_known && !lctx->default_ttl_known) {
1848 if (type == dns_rdatatype_soa) {
1849 (*callbacks->warn)(callbacks,
1850 "%s:%lu: no TTL specified; "
1851 "using SOA MINTTL instead",
1853 lctx->ttl = dns_soa_getminimum(&rdata[rdcount]);
1854 limit_ttl(callbacks, source, line, &lctx->ttl);
1855 lctx->default_ttl = lctx->ttl;
1856 lctx->default_ttl_known = ISC_TRUE;
1857 } else if ((lctx->options & DNS_MASTER_HINT) != 0) {
1859 * Zero TTL's are fine for hints.
1862 lctx->default_ttl = lctx->ttl;
1863 lctx->default_ttl_known = ISC_TRUE;
1865 (*callbacks->warn)(callbacks,
1866 "%s:%lu: no TTL specified; "
1869 result = DNS_R_NOTTL;
1870 if (MANYERRS(lctx, result)) {
1871 SETRESULT(lctx, result);
1874 goto insist_and_cleanup;
1877 } else if (!explicit_ttl && lctx->default_ttl_known) {
1878 lctx->ttl = lctx->default_ttl;
1879 } else if (!explicit_ttl && lctx->warn_1035) {
1880 (*callbacks->warn)(callbacks,
1882 "using RFC1035 TTL semantics",
1884 lctx->warn_1035 = ISC_FALSE;
1887 if (type == dns_rdatatype_rrsig && lctx->warn_sigexpired) {
1888 dns_rdata_rrsig_t sig;
1889 result = dns_rdata_tostruct(&rdata[rdcount], &sig,
1891 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1892 if (isc_serial_lt(sig.timeexpire, lctx->now)) {
1893 (*callbacks->warn)(callbacks,
1895 "signature has expired",
1897 lctx->warn_sigexpired = ISC_FALSE;
1901 if ((type == dns_rdatatype_sig || type == dns_rdatatype_nxt) &&
1902 lctx->warn_tcr && (lctx->options & DNS_MASTER_ZONE) != 0 &&
1903 (lctx->options & DNS_MASTER_SLAVE) == 0) {
1904 (*callbacks->warn)(callbacks, "%s:%lu: old style DNSSEC "
1905 " zone detected", source, line);
1906 lctx->warn_tcr = ISC_FALSE;
1909 if ((lctx->options & DNS_MASTER_AGETTL) != 0) {
1911 * Adjust the TTL for $DATE. If the RR has already
1912 * expired, ignore it.
1914 if (lctx->ttl < ttl_offset)
1916 lctx->ttl -= ttl_offset;
1920 * Find type in rdatalist.
1921 * If it does not exist create new one and prepend to list
1922 * as this will minimise list traversal.
1924 if (ictx->glue != NULL)
1925 this = ISC_LIST_HEAD(glue_list);
1927 this = ISC_LIST_HEAD(current_list);
1929 while (this != NULL) {
1930 if (this->type == type && this->covers == covers)
1932 this = ISC_LIST_NEXT(this, link);
1936 if (rdlcount == rdatalist_size) {
1938 grow_rdatalist(rdatalist_size + RDLSZ,
1944 if (new_rdatalist == NULL) {
1945 result = ISC_R_NOMEMORY;
1946 goto log_and_cleanup;
1948 rdatalist = new_rdatalist;
1949 rdatalist_size += RDLSZ;
1951 this = &rdatalist[rdlcount++];
1952 dns_rdatalist_init(this);
1954 this->covers = covers;
1955 this->rdclass = lctx->zclass;
1956 this->ttl = lctx->ttl;
1957 if (ictx->glue != NULL)
1958 ISC_LIST_INITANDPREPEND(glue_list, this, link);
1960 ISC_LIST_INITANDPREPEND(current_list, this,
1962 } else if (this->ttl != lctx->ttl) {
1963 (*callbacks->warn)(callbacks,
1965 "TTL set to prior TTL (%lu)",
1966 source, line, this->ttl);
1967 lctx->ttl = this->ttl;
1970 ISC_LIST_APPEND(this->rdata, &rdata[rdcount], link);
1971 if (ictx->glue != NULL)
1972 ictx->glue_line = line;
1974 ictx->current_line = line;
1978 * We must have at least 64k as rdlen is 16 bits.
1979 * If we don't commit everything we have so far.
1981 if ((target.length - target.used) < MINTSIZ)
1985 } while (!done && (lctx->loop_cnt == 0 || loop_cnt++ < lctx->loop_cnt));
1988 * Commit what has not yet been committed.
1990 result = commit(callbacks, lctx, ¤t_list, ictx->current,
1991 source, ictx->current_line);
1992 if (MANYERRS(lctx, result)) {
1993 SETRESULT(lctx, result);
1994 } else if (result != ISC_R_SUCCESS)
1995 goto insist_and_cleanup;
1996 result = commit(callbacks, lctx, &glue_list, ictx->glue,
1997 source, ictx->glue_line);
1998 if (MANYERRS(lctx, result)) {
1999 SETRESULT(lctx, result);
2000 } else if (result != ISC_R_SUCCESS)
2001 goto insist_and_cleanup;
2004 INSIST(lctx->done != NULL && lctx->task != NULL);
2005 result = DNS_R_CONTINUE;
2006 } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) {
2007 result = lctx->result;
2008 } else if (result == ISC_R_SUCCESS && lctx->seen_include)
2009 result = DNS_R_SEENINCLUDE;
2016 INSIST(result != ISC_R_SUCCESS);
2019 while ((this = ISC_LIST_HEAD(current_list)) != NULL)
2020 ISC_LIST_UNLINK(current_list, this, link);
2021 while ((this = ISC_LIST_HEAD(glue_list)) != NULL)
2022 ISC_LIST_UNLINK(glue_list, this, link);
2023 if (rdatalist != NULL)
2024 isc_mem_put(mctx, rdatalist,
2025 rdatalist_size * sizeof(*rdatalist));
2027 isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
2028 if (target_mem != NULL)
2029 isc_mem_put(mctx, target_mem, target_size);
2030 if (include_file != NULL)
2031 isc_mem_free(mctx, include_file);
2033 isc_mem_free(mctx, range);
2035 isc_mem_free(mctx, lhs);
2037 isc_mem_free(mctx, gtype);
2039 isc_mem_free(mctx, rhs);
2044 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) {
2045 isc_result_t result;
2047 dns_incctx_t *new = NULL;
2051 REQUIRE(master_file != NULL);
2052 REQUIRE(DNS_LCTX_VALID(lctx));
2055 lctx->seen_include = ISC_TRUE;
2057 result = incctx_create(lctx->mctx, origin, &new);
2058 if (result != ISC_R_SUCCESS)
2062 * Push origin_changed.
2064 new->origin_changed = ictx->origin_changed;
2066 /* Set current domain. */
2067 if (ictx->glue != NULL || ictx->current != NULL) {
2068 for (new_in_use = 0; new_in_use < NBUFS; new_in_use++)
2069 if (!new->in_use[new_in_use])
2071 INSIST(new_in_use < NBUFS);
2072 new->current_in_use = new_in_use;
2074 dns_fixedname_name(&new->fixed[new->current_in_use]);
2075 new->in_use[new->current_in_use] = ISC_TRUE;
2076 dns_name_toregion((ictx->glue != NULL) ?
2077 ictx->glue : ictx->current, &r);
2078 dns_name_fromregion(new->current, &r);
2079 new->drop = ictx->drop;
2082 result = (lctx->openfile)(lctx, master_file);
2083 if (result != ISC_R_SUCCESS)
2087 return (ISC_R_SUCCESS);
2090 incctx_destroy(lctx->mctx, new);
2095 * Fill/check exists buffer with 'len' bytes. Track remaining bytes to be
2096 * read when incrementally filling the buffer.
2098 static inline isc_result_t
2099 read_and_check(isc_boolean_t do_read, isc_buffer_t *buffer,
2100 size_t len, FILE *f, isc_uint32_t *totallen)
2102 isc_result_t result;
2104 REQUIRE(totallen != NULL);
2107 INSIST(isc_buffer_availablelength(buffer) >= len);
2108 result = isc_stdio_read(isc_buffer_used(buffer), 1, len,
2110 if (result != ISC_R_SUCCESS)
2112 isc_buffer_add(buffer, (unsigned int)len);
2113 if (*totallen < len)
2114 return (ISC_R_RANGE);
2115 *totallen -= (isc_uint32_t)len;
2116 } else if (isc_buffer_remaininglength(buffer) < len)
2117 return (ISC_R_RANGE);
2119 return (ISC_R_SUCCESS);
2123 load_raw(dns_loadctx_t *lctx) {
2124 isc_result_t result = ISC_R_SUCCESS;
2125 isc_boolean_t done = ISC_FALSE;
2126 unsigned int loop_cnt = 0;
2127 dns_rdatacallbacks_t *callbacks;
2128 unsigned char namebuf[DNS_NAME_MAXWIRE];
2129 dns_fixedname_t fixed;
2131 rdatalist_head_t head, dummy;
2132 dns_rdatalist_t rdatalist;
2133 isc_mem_t *mctx = lctx->mctx;
2134 dns_rdata_t *rdata = NULL;
2135 unsigned int rdata_size = 0;
2136 int target_size = TSIZ;
2137 isc_buffer_t target, buf;
2138 unsigned char *target_mem = NULL;
2139 dns_masterrawheader_t header;
2140 dns_decompress_t dctx;
2142 callbacks = lctx->callbacks;
2143 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
2145 dns_master_initrawheader(&header);
2148 unsigned char data[sizeof(header)];
2150 sizeof(header.format) + sizeof(header.version);
2153 INSIST(commonlen <= sizeof(header));
2154 isc_buffer_init(&target, data, sizeof(data));
2156 result = isc_stdio_read(data, 1, commonlen, lctx->f, NULL);
2157 if (result != ISC_R_SUCCESS) {
2158 UNEXPECTED_ERROR(__FILE__, __LINE__,
2159 "isc_stdio_read failed: %s",
2160 isc_result_totext(result));
2163 isc_buffer_add(&target, (unsigned int)commonlen);
2164 header.format = isc_buffer_getuint32(&target);
2165 if (header.format != dns_masterformat_raw) {
2166 (*callbacks->error)(callbacks,
2168 "file format mismatch");
2169 return (ISC_R_NOTIMPLEMENTED);
2172 header.version = isc_buffer_getuint32(&target);
2173 switch (header.version) {
2175 remainder = sizeof(header.dumptime);
2177 case DNS_RAWFORMAT_VERSION:
2178 remainder = sizeof(header) - commonlen;
2181 (*callbacks->error)(callbacks,
2183 "unsupported file format version");
2184 return (ISC_R_NOTIMPLEMENTED);
2187 result = isc_stdio_read(data + commonlen, 1, remainder,
2189 if (result != ISC_R_SUCCESS) {
2190 UNEXPECTED_ERROR(__FILE__, __LINE__,
2191 "isc_stdio_read failed: %s",
2192 isc_result_totext(result));
2196 isc_buffer_add(&target, (unsigned int)remainder);
2197 header.dumptime = isc_buffer_getuint32(&target);
2198 if (header.version == DNS_RAWFORMAT_VERSION) {
2199 header.flags = isc_buffer_getuint32(&target);
2200 header.sourceserial = isc_buffer_getuint32(&target);
2201 header.lastxfrin = isc_buffer_getuint32(&target);
2204 lctx->first = ISC_FALSE;
2205 lctx->header = header;
2208 ISC_LIST_INIT(head);
2209 ISC_LIST_INIT(dummy);
2212 * Allocate target_size of buffer space. This is greater than twice
2213 * the maximum individual RR data size.
2215 target_mem = isc_mem_get(mctx, target_size);
2216 if (target_mem == NULL) {
2217 result = ISC_R_NOMEMORY;
2220 isc_buffer_init(&target, target_mem, target_size);
2222 dns_fixedname_init(&fixed);
2223 name = dns_fixedname_name(&fixed);
2226 * In the following loop, we regard any error fatal regardless of
2227 * whether "MANYERRORS" is set in the context option. This is because
2228 * normal errors should already have been checked at creation time.
2229 * Besides, it is very unlikely that we can recover from an error
2230 * in this format, and so trying to continue parsing erroneous data
2231 * does not really make sense.
2234 (lctx->loop_cnt == 0 || loop_cnt < lctx->loop_cnt);
2236 unsigned int i, rdcount;
2237 isc_uint16_t namelen;
2238 isc_uint32_t totallen;
2239 size_t minlen, readlen;
2240 isc_boolean_t sequential_read = ISC_FALSE;
2242 /* Read the data length */
2243 isc_buffer_clear(&target);
2244 INSIST(isc_buffer_availablelength(&target) >=
2246 result = isc_stdio_read(target.base, 1, sizeof(totallen),
2248 if (result == ISC_R_EOF) {
2249 result = ISC_R_SUCCESS;
2253 if (result != ISC_R_SUCCESS)
2255 isc_buffer_add(&target, sizeof(totallen));
2256 totallen = isc_buffer_getuint32(&target);
2259 * Validation: the input data must at least contain the common
2262 minlen = sizeof(totallen) + sizeof(isc_uint16_t) +
2263 sizeof(isc_uint16_t) + sizeof(isc_uint16_t) +
2264 sizeof(isc_uint32_t) + sizeof(isc_uint32_t);
2265 if (totallen < minlen) {
2266 result = ISC_R_RANGE;
2269 totallen -= sizeof(totallen);
2271 isc_buffer_clear(&target);
2272 if (totallen > isc_buffer_availablelength(&target)) {
2274 * The default buffer size should typically be large
2275 * enough to store the entire RRset. We could try to
2276 * allocate enough space if this is not the case, but
2277 * it might cause a hazardous result when "totallen"
2278 * is forged. Thus, we'd rather take an inefficient
2279 * but robust approach in this atypical case: read
2280 * data step by step, and commit partial data when
2281 * necessary. Note that the buffer must be large
2282 * enough to store the "header part", owner name, and
2283 * at least one rdata (however large it is).
2285 sequential_read = ISC_TRUE;
2286 readlen = minlen - sizeof(totallen);
2289 * Typical case. We can read the whole RRset at once
2290 * with the default buffer.
2294 result = isc_stdio_read(target.base, 1, readlen,
2296 if (result != ISC_R_SUCCESS)
2298 isc_buffer_add(&target, (unsigned int)readlen);
2299 totallen -= (isc_uint32_t)readlen;
2301 /* Construct RRset headers */
2302 dns_rdatalist_init(&rdatalist);
2303 rdatalist.rdclass = isc_buffer_getuint16(&target);
2304 if (lctx->zclass != rdatalist.rdclass) {
2305 result = DNS_R_BADCLASS;
2308 rdatalist.type = isc_buffer_getuint16(&target);
2309 rdatalist.covers = isc_buffer_getuint16(&target);
2310 rdatalist.ttl = isc_buffer_getuint32(&target);
2311 rdcount = isc_buffer_getuint32(&target);
2312 if (rdcount == 0 || rdcount > 0xffff) {
2313 result = ISC_R_RANGE;
2316 INSIST(isc_buffer_consumedlength(&target) <= readlen);
2318 /* Owner name: length followed by name */
2319 result = read_and_check(sequential_read, &target,
2320 sizeof(namelen), lctx->f, &totallen);
2321 if (result != ISC_R_SUCCESS)
2323 namelen = isc_buffer_getuint16(&target);
2324 if (namelen > sizeof(namebuf)) {
2325 result = ISC_R_RANGE;
2329 result = read_and_check(sequential_read, &target, namelen,
2330 lctx->f, &totallen);
2331 if (result != ISC_R_SUCCESS)
2334 isc_buffer_setactive(&target, (unsigned int)namelen);
2335 result = dns_name_fromwire(name, &target, &dctx, 0, NULL);
2336 if (result != ISC_R_SUCCESS)
2339 /* Rdata contents. */
2340 if (rdcount > rdata_size) {
2341 dns_rdata_t *new_rdata = NULL;
2343 new_rdata = grow_rdata(rdcount + RDSZ, rdata,
2346 if (new_rdata == NULL) {
2347 result = ISC_R_NOMEMORY;
2350 rdata_size = rdcount + RDSZ;
2355 for (i = 0; i < rdcount; i++) {
2358 dns_rdata_init(&rdata[i]);
2360 if (sequential_read &&
2361 isc_buffer_availablelength(&target) < MINTSIZ) {
2364 INSIST(i > 0); /* detect an infinite loop */
2366 /* Partial Commit. */
2367 ISC_LIST_APPEND(head, &rdatalist, link);
2368 result = commit(callbacks, lctx, &head, name,
2370 for (j = 0; j < i; j++) {
2371 ISC_LIST_UNLINK(rdatalist.rdata,
2373 dns_rdata_reset(&rdata[j]);
2375 if (result != ISC_R_SUCCESS)
2378 /* Rewind the buffer and continue */
2379 isc_buffer_clear(&target);
2387 result = read_and_check(sequential_read, &target,
2388 sizeof(rdlen), lctx->f,
2390 if (result != ISC_R_SUCCESS)
2392 rdlen = isc_buffer_getuint16(&target);
2395 result = read_and_check(sequential_read, &target,
2396 rdlen, lctx->f, &totallen);
2397 if (result != ISC_R_SUCCESS)
2399 isc_buffer_setactive(&target, (unsigned int)rdlen);
2401 * It is safe to have the source active region and
2402 * the target available region be the same if
2403 * decompression is disabled (see dctx above) and we
2404 * are not downcasing names (options == 0).
2406 isc_buffer_init(&buf, isc_buffer_current(&target),
2407 (unsigned int)rdlen);
2408 result = dns_rdata_fromwire(&rdata[i],
2410 rdatalist.type, &target,
2412 if (result != ISC_R_SUCCESS)
2414 ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link);
2418 * Sanity check. Still having remaining space is not
2419 * necessarily critical, but it very likely indicates broken
2420 * or malformed data.
2422 if (isc_buffer_remaininglength(&target) != 0 || totallen != 0) {
2423 result = ISC_R_RANGE;
2427 ISC_LIST_APPEND(head, &rdatalist, link);
2429 /* Commit this RRset. rdatalist will be unlinked. */
2430 result = commit(callbacks, lctx, &head, name, NULL, 0);
2432 for (i = 0; i < rdcount; i++) {
2433 ISC_LIST_UNLINK(rdatalist.rdata, &rdata[i], link);
2434 dns_rdata_reset(&rdata[i]);
2437 if (result != ISC_R_SUCCESS)
2442 INSIST(lctx->done != NULL && lctx->task != NULL);
2443 result = DNS_R_CONTINUE;
2444 } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS)
2445 result = lctx->result;
2447 if (result == ISC_R_SUCCESS && callbacks->rawdata != NULL)
2448 (*callbacks->rawdata)(callbacks->zone, &header);
2452 isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
2453 if (target_mem != NULL)
2454 isc_mem_put(mctx, target_mem, target_size);
2455 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE) {
2456 (*callbacks->error)(callbacks, "dns_master_load: %s",
2457 dns_result_totext(result));
2464 dns_master_loadfile(const char *master_file, dns_name_t *top,
2466 dns_rdataclass_t zclass, unsigned int options,
2467 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2469 return (dns_master_loadfile3(master_file, top, origin, zclass, options,
2470 0, callbacks, mctx, dns_masterformat_text));
2474 dns_master_loadfile2(const char *master_file, dns_name_t *top,
2476 dns_rdataclass_t zclass, unsigned int options,
2477 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
2478 dns_masterformat_t format)
2480 return (dns_master_loadfile3(master_file, top, origin, zclass, options,
2481 0, callbacks, mctx, format));
2485 dns_master_loadfile3(const char *master_file, dns_name_t *top,
2486 dns_name_t *origin, dns_rdataclass_t zclass,
2487 unsigned int options, isc_uint32_t resign,
2488 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
2489 dns_masterformat_t format)
2491 dns_loadctx_t *lctx = NULL;
2492 isc_result_t result;
2494 result = loadctx_create(format, mctx, options, resign, top, zclass,
2495 origin, callbacks, NULL, NULL, NULL, NULL,
2497 if (result != ISC_R_SUCCESS)
2500 result = (lctx->openfile)(lctx, master_file);
2501 if (result != ISC_R_SUCCESS)
2504 result = (lctx->load)(lctx);
2505 INSIST(result != DNS_R_CONTINUE);
2508 dns_loadctx_detach(&lctx);
2513 dns_master_loadfileinc(const char *master_file, dns_name_t *top,
2514 dns_name_t *origin, dns_rdataclass_t zclass,
2515 unsigned int options, dns_rdatacallbacks_t *callbacks,
2516 isc_task_t *task, dns_loaddonefunc_t done,
2517 void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx)
2519 return (dns_master_loadfileinc3(master_file, top, origin, zclass,
2520 options, 0, callbacks, task, done,
2521 done_arg, lctxp, mctx,
2522 dns_masterformat_text));
2526 dns_master_loadfileinc2(const char *master_file, dns_name_t *top,
2527 dns_name_t *origin, dns_rdataclass_t zclass,
2528 unsigned int options, dns_rdatacallbacks_t *callbacks,
2529 isc_task_t *task, dns_loaddonefunc_t done,
2530 void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx,
2531 dns_masterformat_t format)
2533 return (dns_master_loadfileinc3(master_file, top, origin, zclass,
2534 options, 0, callbacks, task, done,
2535 done_arg, lctxp, mctx, format));
2539 dns_master_loadfileinc3(const char *master_file, dns_name_t *top,
2540 dns_name_t *origin, dns_rdataclass_t zclass,
2541 unsigned int options, isc_uint32_t resign,
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,
2545 dns_masterformat_t format)
2547 dns_loadctx_t *lctx = NULL;
2548 isc_result_t result;
2550 REQUIRE(task != NULL);
2551 REQUIRE(done != NULL);
2553 result = loadctx_create(format, mctx, options, resign, top, zclass,
2554 origin, callbacks, task, done, done_arg, NULL,
2556 if (result != ISC_R_SUCCESS)
2559 result = (lctx->openfile)(lctx, master_file);
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);
2570 dns_loadctx_detach(&lctx);
2575 dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
2576 dns_rdataclass_t zclass, unsigned int options,
2577 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2579 isc_result_t result;
2580 dns_loadctx_t *lctx = NULL;
2582 REQUIRE(stream != NULL);
2584 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2585 zclass, origin, callbacks, NULL, NULL, NULL,
2587 if (result != ISC_R_SUCCESS)
2590 result = isc_lex_openstream(lctx->lex, stream);
2591 if (result != ISC_R_SUCCESS)
2594 result = (lctx->load)(lctx);
2595 INSIST(result != DNS_R_CONTINUE);
2599 dns_loadctx_detach(&lctx);
2604 dns_master_loadstreaminc(FILE *stream, dns_name_t *top, dns_name_t *origin,
2605 dns_rdataclass_t zclass, unsigned int options,
2606 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2607 dns_loaddonefunc_t done, void *done_arg,
2608 dns_loadctx_t **lctxp, isc_mem_t *mctx)
2610 isc_result_t result;
2611 dns_loadctx_t *lctx = NULL;
2613 REQUIRE(stream != NULL);
2614 REQUIRE(task != NULL);
2615 REQUIRE(done != NULL);
2617 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2618 zclass, origin, callbacks, task, done,
2619 done_arg, NULL, &lctx);
2620 if (result != ISC_R_SUCCESS)
2623 result = isc_lex_openstream(lctx->lex, stream);
2624 if (result != ISC_R_SUCCESS)
2627 result = task_send(lctx);
2628 if (result == ISC_R_SUCCESS) {
2629 dns_loadctx_attach(lctx, lctxp);
2630 return (DNS_R_CONTINUE);
2635 dns_loadctx_detach(&lctx);
2640 dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top,
2641 dns_name_t *origin, dns_rdataclass_t zclass,
2642 unsigned int options,
2643 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2645 isc_result_t result;
2646 dns_loadctx_t *lctx = NULL;
2648 REQUIRE(buffer != NULL);
2650 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2651 zclass, origin, callbacks, NULL, NULL, NULL,
2653 if (result != ISC_R_SUCCESS)
2656 result = isc_lex_openbuffer(lctx->lex, buffer);
2657 if (result != ISC_R_SUCCESS)
2660 result = (lctx->load)(lctx);
2661 INSIST(result != DNS_R_CONTINUE);
2664 dns_loadctx_detach(&lctx);
2669 dns_master_loadbufferinc(isc_buffer_t *buffer, dns_name_t *top,
2670 dns_name_t *origin, dns_rdataclass_t zclass,
2671 unsigned int options,
2672 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2673 dns_loaddonefunc_t done, void *done_arg,
2674 dns_loadctx_t **lctxp, isc_mem_t *mctx)
2676 isc_result_t result;
2677 dns_loadctx_t *lctx = NULL;
2679 REQUIRE(buffer != NULL);
2680 REQUIRE(task != NULL);
2681 REQUIRE(done != NULL);
2683 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2684 zclass, origin, callbacks, task, done,
2685 done_arg, NULL, &lctx);
2686 if (result != ISC_R_SUCCESS)
2689 result = isc_lex_openbuffer(lctx->lex, buffer);
2690 if (result != ISC_R_SUCCESS)
2693 result = task_send(lctx);
2694 if (result == ISC_R_SUCCESS) {
2695 dns_loadctx_attach(lctx, lctxp);
2696 return (DNS_R_CONTINUE);
2700 dns_loadctx_detach(&lctx);
2705 dns_master_loadlexer(isc_lex_t *lex, dns_name_t *top,
2706 dns_name_t *origin, dns_rdataclass_t zclass,
2707 unsigned int options,
2708 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2710 isc_result_t result;
2711 dns_loadctx_t *lctx = NULL;
2713 REQUIRE(lex != NULL);
2715 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2716 zclass, origin, callbacks, NULL, NULL, NULL,
2718 if (result != ISC_R_SUCCESS)
2721 result = (lctx->load)(lctx);
2722 INSIST(result != DNS_R_CONTINUE);
2724 dns_loadctx_detach(&lctx);
2729 dns_master_loadlexerinc(isc_lex_t *lex, dns_name_t *top,
2730 dns_name_t *origin, dns_rdataclass_t zclass,
2731 unsigned int options,
2732 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2733 dns_loaddonefunc_t done, void *done_arg,
2734 dns_loadctx_t **lctxp, isc_mem_t *mctx)
2736 isc_result_t result;
2737 dns_loadctx_t *lctx = NULL;
2739 REQUIRE(lex != NULL);
2740 REQUIRE(task != NULL);
2741 REQUIRE(done != NULL);
2743 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2744 zclass, origin, callbacks, task, done,
2745 done_arg, lex, &lctx);
2746 if (result != ISC_R_SUCCESS)
2749 result = task_send(lctx);
2750 if (result == ISC_R_SUCCESS) {
2751 dns_loadctx_attach(lctx, lctxp);
2752 return (DNS_R_CONTINUE);
2755 dns_loadctx_detach(&lctx);
2760 * Grow the slab of dns_rdatalist_t structures.
2761 * Re-link glue and current list.
2763 static dns_rdatalist_t *
2764 grow_rdatalist(int new_len, dns_rdatalist_t *old, int old_len,
2765 rdatalist_head_t *current, rdatalist_head_t *glue,
2768 dns_rdatalist_t *new;
2770 ISC_LIST(dns_rdatalist_t) save;
2771 dns_rdatalist_t *this;
2773 new = isc_mem_get(mctx, new_len * sizeof(*new));
2777 ISC_LIST_INIT(save);
2778 while ((this = ISC_LIST_HEAD(*current)) != NULL) {
2779 ISC_LIST_UNLINK(*current, this, link);
2780 ISC_LIST_APPEND(save, this, link);
2782 while ((this = ISC_LIST_HEAD(save)) != NULL) {
2783 ISC_LIST_UNLINK(save, this, link);
2784 INSIST(rdlcount < new_len);
2785 new[rdlcount] = *this;
2786 ISC_LIST_APPEND(*current, &new[rdlcount], link);
2790 ISC_LIST_INIT(save);
2791 while ((this = ISC_LIST_HEAD(*glue)) != NULL) {
2792 ISC_LIST_UNLINK(*glue, this, link);
2793 ISC_LIST_APPEND(save, this, link);
2795 while ((this = ISC_LIST_HEAD(save)) != NULL) {
2796 ISC_LIST_UNLINK(save, this, link);
2797 INSIST(rdlcount < new_len);
2798 new[rdlcount] = *this;
2799 ISC_LIST_APPEND(*glue, &new[rdlcount], link);
2803 INSIST(rdlcount == old_len);
2805 isc_mem_put(mctx, old, old_len * sizeof(*old));
2810 * Grow the slab of rdata structs.
2811 * Re-link the current and glue chains.
2813 static dns_rdata_t *
2814 grow_rdata(int new_len, dns_rdata_t *old, int old_len,
2815 rdatalist_head_t *current, rdatalist_head_t *glue,
2820 ISC_LIST(dns_rdata_t) save;
2821 dns_rdatalist_t *this;
2824 new = isc_mem_get(mctx, new_len * sizeof(*new));
2827 memset(new, 0, new_len * sizeof(*new));
2830 * Copy current relinking.
2832 this = ISC_LIST_HEAD(*current);
2833 while (this != NULL) {
2834 ISC_LIST_INIT(save);
2835 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
2836 ISC_LIST_UNLINK(this->rdata, rdata, link);
2837 ISC_LIST_APPEND(save, rdata, link);
2839 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
2840 ISC_LIST_UNLINK(save, rdata, link);
2841 INSIST(rdcount < new_len);
2842 new[rdcount] = *rdata;
2843 ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
2846 this = ISC_LIST_NEXT(this, link);
2850 * Copy glue relinking.
2852 this = ISC_LIST_HEAD(*glue);
2853 while (this != NULL) {
2854 ISC_LIST_INIT(save);
2855 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
2856 ISC_LIST_UNLINK(this->rdata, rdata, link);
2857 ISC_LIST_APPEND(save, rdata, link);
2859 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
2860 ISC_LIST_UNLINK(save, rdata, link);
2861 INSIST(rdcount < new_len);
2862 new[rdcount] = *rdata;
2863 ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
2866 this = ISC_LIST_NEXT(this, link);
2868 INSIST(rdcount == old_len || rdcount == 0);
2870 isc_mem_put(mctx, old, old_len * sizeof(*old));
2875 resign_fromlist(dns_rdatalist_t *this, dns_loadctx_t *lctx) {
2877 dns_rdata_rrsig_t sig;
2880 rdata = ISC_LIST_HEAD(this->rdata);
2881 INSIST(rdata != NULL);
2882 (void)dns_rdata_tostruct(rdata, &sig, NULL);
2883 if (isc_serial_gt(sig.timesigned, lctx->now))
2886 when = sig.timeexpire - lctx->resign;
2888 rdata = ISC_LIST_NEXT(rdata, link);
2889 while (rdata != NULL) {
2890 (void)dns_rdata_tostruct(rdata, &sig, NULL);
2891 if (isc_serial_gt(sig.timesigned, lctx->now))
2893 else if (sig.timeexpire - lctx->resign < when)
2894 when = sig.timeexpire - lctx->resign;
2895 rdata = ISC_LIST_NEXT(rdata, link);
2901 * Convert each element from a rdatalist_t to rdataset then call commit.
2902 * Unlink each element as we go.
2906 commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
2907 rdatalist_head_t *head, dns_name_t *owner,
2908 const char *source, unsigned int line)
2910 dns_rdatalist_t *this;
2911 dns_rdataset_t dataset;
2912 isc_result_t result;
2913 char namebuf[DNS_NAME_FORMATSIZE];
2914 void (*error)(struct dns_rdatacallbacks *, const char *, ...);
2916 this = ISC_LIST_HEAD(*head);
2917 error = callbacks->error;
2920 return (ISC_R_SUCCESS);
2922 dns_rdataset_init(&dataset);
2923 RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset)
2925 dataset.trust = dns_trust_ultimate;
2927 * If this is a secure dynamic zone set the re-signing time.
2929 if (dataset.type == dns_rdatatype_rrsig &&
2930 (lctx->options & DNS_MASTER_RESIGN) != 0) {
2931 dataset.attributes |= DNS_RDATASETATTR_RESIGN;
2932 dataset.resign = resign_fromlist(this, lctx);
2934 result = ((*callbacks->add)(callbacks->add_private, owner,
2936 if (result == ISC_R_NOMEMORY) {
2937 (*error)(callbacks, "dns_master_load: %s",
2938 dns_result_totext(result));
2939 } else if (result != ISC_R_SUCCESS) {
2940 dns_name_format(owner, namebuf, sizeof(namebuf));
2941 if (source != NULL) {
2942 (*error)(callbacks, "%s: %s:%lu: %s: %s",
2943 "dns_master_load", source, line,
2944 namebuf, dns_result_totext(result));
2946 (*error)(callbacks, "%s: %s: %s",
2947 "dns_master_load", namebuf,
2948 dns_result_totext(result));
2951 if (MANYERRS(lctx, result))
2952 SETRESULT(lctx, result);
2953 else if (result != ISC_R_SUCCESS)
2955 ISC_LIST_UNLINK(*head, this, link);
2956 this = ISC_LIST_HEAD(*head);
2957 } while (this != NULL);
2958 return (ISC_R_SUCCESS);
2962 * Returns ISC_TRUE if one of the NS rdata's contains 'owner'.
2965 static isc_boolean_t
2966 is_glue(rdatalist_head_t *head, dns_name_t *owner) {
2967 dns_rdatalist_t *this;
2969 isc_region_t region;
2975 this = ISC_LIST_HEAD(*head);
2976 while (this != NULL) {
2977 if (this->type == dns_rdatatype_ns)
2979 this = ISC_LIST_NEXT(this, link);
2984 rdata = ISC_LIST_HEAD(this->rdata);
2985 while (rdata != NULL) {
2986 dns_name_init(&name, NULL);
2987 dns_rdata_toregion(rdata, ®ion);
2988 dns_name_fromregion(&name, ®ion);
2989 if (dns_name_compare(&name, owner) == 0)
2991 rdata = ISC_LIST_NEXT(rdata, link);
2997 load_quantum(isc_task_t *task, isc_event_t *event) {
2998 isc_result_t result;
2999 dns_loadctx_t *lctx;
3001 REQUIRE(event != NULL);
3002 lctx = event->ev_arg;
3003 REQUIRE(DNS_LCTX_VALID(lctx));
3006 result = ISC_R_CANCELED;
3008 result = (lctx->load)(lctx);
3009 if (result == DNS_R_CONTINUE) {
3010 event->ev_arg = lctx;
3011 isc_task_send(task, &event);
3013 (lctx->done)(lctx->done_arg, result);
3014 isc_event_free(&event);
3015 dns_loadctx_detach(&lctx);
3020 task_send(dns_loadctx_t *lctx) {
3023 event = isc_event_allocate(lctx->mctx, NULL,
3024 DNS_EVENT_MASTERQUANTUM,
3025 load_quantum, lctx, sizeof(*event));
3027 return (ISC_R_NOMEMORY);
3028 isc_task_send(lctx->task, &event);
3029 return (ISC_R_SUCCESS);
3033 dns_loadctx_cancel(dns_loadctx_t *lctx) {
3034 REQUIRE(DNS_LCTX_VALID(lctx));
3037 lctx->canceled = ISC_TRUE;
3038 UNLOCK(&lctx->lock);
3042 dns_master_initrawheader(dns_masterrawheader_t *header) {
3043 memset(header, 0, sizeof(dns_masterrawheader_t));