2 * Copyright (C) 2004-2009 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.
18 /* $Id: master.c,v 1.171.120.2 2009/01/18 23:47:40 tbox Exp $ */
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 (65535 - 12 - 1 - 2 - 2 - 4 - 2)
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)
88 #define DNS_MASTER_BUFSZ 2048
90 typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
92 typedef struct dns_incctx dns_incctx_t;
95 * Master file load state.
101 dns_masterformat_t format;
103 dns_rdatacallbacks_t *callbacks;
105 dns_loaddonefunc_t done;
109 isc_result_t (*openfile)(dns_loadctx_t *lctx,
110 const char *filename);
111 isc_result_t (*load)(dns_loadctx_t *lctx);
113 /* Members specific to the text format: */
115 isc_boolean_t keep_lex;
116 unsigned int options;
117 isc_boolean_t ttl_known;
118 isc_boolean_t default_ttl_known;
119 isc_boolean_t warn_1035;
120 isc_boolean_t warn_tcr;
121 isc_boolean_t warn_sigexpired;
122 isc_boolean_t seen_include;
124 isc_uint32_t default_ttl;
125 dns_rdataclass_t zclass;
126 dns_fixedname_t fixed_top;
127 dns_name_t *top; /*%< top of zone */
129 /* Members specific to the raw format: */
133 /* Which fixed buffers we are using? */
134 unsigned int loop_cnt; /*% records per quantum,
136 isc_boolean_t canceled;
140 isc_uint32_t references;
146 dns_incctx_t *parent;
150 dns_fixedname_t fixed[NBUFS]; /* working buffers */
151 unsigned int in_use[NBUFS]; /* covert to bitmap? */
156 unsigned int glue_line;
157 unsigned int current_line;
160 #define DNS_LCTX_MAGIC ISC_MAGIC('L','c','t','x')
161 #define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
163 #define DNS_AS_STR(t) ((t).value.as_textregion.base)
166 openfile_text(dns_loadctx_t *lctx, const char *master_file);
169 openfile_raw(dns_loadctx_t *lctx, const char *master_file);
172 load_text(dns_loadctx_t *lctx);
175 load_raw(dns_loadctx_t *lctx);
178 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx);
181 commit(dns_rdatacallbacks_t *, dns_loadctx_t *, rdatalist_head_t *,
182 dns_name_t *, const char *, unsigned int);
185 is_glue(rdatalist_head_t *, dns_name_t *);
187 static dns_rdatalist_t *
188 grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *,
189 rdatalist_head_t *, isc_mem_t *mctx);
192 grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *,
196 load_quantum(isc_task_t *task, isc_event_t *event);
199 task_send(dns_loadctx_t *lctx);
202 loadctx_destroy(dns_loadctx_t *lctx);
204 #define GETTOKEN(lexer, options, token, eol) \
206 result = gettoken(lexer, options, token, eol, callbacks); \
208 case ISC_R_SUCCESS: \
210 case ISC_R_UNEXPECTED: \
211 goto insist_and_cleanup; \
213 if (MANYERRS(lctx, result)) { \
214 SETRESULT(lctx, result); \
216 read_till_eol = ISC_TRUE; \
219 goto log_and_cleanup; \
221 if ((token)->type == isc_tokentype_special) { \
222 result = DNS_R_SYNTAX; \
223 if (MANYERRS(lctx, result)) { \
224 SETRESULT(lctx, result); \
226 read_till_eol = ISC_TRUE; \
229 goto log_and_cleanup; \
235 result = commit(callbacks, lctx, ¤t_list, \
236 ictx->current, source, ictx->current_line); \
237 if (MANYERRS(lctx, result)) { \
238 SETRESULT(lctx, result); \
239 } else if (result != ISC_R_SUCCESS) \
240 goto insist_and_cleanup; \
241 result = commit(callbacks, lctx, &glue_list, \
242 ictx->glue, source, ictx->glue_line); \
243 if (MANYERRS(lctx, result)) { \
244 SETRESULT(lctx, result); \
245 } else if (result != ISC_R_SUCCESS) \
246 goto insist_and_cleanup; \
249 isc_buffer_init(&target, target_mem, target_size); \
250 rdcount_save = rdcount; \
251 rdlcount_save = rdlcount; \
254 #define WARNUNEXPECTEDEOF(lexer) \
256 if (isc_lex_isfile(lexer)) \
257 (*callbacks->warn)(callbacks, \
258 "%s: file does not end with newline", \
264 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE); \
265 if (token.type != isc_tokentype_eol) { \
266 isc_lex_ungettoken(lctx->lex, &token); \
267 result = DNS_R_EXTRATOKEN; \
268 if (MANYERRS(lctx, result)) { \
269 SETRESULT(lctx, result); \
271 read_till_eol = ISC_TRUE; \
273 } else if (result != ISC_R_SUCCESS) \
274 goto log_and_cleanup; \
278 #define MANYERRS(lctx, result) \
279 ((result != ISC_R_SUCCESS) && \
280 (result != ISC_R_IOERROR) && \
281 ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
283 #define SETRESULT(lctx, r) \
285 if ((lctx)->result == ISC_R_SUCCESS) \
286 (lctx)->result = r; \
289 #define LOGITFILE(result, filename) \
290 if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \
291 result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \
292 result == ISC_R_NOPERM) \
293 (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \
294 "dns_master_load", source, line, \
295 filename, dns_result_totext(result)); \
298 #define LOGIT(result) \
299 if (result == ISC_R_NOMEMORY) \
300 (*callbacks->error)(callbacks, "dns_master_load: %s", \
301 dns_result_totext(result)); \
303 (*callbacks->error)(callbacks, "%s: %s:%lu: %s", \
305 source, line, dns_result_totext(result))
308 static unsigned char in_addr_arpa_data[] = "\007IN-ADDR\004ARPA";
309 static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 };
310 static const dns_name_t in_addr_arpa =
313 in_addr_arpa_data, 14, 3,
314 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
315 in_addr_arpa_offsets, NULL,
316 {(void *)-1, (void *)-1},
320 static unsigned char ip6_int_data[] = "\003IP6\003INT";
321 static unsigned char ip6_int_offsets[] = { 0, 4, 8 };
322 static const dns_name_t ip6_int =
326 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
327 ip6_int_offsets, NULL,
328 {(void *)-1, (void *)-1},
332 static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA";
333 static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
334 static const dns_name_t ip6_arpa =
337 ip6_arpa_data, 10, 3,
338 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
339 ip6_arpa_offsets, NULL,
340 {(void *)-1, (void *)-1},
345 static inline isc_result_t
346 gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token,
347 isc_boolean_t eol, dns_rdatacallbacks_t *callbacks)
351 options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE |
353 result = isc_lex_gettoken(lex, options, token);
354 if (result != ISC_R_SUCCESS) {
357 return (ISC_R_NOMEMORY);
359 (*callbacks->error)(callbacks,
360 "dns_master_load: %s:%lu:"
361 " isc_lex_gettoken() failed: %s",
362 isc_lex_getsourcename(lex),
363 isc_lex_getsourceline(lex),
364 isc_result_totext(result));
370 if (token->type == isc_tokentype_eol ||
371 token->type == isc_tokentype_eof) {
372 (*callbacks->error)(callbacks,
373 "dns_master_load: %s:%lu: unexpected end of %s",
374 isc_lex_getsourcename(lex),
375 isc_lex_getsourceline(lex),
379 return (ISC_R_UNEXPECTEDEND);
381 return (ISC_R_SUCCESS);
386 dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
388 REQUIRE(target != NULL && *target == NULL);
389 REQUIRE(DNS_LCTX_VALID(source));
392 INSIST(source->references > 0);
393 source->references++;
394 INSIST(source->references != 0); /* Overflow? */
395 UNLOCK(&source->lock);
401 dns_loadctx_detach(dns_loadctx_t **lctxp) {
403 isc_boolean_t need_destroy = ISC_FALSE;
405 REQUIRE(lctxp != NULL);
407 REQUIRE(DNS_LCTX_VALID(lctx));
410 INSIST(lctx->references > 0);
412 if (lctx->references == 0)
413 need_destroy = ISC_TRUE;
417 loadctx_destroy(lctx);
422 incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
423 dns_incctx_t *parent;
426 parent = ictx->parent;
429 isc_mem_put(mctx, ictx, sizeof(*ictx));
431 if (parent != NULL) {
438 loadctx_destroy(dns_loadctx_t *lctx) {
442 REQUIRE(DNS_LCTX_VALID(lctx));
445 if (lctx->inc != NULL)
446 incctx_destroy(lctx->mctx, lctx->inc);
448 if (lctx->f != NULL) {
449 result = isc_stdio_close(lctx->f);
450 if (result != ISC_R_SUCCESS) {
451 UNEXPECTED_ERROR(__FILE__, __LINE__,
452 "isc_stdio_close() failed: %s",
453 isc_result_totext(result));
457 /* isc_lex_destroy() will close all open streams */
458 if (lctx->lex != NULL && !lctx->keep_lex)
459 isc_lex_destroy(&lctx->lex);
461 if (lctx->task != NULL)
462 isc_task_detach(&lctx->task);
463 DESTROYLOCK(&lctx->lock);
465 isc_mem_attach(lctx->mctx, &mctx);
466 isc_mem_detach(&lctx->mctx);
467 isc_mem_put(mctx, lctx, sizeof(*lctx));
468 isc_mem_detach(&mctx);
472 incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
477 ictx = isc_mem_get(mctx, sizeof(*ictx));
479 return (ISC_R_NOMEMORY);
481 for (i = 0; i < NBUFS; i++) {
482 dns_fixedname_init(&ictx->fixed[i]);
483 ictx->in_use[i] = ISC_FALSE;
486 ictx->origin_in_use = 0;
487 ictx->origin = dns_fixedname_name(&ictx->fixed[ictx->origin_in_use]);
488 ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
489 dns_name_toregion(origin, &r);
490 dns_name_fromregion(ictx->origin, &r);
493 ictx->current = NULL;
494 ictx->glue_in_use = -1;
495 ictx->current_in_use = -1;
497 ictx->drop = ISC_FALSE;
499 ictx->current_line = 0;
502 return (ISC_R_SUCCESS);
506 loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
507 unsigned int options, isc_uint32_t resign, dns_name_t *top,
508 dns_rdataclass_t zclass, dns_name_t *origin,
509 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
510 dns_loaddonefunc_t done, void *done_arg, isc_lex_t *lex,
511 dns_loadctx_t **lctxp)
516 isc_lexspecials_t specials;
518 REQUIRE(lctxp != NULL && *lctxp == NULL);
519 REQUIRE(callbacks != NULL);
520 REQUIRE(callbacks->add != NULL);
521 REQUIRE(callbacks->error != NULL);
522 REQUIRE(callbacks->warn != NULL);
523 REQUIRE(mctx != NULL);
524 REQUIRE(dns_name_isabsolute(top));
525 REQUIRE(dns_name_isabsolute(origin));
526 REQUIRE((task == NULL && done == NULL) ||
527 (task != NULL && done != NULL));
529 lctx = isc_mem_get(mctx, sizeof(*lctx));
531 return (ISC_R_NOMEMORY);
532 result = isc_mutex_init(&lctx->lock);
533 if (result != ISC_R_SUCCESS) {
534 isc_mem_put(mctx, lctx, sizeof(*lctx));
539 result = incctx_create(mctx, origin, &lctx->inc);
540 if (result != ISC_R_SUCCESS)
543 lctx->format = format;
547 case dns_masterformat_text:
548 lctx->openfile = openfile_text;
549 lctx->load = load_text;
551 case dns_masterformat_raw:
552 lctx->openfile = openfile_raw;
553 lctx->load = load_raw;
559 lctx->keep_lex = ISC_TRUE;
562 result = isc_lex_create(mctx, TOKENSIZ, &lctx->lex);
563 if (result != ISC_R_SUCCESS)
565 lctx->keep_lex = ISC_FALSE;
566 memset(specials, 0, sizeof(specials));
570 isc_lex_setspecials(lctx->lex, specials);
571 isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE);
574 lctx->ttl_known = ISC_FALSE;
576 lctx->default_ttl_known = ISC_FALSE;
577 lctx->default_ttl = 0;
578 lctx->warn_1035 = ISC_TRUE; /* XXX Argument? */
579 lctx->warn_tcr = ISC_TRUE; /* XXX Argument? */
580 lctx->warn_sigexpired = ISC_TRUE; /* XXX Argument? */
581 lctx->options = options;
582 lctx->seen_include = ISC_FALSE;
583 lctx->zclass = zclass;
584 lctx->resign = resign;
585 lctx->result = ISC_R_SUCCESS;
587 dns_fixedname_init(&lctx->fixed_top);
588 lctx->top = dns_fixedname_name(&lctx->fixed_top);
589 dns_name_toregion(top, &r);
590 dns_name_fromregion(lctx->top, &r);
593 lctx->first = ISC_TRUE;
595 lctx->loop_cnt = (done != NULL) ? 100 : 0;
596 lctx->callbacks = callbacks;
599 isc_task_attach(task, &lctx->task);
601 lctx->done_arg = done_arg;
602 lctx->canceled = ISC_FALSE;
604 isc_mem_attach(mctx, &lctx->mctx);
605 lctx->references = 1; /* Implicit attach. */
606 lctx->magic = DNS_LCTX_MAGIC;
608 return (ISC_R_SUCCESS);
611 incctx_destroy(mctx, lctx->inc);
613 isc_mem_put(mctx, lctx, sizeof(*lctx));
618 genname(char *name, int it, char *buffer, size_t length) {
619 char fmt[sizeof("%04000000000d")];
631 while (*name != '\0') {
636 return (ISC_R_NOSPACE);
638 isc_textregion_consume(&r, 1);
642 /* Get format specifier. */
644 n = sscanf(name, "{%d,%u,%1[doxX]}",
645 &delta, &width, mode);
650 n = snprintf(fmt, sizeof(fmt),
654 n = snprintf(fmt, sizeof(fmt),
655 "%%0%u%c", width, mode[0]);
658 return (DNS_R_SYNTAX);
660 if (n >= sizeof(fmt))
661 return (ISC_R_NOSPACE);
662 /* Skip past closing brace. */
663 while (*name != '\0' && *name++ != '}')
666 n = snprintf(numbuf, sizeof(numbuf), fmt, it + delta);
667 if (n >= sizeof(numbuf))
668 return (ISC_R_NOSPACE);
670 while (*cp != '\0') {
672 return (ISC_R_NOSPACE);
674 isc_textregion_consume(&r, 1);
676 } else if (*name == '\\') {
678 return (ISC_R_NOSPACE);
680 isc_textregion_consume(&r, 1);
684 return (ISC_R_NOSPACE);
686 isc_textregion_consume(&r, 1);
689 return (ISC_R_NOSPACE);
691 isc_textregion_consume(&r, 1);
695 return (ISC_R_NOSPACE);
697 return (ISC_R_SUCCESS);
701 openfile_text(dns_loadctx_t *lctx, const char *master_file) {
702 return (isc_lex_openfile(lctx->lex, master_file));
706 openfile_raw(dns_loadctx_t *lctx, const char *master_file) {
709 result = isc_stdio_open(master_file, "r", &lctx->f);
710 if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
711 UNEXPECTED_ERROR(__FILE__, __LINE__,
712 "isc_stdio_open() failed: %s",
713 isc_result_totext(result));
720 generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
721 const char *source, unsigned int line)
723 char *target_mem = NULL;
726 dns_fixedname_t ownerfixed;
728 dns_rdata_t rdata = DNS_RDATA_INIT;
729 dns_rdatacallbacks_t *callbacks;
730 dns_rdatalist_t rdatalist;
731 dns_rdatatype_t type;
732 rdatalist_head_t head;
734 int target_size = MINTSIZ; /* only one rdata at a time */
739 unsigned int start, stop, step, i;
743 callbacks = lctx->callbacks;
744 dns_fixedname_init(&ownerfixed);
745 owner = dns_fixedname_name(&ownerfixed);
748 target_mem = isc_mem_get(lctx->mctx, target_size);
749 rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_BUFSZ);
750 lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_BUFSZ);
751 if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) {
752 result = ISC_R_NOMEMORY;
755 isc_buffer_init(&target, target_mem, target_size);
757 n = sscanf(range, "%u-%u/%u", &start, &stop, &step);
758 if (n < 2 || stop < start) {
759 (*callbacks->error)(callbacks,
760 "%s: %s:%lu: invalid range '%s'",
761 "$GENERATE", source, line, range);
762 result = DNS_R_SYNTAX;
772 r.length = strlen(gtype);
773 result = dns_rdatatype_fromtext(&type, &r);
774 if (result != ISC_R_SUCCESS) {
775 (*callbacks->error)(callbacks,
776 "%s: %s:%lu: unknown RR type '%s'",
777 "$GENERATE", source, line, gtype);
782 case dns_rdatatype_ns:
783 case dns_rdatatype_ptr:
784 case dns_rdatatype_cname:
785 case dns_rdatatype_dname:
788 case dns_rdatatype_a:
789 case dns_rdatatype_aaaa:
790 if (lctx->zclass == dns_rdataclass_in ||
791 lctx->zclass == dns_rdataclass_ch ||
792 lctx->zclass == dns_rdataclass_hs)
796 (*callbacks->error)(callbacks,
797 "%s: %s:%lu: unsupported type '%s'",
798 "$GENERATE", source, line, gtype);
799 result = ISC_R_NOTIMPLEMENTED;
803 ISC_LIST_INIT(rdatalist.rdata);
804 ISC_LINK_INIT(&rdatalist, link);
805 for (i = start; i <= stop; i += step) {
806 result = genname(lhs, i, lhsbuf, DNS_MASTER_BUFSZ);
807 if (result != ISC_R_SUCCESS)
809 result = genname(rhs, i, rhsbuf, DNS_MASTER_BUFSZ);
810 if (result != ISC_R_SUCCESS)
813 isc_buffer_init(&buffer, lhsbuf, strlen(lhsbuf));
814 isc_buffer_add(&buffer, strlen(lhsbuf));
815 isc_buffer_setactive(&buffer, strlen(lhsbuf));
816 result = dns_name_fromtext(owner, &buffer, ictx->origin,
818 if (result != ISC_R_SUCCESS)
821 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
822 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
823 !dns_name_issubdomain(owner, lctx->top))
825 char namebuf[DNS_NAME_FORMATSIZE];
826 dns_name_format(owner, namebuf, sizeof(namebuf));
828 * Ignore out-of-zone data.
830 (*callbacks->warn)(callbacks,
832 "ignoring out-of-zone data (%s)",
833 source, line, namebuf);
837 isc_buffer_init(&buffer, rhsbuf, strlen(rhsbuf));
838 isc_buffer_add(&buffer, strlen(rhsbuf));
839 isc_buffer_setactive(&buffer, strlen(rhsbuf));
841 result = isc_lex_openbuffer(lctx->lex, &buffer);
842 if (result != ISC_R_SUCCESS)
845 isc_buffer_init(&target, target_mem, target_size);
846 result = dns_rdata_fromtext(&rdata, lctx->zclass, type,
847 lctx->lex, ictx->origin, 0,
848 lctx->mctx, &target, callbacks);
849 RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
850 if (result != ISC_R_SUCCESS)
853 rdatalist.type = type;
854 rdatalist.covers = 0;
855 rdatalist.rdclass = lctx->zclass;
856 rdatalist.ttl = lctx->ttl;
857 ISC_LIST_PREPEND(head, &rdatalist, link);
858 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
859 result = commit(callbacks, lctx, &head, owner, source, line);
860 ISC_LIST_UNLINK(rdatalist.rdata, &rdata, link);
861 if (result != ISC_R_SUCCESS)
863 dns_rdata_reset(&rdata);
865 result = ISC_R_SUCCESS;
869 if (result == ISC_R_NOMEMORY)
870 (*callbacks->error)(callbacks, "$GENERATE: %s",
871 dns_result_totext(result));
873 (*callbacks->error)(callbacks, "$GENERATE: %s:%lu: %s",
874 source, line, dns_result_totext(result));
877 INSIST(result != ISC_R_SUCCESS);
880 if (target_mem != NULL)
881 isc_mem_put(lctx->mctx, target_mem, target_size);
883 isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_BUFSZ);
885 isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_BUFSZ);
890 limit_ttl(dns_rdatacallbacks_t *callbacks, const char *source, unsigned int line,
893 if (*ttlp > 0x7fffffffUL) {
894 (callbacks->warn)(callbacks,
896 "$TTL %lu > MAXTTL, "
906 check_ns(dns_loadctx_t *lctx, isc_token_t *token, const char *source,
910 isc_result_t result = ISC_R_SUCCESS;
911 void (*callback)(struct dns_rdatacallbacks *, const char *, ...);
913 if ((lctx->options & DNS_MASTER_FATALNS) != 0)
914 callback = lctx->callbacks->error;
916 callback = lctx->callbacks->warn;
918 if (token->type == isc_tokentype_string) {
920 struct in6_addr addr6;
922 tmp = isc_mem_strdup(lctx->mctx, DNS_AS_STR(*token));
924 return (ISC_R_NOMEMORY);
926 * Catch both "1.2.3.4" and "1.2.3.4."
928 if (tmp[strlen(tmp) - 1] == '.')
929 tmp[strlen(tmp) - 1] = '\0';
930 if (inet_aton(tmp, &addr) == 1 ||
931 inet_pton(AF_INET6, tmp, &addr6) == 1)
932 result = DNS_R_NSISADDRESS;
934 if (result != ISC_R_SUCCESS)
935 (*callback)(lctx->callbacks, "%s:%lu: NS record '%s' "
936 "appears to be an address",
937 source, line, DNS_AS_STR(*token));
939 isc_mem_free(lctx->mctx, tmp);
944 check_wildcard(dns_incctx_t *ictx, const char *source, unsigned long line,
945 dns_rdatacallbacks_t *callbacks)
949 name = (ictx->glue != NULL) ? ictx->glue : ictx->current;
950 if (dns_name_internalwildcard(name)) {
951 char namebuf[DNS_NAME_FORMATSIZE];
953 dns_name_format(name, namebuf, sizeof(namebuf));
954 (*callbacks->warn)(callbacks, "%s:%lu: warning: ownername "
955 "'%s' contains an non-terminal wildcard",
956 source, line, namebuf);
961 load_text(dns_loadctx_t *lctx) {
962 dns_rdataclass_t rdclass;
963 dns_rdatatype_t type, covers;
964 isc_uint32_t ttl_offset = 0;
965 dns_name_t *new_name;
966 isc_boolean_t current_has_delegation = ISC_FALSE;
967 isc_boolean_t done = ISC_FALSE;
968 isc_boolean_t finish_origin = ISC_FALSE;
969 isc_boolean_t finish_include = ISC_FALSE;
970 isc_boolean_t read_till_eol = ISC_FALSE;
971 isc_boolean_t initialws;
972 char *include_file = NULL;
974 isc_result_t result = ISC_R_UNEXPECTED;
975 rdatalist_head_t glue_list;
976 rdatalist_head_t current_list;
977 dns_rdatalist_t *this;
978 dns_rdatalist_t *rdatalist = NULL;
979 dns_rdatalist_t *new_rdatalist;
981 int rdlcount_save = 0;
982 int rdatalist_size = 0;
985 isc_buffer_t target_ft;
986 isc_buffer_t target_save;
987 dns_rdata_t *rdata = NULL;
988 dns_rdata_t *new_rdata;
990 int rdcount_save = 0;
992 unsigned char *target_mem = NULL;
993 int target_size = TSIZ;
995 unsigned int loop_cnt = 0;
997 dns_rdatacallbacks_t *callbacks;
1003 const char *source = "";
1004 unsigned long line = 0;
1005 isc_boolean_t explicit_ttl;
1007 char classname1[DNS_RDATACLASS_FORMATSIZE];
1008 char classname2[DNS_RDATACLASS_FORMATSIZE];
1009 unsigned int options = 0;
1011 REQUIRE(DNS_LCTX_VALID(lctx));
1012 callbacks = lctx->callbacks;
1016 ISC_LIST_INIT(glue_list);
1017 ISC_LIST_INIT(current_list);
1019 isc_stdtime_get(&now);
1022 * Allocate target_size of buffer space. This is greater than twice
1023 * the maximum individual RR data size.
1025 target_mem = isc_mem_get(mctx, target_size);
1026 if (target_mem == NULL) {
1027 result = ISC_R_NOMEMORY;
1028 goto log_and_cleanup;
1030 isc_buffer_init(&target, target_mem, target_size);
1031 target_save = target;
1033 if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0)
1034 options |= DNS_RDATA_CHECKNAMES;
1035 if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0)
1036 options |= DNS_RDATA_CHECKNAMESFAIL;
1037 if ((lctx->options & DNS_MASTER_CHECKMX) != 0)
1038 options |= DNS_RDATA_CHECKMX;
1039 if ((lctx->options & DNS_MASTER_CHECKMXFAIL) != 0)
1040 options |= DNS_RDATA_CHECKMXFAIL;
1041 source = isc_lex_getsourcename(lctx->lex);
1043 initialws = ISC_FALSE;
1044 line = isc_lex_getsourceline(lctx->lex);
1045 GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS | ISC_LEXOPT_QSTRING,
1047 line = isc_lex_getsourceline(lctx->lex);
1049 if (token.type == isc_tokentype_eof) {
1051 WARNUNEXPECTEDEOF(lctx->lex);
1052 /* Pop the include stack? */
1053 if (ictx->parent != NULL) {
1055 lctx->inc = ictx->parent;
1056 ictx->parent = NULL;
1057 incctx_destroy(lctx->mctx, ictx);
1058 RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
1059 line = isc_lex_getsourceline(lctx->lex);
1060 source = isc_lex_getsourcename(lctx->lex);
1069 if (token.type == isc_tokentype_eol) {
1070 read_till_eol = ISC_FALSE;
1071 continue; /* blank line */
1077 if (token.type == isc_tokentype_initialws) {
1079 * Still working on the same name.
1081 initialws = ISC_TRUE;
1082 } else if (token.type == isc_tokentype_string ||
1083 token.type == isc_tokentype_qstring) {
1088 * "$ORIGIN" and "$INCLUDE" can both take domain names.
1089 * The processing of "$ORIGIN" and "$INCLUDE" extends
1090 * across the normal domain name processing.
1093 if (strcasecmp(DNS_AS_STR(token), "$ORIGIN") == 0) {
1094 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1095 finish_origin = ISC_TRUE;
1096 } else if (strcasecmp(DNS_AS_STR(token),
1098 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1100 dns_ttl_fromtext(&token.value.as_textregion,
1102 if (MANYERRS(lctx, result)) {
1103 SETRESULT(lctx, result);
1105 } else if (result != ISC_R_SUCCESS)
1106 goto insist_and_cleanup;
1107 limit_ttl(callbacks, source, line, &lctx->ttl);
1108 lctx->default_ttl = lctx->ttl;
1109 lctx->default_ttl_known = ISC_TRUE;
1112 } else if (strcasecmp(DNS_AS_STR(token),
1115 if ((lctx->options & DNS_MASTER_NOINCLUDE)
1118 (callbacks->error)(callbacks,
1119 "%s: %s:%lu: $INCLUDE not allowed",
1122 result = DNS_R_REFUSED;
1123 goto insist_and_cleanup;
1125 if (ttl_offset != 0) {
1126 (callbacks->error)(callbacks,
1127 "%s: %s:%lu: $INCLUDE "
1128 "may not be used with $DATE",
1131 result = DNS_R_SYNTAX;
1132 goto insist_and_cleanup;
1134 GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
1136 if (include_file != NULL)
1137 isc_mem_free(mctx, include_file);
1138 include_file = isc_mem_strdup(mctx,
1140 if (include_file == NULL) {
1141 result = ISC_R_NOMEMORY;
1142 goto log_and_cleanup;
1144 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE);
1146 if (token.type == isc_tokentype_eol ||
1147 token.type == isc_tokentype_eof) {
1148 if (token.type == isc_tokentype_eof)
1149 WARNUNEXPECTEDEOF(lctx->lex);
1150 isc_lex_ungettoken(lctx->lex, &token);
1154 result = pushfile(include_file,
1155 ictx->origin, lctx);
1156 if (MANYERRS(lctx, result)) {
1157 SETRESULT(lctx, result);
1158 LOGITFILE(result, include_file);
1160 } else if (result != ISC_R_SUCCESS) {
1161 LOGITFILE(result, include_file);
1162 goto insist_and_cleanup;
1165 line = isc_lex_getsourceline(lctx->lex);
1167 isc_lex_getsourcename(lctx->lex);
1171 * There is an origin field. Fall through
1172 * to domain name processing code and do
1173 * the actual inclusion later.
1175 finish_include = ISC_TRUE;
1176 } else if (strcasecmp(DNS_AS_STR(token),
1178 isc_int64_t dump_time64;
1179 isc_stdtime_t dump_time, current_time;
1180 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1181 isc_stdtime_get(¤t_time);
1182 result = dns_time64_fromtext(DNS_AS_STR(token),
1184 if (MANYERRS(lctx, result)) {
1185 SETRESULT(lctx, result);
1188 } else if (result != ISC_R_SUCCESS)
1189 goto log_and_cleanup;
1190 dump_time = (isc_stdtime_t)dump_time64;
1191 if (dump_time != dump_time64) {
1192 UNEXPECTED_ERROR(__FILE__, __LINE__,
1193 "%s: %s:%lu: $DATE outside epoch",
1194 "dns_master_load", source, line);
1195 result = ISC_R_UNEXPECTED;
1196 goto insist_and_cleanup;
1198 if (dump_time > current_time) {
1199 UNEXPECTED_ERROR(__FILE__, __LINE__,
1201 "$DATE in future, using current date",
1202 "dns_master_load", source, line);
1203 dump_time = current_time;
1205 ttl_offset = current_time - dump_time;
1208 } else if (strcasecmp(DNS_AS_STR(token),
1209 "$GENERATE") == 0) {
1214 isc_mem_free(mctx, range);
1216 isc_mem_free(mctx, lhs);
1218 isc_mem_free(mctx, gtype);
1220 isc_mem_free(mctx, rhs);
1221 range = lhs = gtype = rhs = NULL;
1223 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1224 range = isc_mem_strdup(mctx,
1226 if (range == NULL) {
1227 result = ISC_R_NOMEMORY;
1228 goto log_and_cleanup;
1231 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1232 lhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1234 result = ISC_R_NOMEMORY;
1235 goto log_and_cleanup;
1238 explicit_ttl = ISC_FALSE;
1240 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1241 if (dns_rdataclass_fromtext(&rdclass,
1242 &token.value.as_textregion)
1244 GETTOKEN(lctx->lex, 0, &token,
1248 if (dns_ttl_fromtext(&token.value.as_textregion,
1251 limit_ttl(callbacks, source, line,
1253 lctx->ttl_known = ISC_TRUE;
1254 explicit_ttl = ISC_TRUE;
1255 GETTOKEN(lctx->lex, 0, &token,
1260 dns_rdataclass_fromtext(&rdclass,
1261 &token.value.as_textregion)
1263 GETTOKEN(lctx->lex, 0, &token,
1266 gtype = isc_mem_strdup(mctx,
1268 if (gtype == NULL) {
1269 result = ISC_R_NOMEMORY;
1270 goto log_and_cleanup;
1273 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1274 rhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1276 result = ISC_R_NOMEMORY;
1277 goto log_and_cleanup;
1279 if (!lctx->ttl_known &&
1280 !lctx->default_ttl_known) {
1281 (*callbacks->error)(callbacks,
1282 "%s: %s:%lu: no TTL specified",
1283 "dns_master_load", source, line);
1284 result = DNS_R_NOTTL;
1285 if (MANYERRS(lctx, result)) {
1286 SETRESULT(lctx, result);
1288 } else if (result != ISC_R_SUCCESS)
1289 goto insist_and_cleanup;
1290 } else if (!explicit_ttl &&
1291 lctx->default_ttl_known) {
1292 lctx->ttl = lctx->default_ttl;
1295 * If the class specified does not match the
1296 * zone's class print out a error message and
1299 if (rdclass != 0 && rdclass != lctx->zclass) {
1302 result = generate(lctx, range, lhs, gtype, rhs,
1304 if (MANYERRS(lctx, result)) {
1305 SETRESULT(lctx, result);
1306 } else if (result != ISC_R_SUCCESS)
1307 goto insist_and_cleanup;
1310 } else if (strncasecmp(DNS_AS_STR(token),
1312 (callbacks->error)(callbacks,
1314 "unknown $ directive '%s'",
1315 "dns_master_load", source, line,
1317 result = DNS_R_SYNTAX;
1318 if (MANYERRS(lctx, result)) {
1319 SETRESULT(lctx, result);
1320 } else if (result != ISC_R_SUCCESS)
1321 goto insist_and_cleanup;
1325 * Normal processing resumes.
1327 * Find a free name buffer.
1329 for (new_in_use = 0; new_in_use < NBUFS; new_in_use++)
1330 if (!ictx->in_use[new_in_use])
1332 INSIST(new_in_use < NBUFS);
1333 dns_fixedname_init(&ictx->fixed[new_in_use]);
1334 new_name = dns_fixedname_name(&ictx->fixed[new_in_use]);
1335 isc_buffer_init(&buffer, token.value.as_region.base,
1336 token.value.as_region.length);
1337 isc_buffer_add(&buffer, token.value.as_region.length);
1338 isc_buffer_setactive(&buffer,
1339 token.value.as_region.length);
1340 result = dns_name_fromtext(new_name, &buffer,
1341 ictx->origin, ISC_FALSE, NULL);
1342 if (MANYERRS(lctx, result)) {
1343 SETRESULT(lctx, result);
1345 read_till_eol = ISC_TRUE;
1347 } else if (result != ISC_R_SUCCESS)
1348 goto log_and_cleanup;
1351 * Finish $ORIGIN / $INCLUDE processing if required.
1353 if (finish_origin) {
1354 if (ictx->origin_in_use != -1)
1355 ictx->in_use[ictx->origin_in_use] =
1357 ictx->origin_in_use = new_in_use;
1358 ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
1359 ictx->origin = new_name;
1360 finish_origin = ISC_FALSE;
1364 if (finish_include) {
1365 finish_include = ISC_FALSE;
1366 result = pushfile(include_file, new_name, lctx);
1367 if (MANYERRS(lctx, result)) {
1368 SETRESULT(lctx, result);
1369 LOGITFILE(result, include_file);
1371 } else if (result != ISC_R_SUCCESS) {
1372 LOGITFILE(result, include_file);
1373 goto insist_and_cleanup;
1376 line = isc_lex_getsourceline(lctx->lex);
1377 source = isc_lex_getsourcename(lctx->lex);
1382 * "$" Processing Finished
1386 * If we are processing glue and the new name does
1387 * not match the current glue name, commit the glue
1388 * and pop stacks leaving us in 'normal' processing
1389 * state. Linked lists are undone by commit().
1391 if (ictx->glue != NULL &&
1392 dns_name_compare(ictx->glue, new_name) != 0) {
1393 result = commit(callbacks, lctx, &glue_list,
1396 if (MANYERRS(lctx, result)) {
1397 SETRESULT(lctx, result);
1398 } else if (result != ISC_R_SUCCESS)
1399 goto insist_and_cleanup;
1400 if (ictx->glue_in_use != -1)
1401 ictx->in_use[ictx->glue_in_use] =
1403 ictx->glue_in_use = -1;
1405 rdcount = rdcount_save;
1406 rdlcount = rdlcount_save;
1407 target = target_save;
1411 * If we are in 'normal' processing state and the new
1412 * name does not match the current name, see if the
1413 * new name is for glue and treat it as such,
1414 * otherwise we have a new name so commit what we
1417 if ((ictx->glue == NULL) && (ictx->current == NULL ||
1418 dns_name_compare(ictx->current, new_name) != 0)) {
1419 if (current_has_delegation &&
1420 is_glue(¤t_list, new_name)) {
1421 rdcount_save = rdcount;
1422 rdlcount_save = rdlcount;
1423 target_save = target;
1424 ictx->glue = new_name;
1425 ictx->glue_in_use = new_in_use;
1426 ictx->in_use[ictx->glue_in_use] =
1429 result = commit(callbacks, lctx,
1433 ictx->current_line);
1434 if (MANYERRS(lctx, result)) {
1435 SETRESULT(lctx, result);
1436 } else if (result != ISC_R_SUCCESS)
1437 goto insist_and_cleanup;
1440 if (ictx->current_in_use != -1)
1441 ictx->in_use[ictx->current_in_use] =
1443 ictx->current_in_use = new_in_use;
1444 ictx->in_use[ictx->current_in_use] =
1446 ictx->current = new_name;
1447 current_has_delegation = ISC_FALSE;
1448 isc_buffer_init(&target, target_mem,
1452 * Check for internal wildcards.
1454 if ((lctx->options & DNS_MASTER_CHECKWILDCARD)
1456 check_wildcard(ictx, source, line,
1460 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
1461 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
1462 !dns_name_issubdomain(new_name, lctx->top))
1464 char namebuf[DNS_NAME_FORMATSIZE];
1465 dns_name_format(new_name, namebuf,
1468 * Ignore out-of-zone data.
1470 (*callbacks->warn)(callbacks,
1472 "ignoring out-of-zone data (%s)",
1473 source, line, namebuf);
1474 ictx->drop = ISC_TRUE;
1476 ictx->drop = ISC_FALSE;
1478 UNEXPECTED_ERROR(__FILE__, __LINE__,
1479 "%s:%lu: isc_lex_gettoken() returned "
1480 "unexpected token type (%d)",
1481 source, line, token.type);
1482 result = ISC_R_UNEXPECTED;
1483 if (MANYERRS(lctx, result)) {
1484 SETRESULT(lctx, result);
1487 } else if (result != ISC_R_SUCCESS)
1488 goto insist_and_cleanup;
1492 * Find TTL, class and type. Both TTL and class are optional
1493 * and may occur in any order if they exist. TTL and class
1494 * come before type which must exist.
1496 * [<TTL>] [<class>] <type> <RDATA>
1497 * [<class>] [<TTL>] <type> <RDATA>
1503 GETTOKEN(lctx->lex, 0, &token, initialws);
1506 if (token.type == isc_tokentype_eol) {
1507 read_till_eol = ISC_FALSE;
1508 continue; /* blank line */
1511 if (token.type == isc_tokentype_eof) {
1512 WARNUNEXPECTEDEOF(lctx->lex);
1513 read_till_eol = ISC_FALSE;
1514 isc_lex_ungettoken(lctx->lex, &token);
1518 if (ictx->current == NULL) {
1519 (*callbacks->error)(callbacks,
1520 "%s:%lu: no current owner name",
1522 result = DNS_R_NOOWNER;
1523 if (MANYERRS(lctx, result)) {
1524 SETRESULT(lctx, result);
1525 read_till_eol = ISC_TRUE;
1527 } else if (result != ISC_R_SUCCESS)
1528 goto insist_and_cleanup;
1532 if (dns_rdataclass_fromtext(&rdclass,
1533 &token.value.as_textregion)
1535 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1537 explicit_ttl = ISC_FALSE;
1538 if (dns_ttl_fromtext(&token.value.as_textregion, &lctx->ttl)
1540 limit_ttl(callbacks, source, line, &lctx->ttl);
1541 explicit_ttl = ISC_TRUE;
1542 lctx->ttl_known = ISC_TRUE;
1543 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1546 if (token.type != isc_tokentype_string) {
1547 UNEXPECTED_ERROR(__FILE__, __LINE__,
1548 "isc_lex_gettoken() returned unexpected token type");
1549 result = ISC_R_UNEXPECTED;
1550 if (MANYERRS(lctx, result)) {
1551 SETRESULT(lctx, result);
1552 read_till_eol = ISC_TRUE;
1554 } else if (result != ISC_R_SUCCESS)
1555 goto insist_and_cleanup;
1559 dns_rdataclass_fromtext(&rdclass,
1560 &token.value.as_textregion)
1562 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1564 if (token.type != isc_tokentype_string) {
1565 UNEXPECTED_ERROR(__FILE__, __LINE__,
1566 "isc_lex_gettoken() returned unexpected token type");
1567 result = ISC_R_UNEXPECTED;
1568 if (MANYERRS(lctx, result)) {
1569 SETRESULT(lctx, result);
1570 read_till_eol = ISC_TRUE;
1572 } else if (result != ISC_R_SUCCESS)
1573 goto insist_and_cleanup;
1576 result = dns_rdatatype_fromtext(&type,
1577 &token.value.as_textregion);
1578 if (result != ISC_R_SUCCESS) {
1579 (*callbacks->warn)(callbacks,
1580 "%s:%lu: unknown RR type '%.*s'",
1582 token.value.as_textregion.length,
1583 token.value.as_textregion.base);
1584 if (MANYERRS(lctx, result)) {
1585 SETRESULT(lctx, result);
1586 read_till_eol = ISC_TRUE;
1588 } else if (result != ISC_R_SUCCESS)
1589 goto insist_and_cleanup;
1593 * If the class specified does not match the zone's class
1594 * print out a error message and exit.
1596 if (rdclass != 0 && rdclass != lctx->zclass) {
1599 dns_rdataclass_format(rdclass, classname1,
1600 sizeof(classname1));
1601 dns_rdataclass_format(lctx->zclass, classname2,
1602 sizeof(classname2));
1603 (*callbacks->error)(callbacks,
1604 "%s:%lu: class '%s' != "
1607 classname1, classname2);
1608 result = DNS_R_BADCLASS;
1609 if (MANYERRS(lctx, result)) {
1610 SETRESULT(lctx, result);
1611 read_till_eol = ISC_TRUE;
1613 } else if (result != ISC_R_SUCCESS)
1614 goto insist_and_cleanup;
1617 if (type == dns_rdatatype_ns && ictx->glue == NULL)
1618 current_has_delegation = ISC_TRUE;
1621 * RFC1123: MD and MF are not allowed to be loaded from
1624 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
1625 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
1626 (type == dns_rdatatype_md || type == dns_rdatatype_mf)) {
1627 char typename[DNS_RDATATYPE_FORMATSIZE];
1629 result = DNS_R_OBSOLETE;
1631 dns_rdatatype_format(type, typename, sizeof(typename));
1632 (*callbacks->error)(callbacks,
1633 "%s:%lu: %s '%s': %s",
1636 dns_result_totext(result));
1637 if (MANYERRS(lctx, result)) {
1638 SETRESULT(lctx, result);
1640 goto insist_and_cleanup;
1644 * Find a rdata structure.
1646 if (rdcount == rdata_size) {
1647 new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
1648 rdata_size, ¤t_list,
1650 if (new_rdata == NULL) {
1651 result = ISC_R_NOMEMORY;
1652 goto log_and_cleanup;
1659 * Peek at the NS record.
1661 if (type == dns_rdatatype_ns &&
1662 lctx->zclass == dns_rdataclass_in &&
1663 (lctx->options & DNS_MASTER_CHECKNS) != 0) {
1665 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1666 result = check_ns(lctx, &token, source, line);
1667 isc_lex_ungettoken(lctx->lex, &token);
1668 if ((lctx->options & DNS_MASTER_FATALNS) != 0) {
1669 if (MANYERRS(lctx, result)) {
1670 SETRESULT(lctx, result);
1671 } else if (result != ISC_R_SUCCESS)
1672 goto insist_and_cleanup;
1679 options &= ~DNS_RDATA_CHECKREVERSE;
1680 if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0) {
1684 name = (ictx->glue != NULL) ? ictx->glue :
1686 ok = dns_rdata_checkowner(name, lctx->zclass, type,
1689 char namebuf[DNS_NAME_FORMATSIZE];
1691 dns_name_format(name, namebuf, sizeof(namebuf));
1692 result = DNS_R_BADOWNERNAME;
1693 desc = dns_result_totext(result);
1694 if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0) {
1695 (*callbacks->error)(callbacks,
1699 if (MANYERRS(lctx, result)) {
1700 SETRESULT(lctx, result);
1701 } else if (result != ISC_R_SUCCESS)
1704 (*callbacks->warn)(callbacks,
1710 if (type == dns_rdatatype_ptr &&
1711 (dns_name_issubdomain(name, &in_addr_arpa) ||
1712 dns_name_issubdomain(name, &ip6_arpa) ||
1713 dns_name_issubdomain(name, &ip6_int)))
1714 options |= DNS_RDATA_CHECKREVERSE;
1718 * Read rdata contents.
1720 dns_rdata_init(&rdata[rdcount]);
1722 result = dns_rdata_fromtext(&rdata[rdcount], lctx->zclass,
1723 type, lctx->lex, ictx->origin,
1724 options, lctx->mctx, &target,
1726 if (MANYERRS(lctx, result)) {
1727 SETRESULT(lctx, result);
1729 } else if (result != ISC_R_SUCCESS)
1730 goto insist_and_cleanup;
1737 if (type == dns_rdatatype_soa &&
1738 (lctx->options & DNS_MASTER_ZONE) != 0 &&
1739 dns_name_compare(ictx->current, lctx->top) != 0) {
1740 char namebuf[DNS_NAME_FORMATSIZE];
1741 dns_name_format(ictx->current, namebuf,
1743 (*callbacks->error)(callbacks, "%s:%lu: SOA "
1744 "record not at top of zone (%s)",
1745 source, line, namebuf);
1746 result = DNS_R_NOTZONETOP;
1747 if (MANYERRS(lctx, result)) {
1748 SETRESULT(lctx, result);
1749 read_till_eol = ISC_TRUE;
1752 } else if (result != ISC_R_SUCCESS)
1753 goto insist_and_cleanup;
1757 if (type == dns_rdatatype_rrsig ||
1758 type == dns_rdatatype_sig)
1759 covers = dns_rdata_covers(&rdata[rdcount]);
1763 if (!lctx->ttl_known && !lctx->default_ttl_known) {
1764 if (type == dns_rdatatype_soa) {
1765 (*callbacks->warn)(callbacks,
1766 "%s:%lu: no TTL specified; "
1767 "using SOA MINTTL instead",
1769 lctx->ttl = dns_soa_getminimum(&rdata[rdcount]);
1770 limit_ttl(callbacks, source, line, &lctx->ttl);
1771 lctx->default_ttl = lctx->ttl;
1772 lctx->default_ttl_known = ISC_TRUE;
1773 } else if ((lctx->options & DNS_MASTER_HINT) != 0) {
1775 * Zero TTL's are fine for hints.
1778 lctx->default_ttl = lctx->ttl;
1779 lctx->default_ttl_known = ISC_TRUE;
1781 (*callbacks->warn)(callbacks,
1782 "%s:%lu: no TTL specified; "
1785 result = DNS_R_NOTTL;
1786 if (MANYERRS(lctx, result)) {
1787 SETRESULT(lctx, result);
1790 goto insist_and_cleanup;
1793 } else if (!explicit_ttl && lctx->default_ttl_known) {
1794 lctx->ttl = lctx->default_ttl;
1795 } else if (!explicit_ttl && lctx->warn_1035) {
1796 (*callbacks->warn)(callbacks,
1798 "using RFC1035 TTL semantics",
1800 lctx->warn_1035 = ISC_FALSE;
1803 if (type == dns_rdatatype_rrsig && lctx->warn_sigexpired) {
1804 dns_rdata_rrsig_t sig;
1805 result = dns_rdata_tostruct(&rdata[rdcount], &sig,
1807 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1808 if (isc_serial_lt(sig.timeexpire, now)) {
1809 (*callbacks->warn)(callbacks,
1811 "signature has expired",
1813 lctx->warn_sigexpired = ISC_FALSE;
1817 if ((type == dns_rdatatype_sig || type == dns_rdatatype_nxt) &&
1818 lctx->warn_tcr && (lctx->options & DNS_MASTER_ZONE) != 0 &&
1819 (lctx->options & DNS_MASTER_SLAVE) == 0) {
1820 (*callbacks->warn)(callbacks, "%s:%lu: old style DNSSEC "
1821 " zone detected", source, line);
1822 lctx->warn_tcr = ISC_FALSE;
1825 if ((lctx->options & DNS_MASTER_AGETTL) != 0) {
1827 * Adjust the TTL for $DATE. If the RR has already
1828 * expired, ignore it.
1830 if (lctx->ttl < ttl_offset)
1832 lctx->ttl -= ttl_offset;
1836 * Find type in rdatalist.
1837 * If it does not exist create new one and prepend to list
1838 * as this will minimise list traversal.
1840 if (ictx->glue != NULL)
1841 this = ISC_LIST_HEAD(glue_list);
1843 this = ISC_LIST_HEAD(current_list);
1845 while (this != NULL) {
1846 if (this->type == type && this->covers == covers)
1848 this = ISC_LIST_NEXT(this, link);
1852 if (rdlcount == rdatalist_size) {
1854 grow_rdatalist(rdatalist_size + RDLSZ,
1860 if (new_rdatalist == NULL) {
1861 result = ISC_R_NOMEMORY;
1862 goto log_and_cleanup;
1864 rdatalist = new_rdatalist;
1865 rdatalist_size += RDLSZ;
1867 this = &rdatalist[rdlcount++];
1869 this->covers = covers;
1870 this->rdclass = lctx->zclass;
1871 this->ttl = lctx->ttl;
1872 ISC_LIST_INIT(this->rdata);
1873 if (ictx->glue != NULL)
1874 ISC_LIST_INITANDPREPEND(glue_list, this, link);
1876 ISC_LIST_INITANDPREPEND(current_list, this,
1878 } else if (this->ttl != lctx->ttl) {
1879 (*callbacks->warn)(callbacks,
1881 "TTL set to prior TTL (%lu)",
1882 source, line, this->ttl);
1883 lctx->ttl = this->ttl;
1886 ISC_LIST_APPEND(this->rdata, &rdata[rdcount], link);
1887 if (ictx->glue != NULL)
1888 ictx->glue_line = line;
1890 ictx->current_line = line;
1894 * We must have at least 64k as rdlen is 16 bits.
1895 * If we don't commit everything we have so far.
1897 if ((target.length - target.used) < MINTSIZ)
1901 } while (!done && (lctx->loop_cnt == 0 || loop_cnt++ < lctx->loop_cnt));
1904 * Commit what has not yet been committed.
1906 result = commit(callbacks, lctx, ¤t_list, ictx->current,
1907 source, ictx->current_line);
1908 if (MANYERRS(lctx, result)) {
1909 SETRESULT(lctx, result);
1910 } else if (result != ISC_R_SUCCESS)
1911 goto insist_and_cleanup;
1912 result = commit(callbacks, lctx, &glue_list, ictx->glue,
1913 source, ictx->glue_line);
1914 if (MANYERRS(lctx, result)) {
1915 SETRESULT(lctx, result);
1916 } else if (result != ISC_R_SUCCESS)
1917 goto insist_and_cleanup;
1920 INSIST(lctx->done != NULL && lctx->task != NULL);
1921 result = DNS_R_CONTINUE;
1922 } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) {
1923 result = lctx->result;
1924 } else if (result == ISC_R_SUCCESS && lctx->seen_include)
1925 result = DNS_R_SEENINCLUDE;
1932 INSIST(result != ISC_R_SUCCESS);
1935 while ((this = ISC_LIST_HEAD(current_list)) != NULL)
1936 ISC_LIST_UNLINK(current_list, this, link);
1937 while ((this = ISC_LIST_HEAD(glue_list)) != NULL)
1938 ISC_LIST_UNLINK(glue_list, this, link);
1939 if (rdatalist != NULL)
1940 isc_mem_put(mctx, rdatalist,
1941 rdatalist_size * sizeof(*rdatalist));
1943 isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
1944 if (target_mem != NULL)
1945 isc_mem_put(mctx, target_mem, target_size);
1946 if (include_file != NULL)
1947 isc_mem_free(mctx, include_file);
1949 isc_mem_free(mctx, range);
1951 isc_mem_free(mctx, lhs);
1953 isc_mem_free(mctx, gtype);
1955 isc_mem_free(mctx, rhs);
1960 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) {
1961 isc_result_t result;
1963 dns_incctx_t *new = NULL;
1967 REQUIRE(master_file != NULL);
1968 REQUIRE(DNS_LCTX_VALID(lctx));
1971 lctx->seen_include = ISC_TRUE;
1973 result = incctx_create(lctx->mctx, origin, &new);
1974 if (result != ISC_R_SUCCESS)
1977 /* Set current domain. */
1978 if (ictx->glue != NULL || ictx->current != NULL) {
1979 for (new_in_use = 0; new_in_use < NBUFS; new_in_use++)
1980 if (!new->in_use[new_in_use])
1982 INSIST(new_in_use < NBUFS);
1983 new->current_in_use = new_in_use;
1985 dns_fixedname_name(&new->fixed[new->current_in_use]);
1986 new->in_use[new->current_in_use] = ISC_TRUE;
1987 dns_name_toregion((ictx->glue != NULL) ?
1988 ictx->glue : ictx->current, &r);
1989 dns_name_fromregion(new->current, &r);
1990 new->drop = ictx->drop;
1993 result = (lctx->openfile)(lctx, master_file);
1994 if (result != ISC_R_SUCCESS)
1998 return (ISC_R_SUCCESS);
2002 incctx_destroy(lctx->mctx, new);
2006 static inline isc_result_t
2007 read_and_check(isc_boolean_t do_read, isc_buffer_t *buffer,
2008 size_t len, FILE *f)
2010 isc_result_t result;
2013 INSIST(isc_buffer_availablelength(buffer) >= len);
2014 result = isc_stdio_read(isc_buffer_used(buffer), 1, len,
2016 if (result != ISC_R_SUCCESS)
2018 isc_buffer_add(buffer, len);
2019 } else if (isc_buffer_remaininglength(buffer) < len)
2020 return (ISC_R_RANGE);
2022 return (ISC_R_SUCCESS);
2026 load_raw(dns_loadctx_t *lctx) {
2027 isc_result_t result = ISC_R_SUCCESS;
2028 isc_boolean_t done = ISC_FALSE;
2029 unsigned int loop_cnt = 0;
2030 dns_rdatacallbacks_t *callbacks;
2031 unsigned char namebuf[DNS_NAME_MAXWIRE];
2034 rdatalist_head_t head, dummy;
2035 dns_rdatalist_t rdatalist;
2036 isc_mem_t *mctx = lctx->mctx;
2037 dns_rdata_t *rdata = NULL;
2038 unsigned int rdata_size = 0;
2039 int target_size = TSIZ;
2040 isc_buffer_t target;
2041 unsigned char *target_mem = NULL;
2043 REQUIRE(DNS_LCTX_VALID(lctx));
2044 callbacks = lctx->callbacks;
2047 dns_masterrawheader_t header;
2048 isc_uint32_t format, version, dumptime;
2049 size_t hdrlen = sizeof(format) + sizeof(version) +
2052 INSIST(hdrlen <= sizeof(header));
2053 isc_buffer_init(&target, &header, sizeof(header));
2055 result = isc_stdio_read(&header, 1, hdrlen, lctx->f, NULL);
2056 if (result != ISC_R_SUCCESS) {
2057 UNEXPECTED_ERROR(__FILE__, __LINE__,
2058 "isc_stdio_read failed: %s",
2059 isc_result_totext(result));
2062 isc_buffer_add(&target, hdrlen);
2063 format = isc_buffer_getuint32(&target);
2064 if (format != dns_masterformat_raw) {
2065 (*callbacks->error)(callbacks,
2067 "file format mismatch");
2068 return (ISC_R_NOTIMPLEMENTED);
2071 version = isc_buffer_getuint32(&target);
2072 if (version > DNS_RAWFORMAT_VERSION) {
2073 (*callbacks->error)(callbacks,
2075 "unsupported file format version");
2076 return (ISC_R_NOTIMPLEMENTED);
2079 /* Empty read: currently, we do not use dumptime */
2080 dumptime = isc_buffer_getuint32(&target);
2082 lctx->first = ISC_FALSE;
2085 ISC_LIST_INIT(head);
2086 ISC_LIST_INIT(dummy);
2087 dns_rdatalist_init(&rdatalist);
2090 * Allocate target_size of buffer space. This is greater than twice
2091 * the maximum individual RR data size.
2093 target_mem = isc_mem_get(mctx, target_size);
2094 if (target_mem == NULL) {
2095 result = ISC_R_NOMEMORY;
2098 isc_buffer_init(&target, target_mem, target_size);
2101 * In the following loop, we regard any error fatal regardless of
2102 * whether "MANYERRORS" is set in the context option. This is because
2103 * normal errors should already have been checked at creation time.
2104 * Besides, it is very unlikely that we can recover from an error
2105 * in this format, and so trying to continue parsing erroneous data
2106 * does not really make sense.
2109 (lctx->loop_cnt == 0 || loop_cnt < lctx->loop_cnt);
2111 unsigned int i, rdcount, consumed_name;
2112 isc_uint16_t namelen;
2113 isc_uint32_t totallen;
2114 size_t minlen, readlen;
2115 isc_boolean_t sequential_read = ISC_FALSE;
2117 /* Read the data length */
2118 isc_buffer_clear(&target);
2119 INSIST(isc_buffer_availablelength(&target) >=
2121 result = isc_stdio_read(target.base, 1, sizeof(totallen),
2123 if (result == ISC_R_EOF) {
2124 result = ISC_R_SUCCESS;
2128 if (result != ISC_R_SUCCESS)
2130 isc_buffer_add(&target, sizeof(totallen));
2131 totallen = isc_buffer_getuint32(&target);
2133 * Validation: the input data must at least contain the common
2136 minlen = sizeof(totallen) + sizeof(isc_uint16_t) +
2137 sizeof(isc_uint16_t) + sizeof(isc_uint16_t) +
2138 sizeof(isc_uint32_t) + sizeof(isc_uint32_t);
2139 if (totallen < minlen) {
2140 result = ISC_R_RANGE;
2143 totallen -= sizeof(totallen);
2145 isc_buffer_clear(&target);
2146 if (totallen > isc_buffer_availablelength(&target)) {
2148 * The default buffer size should typically be large
2149 * enough to store the entire RRset. We could try to
2150 * allocate enough space if this is not the case, but
2151 * it might cause a hazardous result when "totallen"
2152 * is forged. Thus, we'd rather take an inefficient
2153 * but robust approach in this atypical case: read
2154 * data step by step, and commit partial data when
2155 * necessary. Note that the buffer must be large
2156 * enough to store the "header part", owner name, and
2157 * at least one rdata (however large it is).
2159 sequential_read = ISC_TRUE;
2160 readlen = minlen - sizeof(totallen);
2163 * Typical case. We can read the whole RRset at once
2164 * with the default buffer.
2168 result = isc_stdio_read(target.base, 1, readlen,
2170 if (result != ISC_R_SUCCESS)
2172 isc_buffer_add(&target, readlen);
2174 /* Construct RRset headers */
2175 rdatalist.rdclass = isc_buffer_getuint16(&target);
2176 rdatalist.type = isc_buffer_getuint16(&target);
2177 rdatalist.covers = isc_buffer_getuint16(&target);
2178 rdatalist.ttl = isc_buffer_getuint32(&target);
2179 rdcount = isc_buffer_getuint32(&target);
2181 result = ISC_R_RANGE;
2184 INSIST(isc_buffer_consumedlength(&target) <= readlen);
2186 /* Owner name: length followed by name */
2187 result = read_and_check(sequential_read, &target,
2188 sizeof(namelen), lctx->f);
2189 if (result != ISC_R_SUCCESS)
2191 namelen = isc_buffer_getuint16(&target);
2192 if (namelen > sizeof(namebuf)) {
2193 result = ISC_R_RANGE;
2197 result = read_and_check(sequential_read, &target, namelen,
2199 if (result != ISC_R_SUCCESS)
2201 isc_buffer_setactive(&target, (unsigned int)namelen);
2202 isc_buffer_activeregion(&target, &r);
2203 dns_name_init(&name, NULL);
2204 dns_name_fromregion(&name, &r);
2205 isc_buffer_forward(&target, (unsigned int)namelen);
2206 consumed_name = isc_buffer_consumedlength(&target);
2208 /* Rdata contents. */
2209 if (rdcount > rdata_size) {
2210 dns_rdata_t *new_rdata = NULL;
2212 new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
2215 if (new_rdata == NULL) {
2216 result = ISC_R_NOMEMORY;
2224 for (i = 0; i < rdcount; i++) {
2227 dns_rdata_init(&rdata[i]);
2229 if (sequential_read &&
2230 isc_buffer_availablelength(&target) < MINTSIZ) {
2233 INSIST(i > 0); /* detect an infinite loop */
2235 /* Partial Commit. */
2236 ISC_LIST_APPEND(head, &rdatalist, link);
2237 result = commit(callbacks, lctx, &head, &name,
2239 for (j = 0; j < i; j++) {
2240 ISC_LIST_UNLINK(rdatalist.rdata,
2242 dns_rdata_reset(&rdata[j]);
2244 if (result != ISC_R_SUCCESS)
2247 /* Rewind the buffer and continue */
2248 isc_buffer_clear(&target);
2249 isc_buffer_add(&target, consumed_name);
2250 isc_buffer_forward(&target, consumed_name);
2259 result = read_and_check(sequential_read, &target,
2260 sizeof(rdlen), lctx->f);
2261 if (result != ISC_R_SUCCESS)
2263 rdlen = isc_buffer_getuint16(&target);
2266 result = read_and_check(sequential_read, &target,
2268 if (result != ISC_R_SUCCESS)
2270 isc_buffer_setactive(&target, (unsigned int)rdlen);
2271 isc_buffer_activeregion(&target, &r);
2272 isc_buffer_forward(&target, (unsigned int)rdlen);
2273 dns_rdata_fromregion(&rdata[i], rdatalist.rdclass,
2274 rdatalist.type, &r);
2276 ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link);
2280 * Sanity check. Still having remaining space is not
2281 * necessarily critical, but it very likely indicates broken
2282 * or malformed data.
2284 if (isc_buffer_remaininglength(&target) != 0) {
2285 result = ISC_R_RANGE;
2289 ISC_LIST_APPEND(head, &rdatalist, link);
2291 /* Commit this RRset. rdatalist will be unlinked. */
2292 result = commit(callbacks, lctx, &head, &name, NULL, 0);
2294 for (i = 0; i < rdcount; i++) {
2295 ISC_LIST_UNLINK(rdatalist.rdata, &rdata[i], link);
2296 dns_rdata_reset(&rdata[i]);
2299 if (result != ISC_R_SUCCESS)
2304 INSIST(lctx->done != NULL && lctx->task != NULL);
2305 result = DNS_R_CONTINUE;
2306 } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS)
2307 result = lctx->result;
2311 isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
2312 if (target_mem != NULL)
2313 isc_mem_put(mctx, target_mem, target_size);
2314 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE) {
2315 (*callbacks->error)(callbacks, "dns_master_load: %s",
2316 dns_result_totext(result));
2323 dns_master_loadfile(const char *master_file, dns_name_t *top,
2325 dns_rdataclass_t zclass, unsigned int options,
2326 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2328 return (dns_master_loadfile3(master_file, top, origin, zclass, options,
2329 0, callbacks, mctx, dns_masterformat_text));
2333 dns_master_loadfile2(const char *master_file, dns_name_t *top,
2335 dns_rdataclass_t zclass, unsigned int options,
2336 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
2337 dns_masterformat_t format)
2339 return (dns_master_loadfile3(master_file, top, origin, zclass, options,
2340 0, callbacks, mctx, format));
2344 dns_master_loadfile3(const char *master_file, dns_name_t *top,
2345 dns_name_t *origin, dns_rdataclass_t zclass,
2346 unsigned int options, isc_uint32_t resign,
2347 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
2348 dns_masterformat_t format)
2350 dns_loadctx_t *lctx = NULL;
2351 isc_result_t result;
2353 result = loadctx_create(format, mctx, options, resign, top, zclass,
2354 origin, callbacks, NULL, NULL, NULL, NULL,
2356 if (result != ISC_R_SUCCESS)
2359 result = (lctx->openfile)(lctx, master_file);
2360 if (result != ISC_R_SUCCESS)
2363 result = (lctx->load)(lctx);
2364 INSIST(result != DNS_R_CONTINUE);
2367 dns_loadctx_detach(&lctx);
2372 dns_master_loadfileinc(const char *master_file, dns_name_t *top,
2373 dns_name_t *origin, dns_rdataclass_t zclass,
2374 unsigned int options, dns_rdatacallbacks_t *callbacks,
2375 isc_task_t *task, dns_loaddonefunc_t done,
2376 void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx)
2378 return (dns_master_loadfileinc3(master_file, top, origin, zclass,
2379 options, 0, callbacks, task, done,
2380 done_arg, lctxp, mctx,
2381 dns_masterformat_text));
2385 dns_master_loadfileinc2(const char *master_file, dns_name_t *top,
2386 dns_name_t *origin, dns_rdataclass_t zclass,
2387 unsigned int options, dns_rdatacallbacks_t *callbacks,
2388 isc_task_t *task, dns_loaddonefunc_t done,
2389 void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx,
2390 dns_masterformat_t format)
2392 return (dns_master_loadfileinc3(master_file, top, origin, zclass,
2393 options, 0, callbacks, task, done,
2394 done_arg, lctxp, mctx, format));
2398 dns_master_loadfileinc3(const char *master_file, dns_name_t *top,
2399 dns_name_t *origin, dns_rdataclass_t zclass,
2400 unsigned int options, isc_uint32_t resign,
2401 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2402 dns_loaddonefunc_t done, void *done_arg,
2403 dns_loadctx_t **lctxp, isc_mem_t *mctx,
2404 dns_masterformat_t format)
2406 dns_loadctx_t *lctx = NULL;
2407 isc_result_t result;
2409 REQUIRE(task != NULL);
2410 REQUIRE(done != NULL);
2412 result = loadctx_create(format, mctx, options, resign, top, zclass,
2413 origin, callbacks, task, done, done_arg, NULL,
2415 if (result != ISC_R_SUCCESS)
2418 result = (lctx->openfile)(lctx, master_file);
2419 if (result != ISC_R_SUCCESS)
2422 result = task_send(lctx);
2423 if (result == ISC_R_SUCCESS) {
2424 dns_loadctx_attach(lctx, lctxp);
2425 return (DNS_R_CONTINUE);
2429 dns_loadctx_detach(&lctx);
2434 dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
2435 dns_rdataclass_t zclass, unsigned int options,
2436 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2438 isc_result_t result;
2439 dns_loadctx_t *lctx = NULL;
2441 REQUIRE(stream != NULL);
2443 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2444 zclass, origin, callbacks, NULL, NULL, NULL,
2446 if (result != ISC_R_SUCCESS)
2449 result = isc_lex_openstream(lctx->lex, stream);
2450 if (result != ISC_R_SUCCESS)
2453 result = (lctx->load)(lctx);
2454 INSIST(result != DNS_R_CONTINUE);
2458 dns_loadctx_detach(&lctx);
2463 dns_master_loadstreaminc(FILE *stream, dns_name_t *top, dns_name_t *origin,
2464 dns_rdataclass_t zclass, unsigned int options,
2465 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2466 dns_loaddonefunc_t done, void *done_arg,
2467 dns_loadctx_t **lctxp, isc_mem_t *mctx)
2469 isc_result_t result;
2470 dns_loadctx_t *lctx = NULL;
2472 REQUIRE(stream != NULL);
2473 REQUIRE(task != NULL);
2474 REQUIRE(done != NULL);
2476 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2477 zclass, origin, callbacks, task, done,
2478 done_arg, NULL, &lctx);
2479 if (result != ISC_R_SUCCESS)
2482 result = isc_lex_openstream(lctx->lex, stream);
2483 if (result != ISC_R_SUCCESS)
2486 result = task_send(lctx);
2487 if (result == ISC_R_SUCCESS) {
2488 dns_loadctx_attach(lctx, lctxp);
2489 return (DNS_R_CONTINUE);
2494 dns_loadctx_detach(&lctx);
2499 dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top,
2500 dns_name_t *origin, dns_rdataclass_t zclass,
2501 unsigned int options,
2502 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2504 isc_result_t result;
2505 dns_loadctx_t *lctx = NULL;
2507 REQUIRE(buffer != NULL);
2509 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2510 zclass, origin, callbacks, NULL, NULL, NULL,
2512 if (result != ISC_R_SUCCESS)
2515 result = isc_lex_openbuffer(lctx->lex, buffer);
2516 if (result != ISC_R_SUCCESS)
2519 result = (lctx->load)(lctx);
2520 INSIST(result != DNS_R_CONTINUE);
2523 dns_loadctx_detach(&lctx);
2528 dns_master_loadbufferinc(isc_buffer_t *buffer, dns_name_t *top,
2529 dns_name_t *origin, dns_rdataclass_t zclass,
2530 unsigned int options,
2531 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2532 dns_loaddonefunc_t done, void *done_arg,
2533 dns_loadctx_t **lctxp, isc_mem_t *mctx)
2535 isc_result_t result;
2536 dns_loadctx_t *lctx = NULL;
2538 REQUIRE(buffer != NULL);
2539 REQUIRE(task != NULL);
2540 REQUIRE(done != NULL);
2542 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2543 zclass, origin, callbacks, task, done,
2544 done_arg, NULL, &lctx);
2545 if (result != ISC_R_SUCCESS)
2548 result = isc_lex_openbuffer(lctx->lex, buffer);
2549 if (result != ISC_R_SUCCESS)
2552 result = task_send(lctx);
2553 if (result == ISC_R_SUCCESS) {
2554 dns_loadctx_attach(lctx, lctxp);
2555 return (DNS_R_CONTINUE);
2559 dns_loadctx_detach(&lctx);
2564 dns_master_loadlexer(isc_lex_t *lex, dns_name_t *top,
2565 dns_name_t *origin, dns_rdataclass_t zclass,
2566 unsigned int options,
2567 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2569 isc_result_t result;
2570 dns_loadctx_t *lctx = NULL;
2572 REQUIRE(lex != NULL);
2574 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2575 zclass, origin, callbacks, NULL, NULL, NULL,
2577 if (result != ISC_R_SUCCESS)
2580 result = (lctx->load)(lctx);
2581 INSIST(result != DNS_R_CONTINUE);
2583 dns_loadctx_detach(&lctx);
2588 dns_master_loadlexerinc(isc_lex_t *lex, dns_name_t *top,
2589 dns_name_t *origin, dns_rdataclass_t zclass,
2590 unsigned int options,
2591 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2592 dns_loaddonefunc_t done, void *done_arg,
2593 dns_loadctx_t **lctxp, isc_mem_t *mctx)
2595 isc_result_t result;
2596 dns_loadctx_t *lctx = NULL;
2598 REQUIRE(lex != NULL);
2599 REQUIRE(task != NULL);
2600 REQUIRE(done != NULL);
2602 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2603 zclass, origin, callbacks, task, done,
2604 done_arg, lex, &lctx);
2605 if (result != ISC_R_SUCCESS)
2608 result = task_send(lctx);
2609 if (result == ISC_R_SUCCESS) {
2610 dns_loadctx_attach(lctx, lctxp);
2611 return (DNS_R_CONTINUE);
2614 dns_loadctx_detach(&lctx);
2619 * Grow the slab of dns_rdatalist_t structures.
2620 * Re-link glue and current list.
2622 static dns_rdatalist_t *
2623 grow_rdatalist(int new_len, dns_rdatalist_t *old, int old_len,
2624 rdatalist_head_t *current, rdatalist_head_t *glue,
2627 dns_rdatalist_t *new;
2629 ISC_LIST(dns_rdatalist_t) save;
2630 dns_rdatalist_t *this;
2632 new = isc_mem_get(mctx, new_len * sizeof(*new));
2636 ISC_LIST_INIT(save);
2637 this = ISC_LIST_HEAD(*current);
2638 while ((this = ISC_LIST_HEAD(*current)) != NULL) {
2639 ISC_LIST_UNLINK(*current, this, link);
2640 ISC_LIST_APPEND(save, this, link);
2642 while ((this = ISC_LIST_HEAD(save)) != NULL) {
2643 ISC_LIST_UNLINK(save, this, link);
2644 new[rdlcount] = *this;
2645 ISC_LIST_APPEND(*current, &new[rdlcount], link);
2649 ISC_LIST_INIT(save);
2650 this = ISC_LIST_HEAD(*glue);
2651 while ((this = ISC_LIST_HEAD(*glue)) != NULL) {
2652 ISC_LIST_UNLINK(*glue, this, link);
2653 ISC_LIST_APPEND(save, this, link);
2655 while ((this = ISC_LIST_HEAD(save)) != NULL) {
2656 ISC_LIST_UNLINK(save, this, link);
2657 new[rdlcount] = *this;
2658 ISC_LIST_APPEND(*glue, &new[rdlcount], link);
2662 INSIST(rdlcount == old_len);
2664 isc_mem_put(mctx, old, old_len * sizeof(*old));
2669 * Grow the slab of rdata structs.
2670 * Re-link the current and glue chains.
2672 static dns_rdata_t *
2673 grow_rdata(int new_len, dns_rdata_t *old, int old_len,
2674 rdatalist_head_t *current, rdatalist_head_t *glue,
2679 ISC_LIST(dns_rdata_t) save;
2680 dns_rdatalist_t *this;
2683 new = isc_mem_get(mctx, new_len * sizeof(*new));
2686 memset(new, 0, new_len * sizeof(*new));
2689 * Copy current relinking.
2691 this = ISC_LIST_HEAD(*current);
2692 while (this != NULL) {
2693 ISC_LIST_INIT(save);
2694 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
2695 ISC_LIST_UNLINK(this->rdata, rdata, link);
2696 ISC_LIST_APPEND(save, rdata, link);
2698 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
2699 ISC_LIST_UNLINK(save, rdata, link);
2700 new[rdcount] = *rdata;
2701 ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
2704 this = ISC_LIST_NEXT(this, link);
2708 * Copy glue relinking.
2710 this = ISC_LIST_HEAD(*glue);
2711 while (this != NULL) {
2712 ISC_LIST_INIT(save);
2713 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
2714 ISC_LIST_UNLINK(this->rdata, rdata, link);
2715 ISC_LIST_APPEND(save, rdata, link);
2717 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
2718 ISC_LIST_UNLINK(save, rdata, link);
2719 new[rdcount] = *rdata;
2720 ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
2723 this = ISC_LIST_NEXT(this, link);
2725 INSIST(rdcount == old_len);
2727 isc_mem_put(mctx, old, old_len * sizeof(*old));
2732 resign_fromlist(dns_rdatalist_t *this, isc_uint32_t resign) {
2734 dns_rdata_rrsig_t sig;
2737 rdata = ISC_LIST_HEAD(this->rdata);
2738 INSIST(rdata != NULL);
2739 (void)dns_rdata_tostruct(rdata, &sig, NULL);
2740 when = sig.timeexpire - resign;
2742 rdata = ISC_LIST_NEXT(rdata, link);
2743 while (rdata != NULL) {
2744 (void)dns_rdata_tostruct(rdata, &sig, NULL);
2745 if (sig.timeexpire - resign < when)
2746 when = sig.timeexpire - resign;
2747 rdata = ISC_LIST_NEXT(rdata, link);
2753 * Convert each element from a rdatalist_t to rdataset then call commit.
2754 * Unlink each element as we go.
2758 commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
2759 rdatalist_head_t *head, dns_name_t *owner,
2760 const char *source, unsigned int line)
2762 dns_rdatalist_t *this;
2763 dns_rdataset_t dataset;
2764 isc_result_t result;
2765 char namebuf[DNS_NAME_FORMATSIZE];
2766 void (*error)(struct dns_rdatacallbacks *, const char *, ...);
2768 this = ISC_LIST_HEAD(*head);
2769 error = callbacks->error;
2772 return (ISC_R_SUCCESS);
2774 dns_rdataset_init(&dataset);
2775 RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset)
2777 dataset.trust = dns_trust_ultimate;
2779 * If this is a secure dynamic zone set the re-signing time.
2781 if (dataset.type == dns_rdatatype_rrsig &&
2782 (lctx->options & DNS_MASTER_RESIGN) != 0) {
2783 dataset.attributes |= DNS_RDATASETATTR_RESIGN;
2784 dns_name_format(owner, namebuf, sizeof(namebuf));
2785 dataset.resign = resign_fromlist(this, lctx->resign);
2787 result = ((*callbacks->add)(callbacks->add_private, owner,
2789 if (result == ISC_R_NOMEMORY) {
2790 (*error)(callbacks, "dns_master_load: %s",
2791 dns_result_totext(result));
2792 } else if (result != ISC_R_SUCCESS) {
2793 dns_name_format(owner, namebuf, sizeof(namebuf));
2794 if (source != NULL) {
2795 (*error)(callbacks, "%s: %s:%lu: %s: %s",
2796 "dns_master_load", source, line,
2797 namebuf, dns_result_totext(result));
2799 (*error)(callbacks, "%s: %s: %s",
2800 "dns_master_load", namebuf,
2801 dns_result_totext(result));
2804 if (MANYERRS(lctx, result))
2805 SETRESULT(lctx, result);
2806 else if (result != ISC_R_SUCCESS)
2808 ISC_LIST_UNLINK(*head, this, link);
2809 this = ISC_LIST_HEAD(*head);
2810 } while (this != NULL);
2811 return (ISC_R_SUCCESS);
2815 * Returns ISC_TRUE if one of the NS rdata's contains 'owner'.
2818 static isc_boolean_t
2819 is_glue(rdatalist_head_t *head, dns_name_t *owner) {
2820 dns_rdatalist_t *this;
2822 isc_region_t region;
2828 this = ISC_LIST_HEAD(*head);
2829 while (this != NULL) {
2830 if (this->type == dns_rdatatype_ns)
2832 this = ISC_LIST_NEXT(this, link);
2837 rdata = ISC_LIST_HEAD(this->rdata);
2838 while (rdata != NULL) {
2839 dns_name_init(&name, NULL);
2840 dns_rdata_toregion(rdata, ®ion);
2841 dns_name_fromregion(&name, ®ion);
2842 if (dns_name_compare(&name, owner) == 0)
2844 rdata = ISC_LIST_NEXT(rdata, link);
2850 load_quantum(isc_task_t *task, isc_event_t *event) {
2851 isc_result_t result;
2852 dns_loadctx_t *lctx;
2854 REQUIRE(event != NULL);
2855 lctx = event->ev_arg;
2856 REQUIRE(DNS_LCTX_VALID(lctx));
2859 result = ISC_R_CANCELED;
2861 result = (lctx->load)(lctx);
2862 if (result == DNS_R_CONTINUE) {
2863 event->ev_arg = lctx;
2864 isc_task_send(task, &event);
2866 (lctx->done)(lctx->done_arg, result);
2867 isc_event_free(&event);
2868 dns_loadctx_detach(&lctx);
2873 task_send(dns_loadctx_t *lctx) {
2876 event = isc_event_allocate(lctx->mctx, NULL,
2877 DNS_EVENT_MASTERQUANTUM,
2878 load_quantum, lctx, sizeof(*event));
2880 return (ISC_R_NOMEMORY);
2881 isc_task_send(lctx->task, &event);
2882 return (ISC_R_SUCCESS);
2886 dns_loadctx_cancel(dns_loadctx_t *lctx) {
2887 REQUIRE(DNS_LCTX_VALID(lctx));
2890 lctx->canceled = ISC_TRUE;
2891 UNLOCK(&lctx->lock);