1 /* $NetBSD: master.c,v 1.14 2015/07/08 17:28:58 christos Exp $ */
4 * Copyright (C) 2004-2009, 2011-2015 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
26 #include <isc/event.h>
28 #include <isc/magic.h>
30 #include <isc/print.h>
31 #include <isc/serial.h>
32 #include <isc/stdio.h>
33 #include <isc/stdtime.h>
34 #include <isc/string.h>
38 #include <dns/callbacks.h>
39 #include <dns/events.h>
40 #include <dns/fixedname.h>
41 #include <dns/master.h>
43 #include <dns/rdata.h>
44 #include <dns/rdataclass.h>
45 #include <dns/rdatalist.h>
46 #include <dns/rdataset.h>
47 #include <dns/rdatastruct.h>
48 #include <dns/rdatatype.h>
49 #include <dns/result.h>
55 * Grow the number of dns_rdatalist_t (#RDLSZ) and dns_rdata_t (#RDSZ) structures
56 * by these sizes when we need to.
59 /*% RDLSZ reflects the number of different types with the same name expected. */
62 * RDSZ reflects the number of rdata expected at a give name that can fit into
71 * Target buffer size and minimum target size.
72 * MINTSIZ must be big enough to hold the largest rdata record.
76 #define TSIZ (128*1024)
78 * max message size - header - root - type - class - ttl - rdlen
80 #define MINTSIZ DNS_RDATA_MAXLENGTH
82 * Size for tokens in the presentation format,
83 * The largest tokens are the base64 blocks in KEY and CERT records,
84 * Largest key allowed is about 1372 bytes but
85 * there is no fixed upper bound on CERT records.
86 * 2K is too small for some X.509s, 8K is overkill.
88 #define TOKENSIZ (8*1024)
91 * Buffers sizes for $GENERATE.
93 #define DNS_MASTER_LHS 2048
94 #define DNS_MASTER_RHS MINTSIZ
96 #define CHECKNAMESFAIL(x) (((x) & DNS_MASTER_CHECKNAMESFAIL) != 0)
98 typedef ISC_LIST(dns_rdatalist_t
) rdatalist_head_t
;
100 typedef struct dns_incctx dns_incctx_t
;
103 * Master file load state.
109 dns_masterformat_t format
;
111 dns_rdatacallbacks_t
*callbacks
;
113 dns_loaddonefunc_t done
;
117 isc_result_t (*openfile
)(dns_loadctx_t
*lctx
,
118 const char *filename
);
119 isc_result_t (*load
)(dns_loadctx_t
*lctx
);
121 /* Members used by all formats */
124 /* Members specific to the text format: */
126 isc_boolean_t keep_lex
;
127 unsigned int options
;
128 isc_boolean_t ttl_known
;
129 isc_boolean_t default_ttl_known
;
130 isc_boolean_t warn_1035
;
131 isc_boolean_t warn_tcr
;
132 isc_boolean_t warn_sigexpired
;
133 isc_boolean_t seen_include
;
135 isc_uint32_t default_ttl
;
136 dns_rdataclass_t zclass
;
137 dns_fixedname_t fixed_top
;
138 dns_name_t
*top
; /*%< top of zone */
140 /* Members specific to the raw format: */
143 dns_masterrawheader_t header
;
145 /* Which fixed buffers we are using? */
146 unsigned int loop_cnt
; /*% records per quantum,
148 isc_boolean_t canceled
;
152 isc_uint32_t references
;
156 dns_masterincludecb_t include_cb
;
161 dns_incctx_t
*parent
;
165 dns_fixedname_t fixed
[NBUFS
]; /* working buffers */
166 unsigned int in_use
[NBUFS
]; /* covert to bitmap? */
170 isc_boolean_t origin_changed
;
172 unsigned int glue_line
;
173 unsigned int current_line
;
176 #define DNS_LCTX_MAGIC ISC_MAGIC('L','c','t','x')
177 #define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
179 #define DNS_AS_STR(t) ((t).value.as_textregion.base)
182 openfile_text(dns_loadctx_t
*lctx
, const char *master_file
);
185 load_text(dns_loadctx_t
*lctx
);
188 openfile_raw(dns_loadctx_t
*lctx
, const char *master_file
);
191 load_raw(dns_loadctx_t
*lctx
);
194 openfile_map(dns_loadctx_t
*lctx
, const char *master_file
);
197 load_map(dns_loadctx_t
*lctx
);
200 pushfile(const char *master_file
, dns_name_t
*origin
, dns_loadctx_t
*lctx
);
203 commit(dns_rdatacallbacks_t
*, dns_loadctx_t
*, rdatalist_head_t
*,
204 dns_name_t
*, const char *, unsigned int);
207 is_glue(rdatalist_head_t
*, dns_name_t
*);
209 static dns_rdatalist_t
*
210 grow_rdatalist(int, dns_rdatalist_t
*, int, rdatalist_head_t
*,
211 rdatalist_head_t
*, isc_mem_t
*mctx
);
214 grow_rdata(int, dns_rdata_t
*, int, rdatalist_head_t
*, rdatalist_head_t
*,
218 load_quantum(isc_task_t
*task
, isc_event_t
*event
);
221 task_send(dns_loadctx_t
*lctx
);
224 loadctx_destroy(dns_loadctx_t
*lctx
);
226 #define GETTOKENERR(lexer, options, token, eol, err) \
228 result = gettoken(lexer, options, token, eol, callbacks); \
230 case ISC_R_SUCCESS: \
232 case ISC_R_UNEXPECTED: \
233 goto insist_and_cleanup; \
235 if (MANYERRS(lctx, result)) { \
236 SETRESULT(lctx, result); \
238 read_till_eol = ISC_TRUE; \
242 goto log_and_cleanup; \
244 if ((token)->type == isc_tokentype_special) { \
245 result = DNS_R_SYNTAX; \
246 if (MANYERRS(lctx, result)) { \
247 SETRESULT(lctx, result); \
249 read_till_eol = ISC_TRUE; \
252 goto log_and_cleanup; \
254 } while (/*CONSTCOND*/0)
255 #define GETTOKEN(lexer, options, token, eol) \
256 GETTOKENERR(lexer, options, token, eol, {} )
260 result = commit(callbacks, lctx, ¤t_list, \
261 ictx->current, source, ictx->current_line); \
262 if (MANYERRS(lctx, result)) { \
263 SETRESULT(lctx, result); \
264 } else if (result != ISC_R_SUCCESS) \
265 goto insist_and_cleanup; \
266 result = commit(callbacks, lctx, &glue_list, \
267 ictx->glue, source, ictx->glue_line); \
268 if (MANYERRS(lctx, result)) { \
269 SETRESULT(lctx, result); \
270 } else if (result != ISC_R_SUCCESS) \
271 goto insist_and_cleanup; \
274 isc_buffer_init(&target, target_mem, target_size); \
275 rdcount_save = rdcount; \
276 rdlcount_save = rdlcount; \
277 } while (/*CONSTCOND*/0)
279 #define WARNUNEXPECTEDEOF(lexer) \
281 if (isc_lex_isfile(lexer)) \
282 (*callbacks->warn)(callbacks, \
283 "%s: file does not end with newline", \
285 } while (/*CONSTCOND*/0)
289 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE); \
290 if (token.type != isc_tokentype_eol) { \
291 isc_lex_ungettoken(lctx->lex, &token); \
292 result = DNS_R_EXTRATOKEN; \
293 if (MANYERRS(lctx, result)) { \
294 SETRESULT(lctx, result); \
296 read_till_eol = ISC_TRUE; \
297 } else if (result != ISC_R_SUCCESS) \
298 goto log_and_cleanup; \
300 } while (/*CONSTCOND*/0)
302 #define MANYERRS(lctx, result) \
303 ((result != ISC_R_SUCCESS) && \
304 (result != ISC_R_IOERROR) && \
305 ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
307 #define SETRESULT(lctx, r) \
309 if ((lctx)->result == ISC_R_SUCCESS) \
310 (lctx)->result = r; \
311 } while (/*CONSTCOND*/0)
313 #define LOGITFILE(result, filename) \
314 if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \
315 result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \
316 result == ISC_R_NOPERM) \
317 (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \
318 "dns_master_load", source, line, \
319 filename, dns_result_totext(result)); \
322 #define LOGIT(result) \
323 if (result == ISC_R_NOMEMORY) \
324 (*callbacks->error)(callbacks, "dns_master_load: %s", \
325 dns_result_totext(result)); \
327 (*callbacks->error)(callbacks, "%s: %s:%lu: %s", \
329 source, line, dns_result_totext(result))
332 static unsigned char in_addr_arpa_data
[] = "\007IN-ADDR\004ARPA";
333 static unsigned char in_addr_arpa_offsets
[] = { 0, 8, 13 };
334 static const dns_name_t in_addr_arpa
=
337 in_addr_arpa_data
, 14, 3,
338 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
339 in_addr_arpa_offsets
, NULL
,
340 {(void *)-1, (void *)-1},
344 static unsigned char ip6_int_data
[] = "\003IP6\003INT";
345 static unsigned char ip6_int_offsets
[] = { 0, 4, 8 };
346 static const dns_name_t ip6_int
=
350 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
351 ip6_int_offsets
, NULL
,
352 {(void *)-1, (void *)-1},
356 static unsigned char ip6_arpa_data
[] = "\003IP6\004ARPA";
357 static unsigned char ip6_arpa_offsets
[] = { 0, 4, 9 };
358 static const dns_name_t ip6_arpa
=
361 ip6_arpa_data
, 10, 3,
362 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
363 ip6_arpa_offsets
, NULL
,
364 {(void *)-1, (void *)-1},
369 static inline isc_result_t
370 gettoken(isc_lex_t
*lex
, unsigned int options
, isc_token_t
*token
,
371 isc_boolean_t eol
, dns_rdatacallbacks_t
*callbacks
)
375 options
|= ISC_LEXOPT_EOL
| ISC_LEXOPT_EOF
| ISC_LEXOPT_DNSMULTILINE
|
377 result
= isc_lex_gettoken(lex
, options
, token
);
378 if (result
!= ISC_R_SUCCESS
) {
381 return (ISC_R_NOMEMORY
);
383 (*callbacks
->error
)(callbacks
,
384 "dns_master_load: %s:%lu:"
385 " isc_lex_gettoken() failed: %s",
386 isc_lex_getsourcename(lex
),
387 isc_lex_getsourceline(lex
),
388 isc_result_totext(result
));
394 if (token
->type
== isc_tokentype_eol
||
395 token
->type
== isc_tokentype_eof
) {
396 unsigned long int line
;
399 file
= isc_lex_getsourcename(lex
);
400 line
= isc_lex_getsourceline(lex
);
401 if (token
->type
== isc_tokentype_eol
) {
406 (*callbacks
->error
)(callbacks
,
407 "dns_master_load: %s:%lu: unexpected end of %s",
409 return (ISC_R_UNEXPECTEDEND
);
411 return (ISC_R_SUCCESS
);
416 dns_loadctx_attach(dns_loadctx_t
*source
, dns_loadctx_t
**target
) {
418 REQUIRE(target
!= NULL
&& *target
== NULL
);
419 REQUIRE(DNS_LCTX_VALID(source
));
422 INSIST(source
->references
> 0);
423 source
->references
++;
424 INSIST(source
->references
!= 0); /* Overflow? */
425 UNLOCK(&source
->lock
);
431 dns_loadctx_detach(dns_loadctx_t
**lctxp
) {
433 isc_boolean_t need_destroy
= ISC_FALSE
;
435 REQUIRE(lctxp
!= NULL
);
437 REQUIRE(DNS_LCTX_VALID(lctx
));
440 INSIST(lctx
->references
> 0);
442 if (lctx
->references
== 0)
443 need_destroy
= ISC_TRUE
;
447 loadctx_destroy(lctx
);
452 incctx_destroy(isc_mem_t
*mctx
, dns_incctx_t
*ictx
) {
453 dns_incctx_t
*parent
;
456 parent
= ictx
->parent
;
459 isc_mem_put(mctx
, ictx
, sizeof(*ictx
));
461 if (parent
!= NULL
) {
468 loadctx_destroy(dns_loadctx_t
*lctx
) {
472 REQUIRE(DNS_LCTX_VALID(lctx
));
475 if (lctx
->inc
!= NULL
)
476 incctx_destroy(lctx
->mctx
, lctx
->inc
);
478 if (lctx
->f
!= NULL
) {
479 result
= isc_stdio_close(lctx
->f
);
480 if (result
!= ISC_R_SUCCESS
) {
481 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
482 "isc_stdio_close() failed: %s",
483 isc_result_totext(result
));
487 /* isc_lex_destroy() will close all open streams */
488 if (lctx
->lex
!= NULL
&& !lctx
->keep_lex
)
489 isc_lex_destroy(&lctx
->lex
);
491 if (lctx
->task
!= NULL
)
492 isc_task_detach(&lctx
->task
);
493 DESTROYLOCK(&lctx
->lock
);
495 isc_mem_attach(lctx
->mctx
, &mctx
);
496 isc_mem_detach(&lctx
->mctx
);
497 isc_mem_put(mctx
, lctx
, sizeof(*lctx
));
498 isc_mem_detach(&mctx
);
502 incctx_create(isc_mem_t
*mctx
, dns_name_t
*origin
, dns_incctx_t
**ictxp
) {
507 ictx
= isc_mem_get(mctx
, sizeof(*ictx
));
509 return (ISC_R_NOMEMORY
);
511 for (i
= 0; i
< NBUFS
; i
++) {
512 dns_fixedname_init(&ictx
->fixed
[i
]);
513 ictx
->in_use
[i
] = ISC_FALSE
;
516 ictx
->origin_in_use
= 0;
517 ictx
->origin
= dns_fixedname_name(&ictx
->fixed
[ictx
->origin_in_use
]);
518 ictx
->in_use
[ictx
->origin_in_use
] = ISC_TRUE
;
519 dns_name_toregion(origin
, &r
);
520 dns_name_fromregion(ictx
->origin
, &r
);
523 ictx
->current
= NULL
;
524 ictx
->glue_in_use
= -1;
525 ictx
->current_in_use
= -1;
527 ictx
->drop
= ISC_FALSE
;
529 ictx
->current_line
= 0;
530 ictx
->origin_changed
= ISC_TRUE
;
533 return (ISC_R_SUCCESS
);
537 loadctx_create(dns_masterformat_t format
, isc_mem_t
*mctx
,
538 unsigned int options
, isc_uint32_t resign
, dns_name_t
*top
,
539 dns_rdataclass_t zclass
, dns_name_t
*origin
,
540 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
541 dns_loaddonefunc_t done
, void *done_arg
,
542 dns_masterincludecb_t include_cb
, void *include_arg
,
543 isc_lex_t
*lex
, dns_loadctx_t
**lctxp
)
548 isc_lexspecials_t specials
;
550 REQUIRE(lctxp
!= NULL
&& *lctxp
== NULL
);
551 REQUIRE(callbacks
!= NULL
);
552 REQUIRE(callbacks
->add
!= NULL
);
553 REQUIRE(callbacks
->error
!= NULL
);
554 REQUIRE(callbacks
->warn
!= NULL
);
555 REQUIRE(mctx
!= NULL
);
556 REQUIRE(dns_name_isabsolute(top
));
557 REQUIRE(dns_name_isabsolute(origin
));
558 REQUIRE((task
== NULL
&& done
== NULL
) ||
559 (task
!= NULL
&& done
!= NULL
));
561 lctx
= isc_mem_get(mctx
, sizeof(*lctx
));
563 return (ISC_R_NOMEMORY
);
564 result
= isc_mutex_init(&lctx
->lock
);
565 if (result
!= ISC_R_SUCCESS
) {
566 isc_mem_put(mctx
, lctx
, sizeof(*lctx
));
571 result
= incctx_create(mctx
, origin
, &lctx
->inc
);
572 if (result
!= ISC_R_SUCCESS
)
577 lctx
->format
= format
;
581 case dns_masterformat_text
:
582 lctx
->openfile
= openfile_text
;
583 lctx
->load
= load_text
;
585 case dns_masterformat_raw
:
586 lctx
->openfile
= openfile_raw
;
587 lctx
->load
= load_raw
;
589 case dns_masterformat_map
:
590 lctx
->openfile
= openfile_map
;
591 lctx
->load
= load_map
;
597 lctx
->keep_lex
= ISC_TRUE
;
600 result
= isc_lex_create(mctx
, TOKENSIZ
, &lctx
->lex
);
601 if (result
!= ISC_R_SUCCESS
)
603 lctx
->keep_lex
= ISC_FALSE
;
604 memset(specials
, 0, sizeof(specials
));
609 isc_lex_setspecials(lctx
->lex
, specials
);
610 isc_lex_setcomments(lctx
->lex
, ISC_LEXCOMMENT_DNSMASTERFILE
);
613 lctx
->ttl_known
= ISC_TF((options
& DNS_MASTER_NOTTL
) != 0);
615 lctx
->default_ttl_known
= lctx
->ttl_known
;
616 lctx
->default_ttl
= 0;
617 lctx
->warn_1035
= ISC_TRUE
; /* XXX Argument? */
618 lctx
->warn_tcr
= ISC_TRUE
; /* XXX Argument? */
619 lctx
->warn_sigexpired
= ISC_TRUE
; /* XXX Argument? */
620 lctx
->options
= options
;
621 lctx
->seen_include
= ISC_FALSE
;
622 lctx
->zclass
= zclass
;
623 lctx
->resign
= resign
;
624 lctx
->result
= ISC_R_SUCCESS
;
625 lctx
->include_cb
= include_cb
;
626 lctx
->include_arg
= include_arg
;
628 dns_fixedname_init(&lctx
->fixed_top
);
629 lctx
->top
= dns_fixedname_name(&lctx
->fixed_top
);
630 dns_name_toregion(top
, &r
);
631 dns_name_fromregion(lctx
->top
, &r
);
634 lctx
->first
= ISC_TRUE
;
635 dns_master_initrawheader(&lctx
->header
);
637 lctx
->loop_cnt
= (done
!= NULL
) ? 100 : 0;
638 lctx
->callbacks
= callbacks
;
641 isc_task_attach(task
, &lctx
->task
);
643 lctx
->done_arg
= done_arg
;
644 lctx
->canceled
= ISC_FALSE
;
646 isc_mem_attach(mctx
, &lctx
->mctx
);
647 lctx
->references
= 1; /* Implicit attach. */
648 lctx
->magic
= DNS_LCTX_MAGIC
;
650 return (ISC_R_SUCCESS
);
653 incctx_destroy(mctx
, lctx
->inc
);
655 isc_mem_put(mctx
, lctx
, sizeof(*lctx
));
659 static const char *hex
= "0123456789abcdef0123456789ABCDEF";
662 * Convert value into a nibble sequence from least significant to most
663 * significant nibble. Zero fill upper most significant nibbles if
664 * required to make the width.
666 * Returns the number of characters that should have been written without
667 * counting the terminating NUL.
670 nibbles(char *numbuf
, size_t length
, unsigned int width
, char mode
, int value
) {
671 unsigned int count
= 0;
674 * This reserve space for the NUL string terminator.
681 char val
= hex
[(value
& 0x0f) + ((mode
== 'n') ? 0 : 16)];
692 * If width is non zero then we need to add a label seperator.
693 * If value is non zero then we need to add another label and
694 * that requires a label seperator.
696 if (width
> 0 || value
!= 0) {
706 } while (value
!= 0 || width
> 0);
711 genname(char *name
, int it
, char *buffer
, size_t length
) {
712 char fmt
[sizeof("%04000000000d")];
720 isc_boolean_t nibblemode
;
723 r
.length
= (unsigned int)length
;
725 while (*name
!= '\0') {
730 return (ISC_R_NOSPACE
);
732 isc_textregion_consume(&r
, 1);
735 nibblemode
= ISC_FALSE
;
737 /* Get format specifier. */
739 n
= sscanf(name
, "{%d,%u,%1[doxXnN]}",
740 &delta
, &width
, mode
);
745 n
= snprintf(fmt
, sizeof(fmt
),
749 if (mode
[0] == 'n' || mode
[0] == 'N')
750 nibblemode
= ISC_TRUE
;
751 n
= snprintf(fmt
, sizeof(fmt
),
752 "%%0%u%c", width
, mode
[0]);
755 return (DNS_R_SYNTAX
);
757 if (n
>= sizeof(fmt
))
758 return (ISC_R_NOSPACE
);
759 /* Skip past closing brace. */
760 while (*name
!= '\0' && *name
++ != '}')
764 n
= nibbles(numbuf
, sizeof(numbuf
), width
,
765 mode
[0], it
+ delta
);
767 n
= snprintf(numbuf
, sizeof(numbuf
), fmt
,
769 if (n
>= sizeof(numbuf
))
770 return (ISC_R_NOSPACE
);
772 while (*cp
!= '\0') {
774 return (ISC_R_NOSPACE
);
776 isc_textregion_consume(&r
, 1);
778 } else if (*name
== '\\') {
780 return (ISC_R_NOSPACE
);
782 isc_textregion_consume(&r
, 1);
786 return (ISC_R_NOSPACE
);
788 isc_textregion_consume(&r
, 1);
791 return (ISC_R_NOSPACE
);
793 isc_textregion_consume(&r
, 1);
797 return (ISC_R_NOSPACE
);
799 return (ISC_R_SUCCESS
);
803 generate(dns_loadctx_t
*lctx
, char *range
, char *lhs
, char *gtype
, char *rhs
,
804 const char *source
, unsigned int line
)
806 char *target_mem
= NULL
;
809 dns_fixedname_t ownerfixed
;
811 dns_rdata_t rdata
= DNS_RDATA_INIT
;
812 dns_rdatacallbacks_t
*callbacks
;
813 dns_rdatalist_t rdatalist
;
814 dns_rdatatype_t type
;
815 rdatalist_head_t head
;
816 int target_size
= MINTSIZ
; /* only one rdata at a time */
821 int i
, n
, start
, stop
, step
= 0;
826 callbacks
= lctx
->callbacks
;
827 dns_fixedname_init(&ownerfixed
);
828 owner
= dns_fixedname_name(&ownerfixed
);
831 target_mem
= isc_mem_get(lctx
->mctx
, target_size
);
832 rhsbuf
= isc_mem_get(lctx
->mctx
, DNS_MASTER_RHS
);
833 lhsbuf
= isc_mem_get(lctx
->mctx
, DNS_MASTER_LHS
);
834 if (target_mem
== NULL
|| rhsbuf
== NULL
|| lhsbuf
== NULL
) {
835 result
= ISC_R_NOMEMORY
;
838 isc_buffer_init(&target
, target_mem
, target_size
);
840 n
= sscanf(range
, "%d-%d%[/]%d", &start
, &stop
, &dummy
, &step
);
841 if ((n
!= 2 && n
!= 4) || (start
< 0) || (stop
< 0) ||
842 (n
== 4 && step
< 1) || (stop
< start
))
844 (*callbacks
->error
)(callbacks
,
845 "%s: %s:%lu: invalid range '%s'",
846 "$GENERATE", source
, line
, range
);
847 result
= DNS_R_SYNTAX
;
857 r
.length
= strlen(gtype
);
858 result
= dns_rdatatype_fromtext(&type
, &r
);
859 if (result
!= ISC_R_SUCCESS
) {
860 (*callbacks
->error
)(callbacks
,
861 "%s: %s:%lu: unknown RR type '%s'",
862 "$GENERATE", source
, line
, gtype
);
866 ISC_LIST_INIT(rdatalist
.rdata
);
867 ISC_LINK_INIT(&rdatalist
, link
);
868 for (i
= start
; i
<= stop
; i
+= step
) {
869 result
= genname(lhs
, i
, lhsbuf
, DNS_MASTER_LHS
);
870 if (result
!= ISC_R_SUCCESS
)
872 result
= genname(rhs
, i
, rhsbuf
, DNS_MASTER_RHS
);
873 if (result
!= ISC_R_SUCCESS
)
876 isc_buffer_init(&buffer
, lhsbuf
, strlen(lhsbuf
));
877 isc_buffer_add(&buffer
, strlen(lhsbuf
));
878 isc_buffer_setactive(&buffer
, strlen(lhsbuf
));
879 result
= dns_name_fromtext(owner
, &buffer
, ictx
->origin
,
881 if (result
!= ISC_R_SUCCESS
)
884 if ((lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
885 (lctx
->options
& DNS_MASTER_SLAVE
) == 0 &&
886 (lctx
->options
& DNS_MASTER_KEY
) == 0 &&
887 !dns_name_issubdomain(owner
, lctx
->top
))
889 char namebuf
[DNS_NAME_FORMATSIZE
];
890 dns_name_format(owner
, namebuf
, sizeof(namebuf
));
892 * Ignore out-of-zone data.
894 (*callbacks
->warn
)(callbacks
,
896 "ignoring out-of-zone data (%s)",
897 source
, line
, namebuf
);
901 isc_buffer_init(&buffer
, rhsbuf
, strlen(rhsbuf
));
902 isc_buffer_add(&buffer
, strlen(rhsbuf
));
903 isc_buffer_setactive(&buffer
, strlen(rhsbuf
));
905 result
= isc_lex_openbuffer(lctx
->lex
, &buffer
);
906 if (result
!= ISC_R_SUCCESS
)
909 isc_buffer_init(&target
, target_mem
, target_size
);
910 result
= dns_rdata_fromtext(&rdata
, lctx
->zclass
, type
,
911 lctx
->lex
, ictx
->origin
, 0,
912 lctx
->mctx
, &target
, callbacks
);
913 RUNTIME_CHECK(isc_lex_close(lctx
->lex
) == ISC_R_SUCCESS
);
914 if (result
!= ISC_R_SUCCESS
)
917 rdatalist
.type
= type
;
918 rdatalist
.covers
= 0;
919 rdatalist
.rdclass
= lctx
->zclass
;
920 rdatalist
.ttl
= lctx
->ttl
;
921 ISC_LIST_PREPEND(head
, &rdatalist
, link
);
922 ISC_LIST_APPEND(rdatalist
.rdata
, &rdata
, link
);
923 result
= commit(callbacks
, lctx
, &head
, owner
, source
, line
);
924 ISC_LIST_UNLINK(rdatalist
.rdata
, &rdata
, link
);
925 if (result
!= ISC_R_SUCCESS
)
927 dns_rdata_reset(&rdata
);
929 result
= ISC_R_SUCCESS
;
933 if (result
== ISC_R_NOMEMORY
)
934 (*callbacks
->error
)(callbacks
, "$GENERATE: %s",
935 dns_result_totext(result
));
937 (*callbacks
->error
)(callbacks
, "$GENERATE: %s:%lu: %s",
938 source
, line
, dns_result_totext(result
));
941 INSIST(result
!= ISC_R_SUCCESS
);
944 if (target_mem
!= NULL
)
945 isc_mem_put(lctx
->mctx
, target_mem
, target_size
);
947 isc_mem_put(lctx
->mctx
, lhsbuf
, DNS_MASTER_LHS
);
949 isc_mem_put(lctx
->mctx
, rhsbuf
, DNS_MASTER_RHS
);
954 limit_ttl(dns_rdatacallbacks_t
*callbacks
, const char *source
,
955 unsigned int line
, isc_uint32_t
*ttlp
)
957 if (*ttlp
> 0x7fffffffUL
) {
958 (callbacks
->warn
)(callbacks
,
960 "$TTL %lu > MAXTTL, "
970 check_ns(dns_loadctx_t
*lctx
, isc_token_t
*token
, const char *source
,
974 isc_result_t result
= ISC_R_SUCCESS
;
975 void (*callback
)(struct dns_rdatacallbacks
*, const char *, ...);
977 if ((lctx
->options
& DNS_MASTER_FATALNS
) != 0)
978 callback
= lctx
->callbacks
->error
;
980 callback
= lctx
->callbacks
->warn
;
982 if (token
->type
== isc_tokentype_string
) {
984 struct in6_addr addr6
;
986 tmp
= isc_mem_strdup(lctx
->mctx
, DNS_AS_STR(*token
));
988 return (ISC_R_NOMEMORY
);
990 * Catch both "1.2.3.4" and "1.2.3.4."
992 if (tmp
[strlen(tmp
) - 1] == '.')
993 tmp
[strlen(tmp
) - 1] = '\0';
994 if (inet_aton(tmp
, &addr
) == 1 ||
995 inet_pton(AF_INET6
, tmp
, &addr6
) == 1)
996 result
= DNS_R_NSISADDRESS
;
998 if (result
!= ISC_R_SUCCESS
)
999 (*callback
)(lctx
->callbacks
, "%s:%lu: NS record '%s' "
1000 "appears to be an address",
1001 source
, line
, DNS_AS_STR(*token
));
1003 isc_mem_free(lctx
->mctx
, tmp
);
1008 check_wildcard(dns_incctx_t
*ictx
, const char *source
, unsigned long line
,
1009 dns_rdatacallbacks_t
*callbacks
)
1013 name
= (ictx
->glue
!= NULL
) ? ictx
->glue
: ictx
->current
;
1014 if (dns_name_internalwildcard(name
)) {
1015 char namebuf
[DNS_NAME_FORMATSIZE
];
1017 dns_name_format(name
, namebuf
, sizeof(namebuf
));
1018 (*callbacks
->warn
)(callbacks
, "%s:%lu: warning: ownername "
1019 "'%s' contains an non-terminal wildcard",
1020 source
, line
, namebuf
);
1025 openfile_text(dns_loadctx_t
*lctx
, const char *master_file
) {
1026 return (isc_lex_openfile(lctx
->lex
, master_file
));
1030 load_text(dns_loadctx_t
*lctx
) {
1031 dns_rdataclass_t rdclass
;
1032 dns_rdatatype_t type
, covers
;
1033 isc_uint32_t ttl_offset
= 0;
1034 dns_name_t
*new_name
;
1035 isc_boolean_t current_has_delegation
= ISC_FALSE
;
1036 isc_boolean_t done
= ISC_FALSE
;
1037 isc_boolean_t finish_origin
= ISC_FALSE
;
1038 isc_boolean_t finish_include
= ISC_FALSE
;
1039 isc_boolean_t read_till_eol
= ISC_FALSE
;
1040 isc_boolean_t initialws
;
1041 char *include_file
= NULL
;
1043 isc_result_t result
= ISC_R_UNEXPECTED
;
1044 rdatalist_head_t glue_list
;
1045 rdatalist_head_t current_list
;
1046 dns_rdatalist_t
*this;
1047 dns_rdatalist_t
*rdatalist
= NULL
;
1048 dns_rdatalist_t
*new_rdatalist
;
1050 int rdlcount_save
= 0;
1051 int rdatalist_size
= 0;
1052 isc_buffer_t buffer
;
1053 isc_buffer_t target
;
1054 isc_buffer_t target_ft
;
1055 isc_buffer_t target_save
;
1056 dns_rdata_t
*rdata
= NULL
;
1057 dns_rdata_t
*new_rdata
;
1059 int rdcount_save
= 0;
1061 unsigned char *target_mem
= NULL
;
1062 int target_size
= TSIZ
;
1064 unsigned int loop_cnt
= 0;
1066 dns_rdatacallbacks_t
*callbacks
;
1072 const char *source
= "";
1073 unsigned long line
= 0;
1074 isc_boolean_t explicit_ttl
;
1076 char classname1
[DNS_RDATACLASS_FORMATSIZE
];
1077 char classname2
[DNS_RDATACLASS_FORMATSIZE
];
1078 unsigned int options
= 0;
1080 REQUIRE(DNS_LCTX_VALID(lctx
));
1081 callbacks
= lctx
->callbacks
;
1085 ISC_LIST_INIT(glue_list
);
1086 ISC_LIST_INIT(current_list
);
1088 isc_stdtime_get(&now
);
1091 * Allocate target_size of buffer space. This is greater than twice
1092 * the maximum individual RR data size.
1094 target_mem
= isc_mem_get(mctx
, target_size
);
1095 if (target_mem
== NULL
) {
1096 result
= ISC_R_NOMEMORY
;
1097 goto log_and_cleanup
;
1099 isc_buffer_init(&target
, target_mem
, target_size
);
1100 target_save
= target
;
1102 if ((lctx
->options
& DNS_MASTER_CHECKNAMES
) != 0)
1103 options
|= DNS_RDATA_CHECKNAMES
;
1104 if ((lctx
->options
& DNS_MASTER_CHECKNAMESFAIL
) != 0)
1105 options
|= DNS_RDATA_CHECKNAMESFAIL
;
1106 if ((lctx
->options
& DNS_MASTER_CHECKMX
) != 0)
1107 options
|= DNS_RDATA_CHECKMX
;
1108 if ((lctx
->options
& DNS_MASTER_CHECKMXFAIL
) != 0)
1109 options
|= DNS_RDATA_CHECKMXFAIL
;
1110 source
= isc_lex_getsourcename(lctx
->lex
);
1112 initialws
= ISC_FALSE
;
1113 line
= isc_lex_getsourceline(lctx
->lex
);
1114 GETTOKEN(lctx
->lex
, ISC_LEXOPT_INITIALWS
| ISC_LEXOPT_QSTRING
,
1116 line
= isc_lex_getsourceline(lctx
->lex
);
1118 if (token
.type
== isc_tokentype_eof
) {
1120 WARNUNEXPECTEDEOF(lctx
->lex
);
1121 /* Pop the include stack? */
1122 if (ictx
->parent
!= NULL
) {
1124 lctx
->inc
= ictx
->parent
;
1125 ictx
->parent
= NULL
;
1126 incctx_destroy(lctx
->mctx
, ictx
);
1127 RUNTIME_CHECK(isc_lex_close(lctx
->lex
) == ISC_R_SUCCESS
);
1128 line
= isc_lex_getsourceline(lctx
->lex
);
1129 source
= isc_lex_getsourcename(lctx
->lex
);
1137 if (token
.type
== isc_tokentype_eol
) {
1138 read_till_eol
= ISC_FALSE
;
1139 continue; /* blank line */
1145 if (token
.type
== isc_tokentype_initialws
) {
1147 * Still working on the same name.
1149 initialws
= ISC_TRUE
;
1150 } else if (token
.type
== isc_tokentype_string
||
1151 token
.type
== isc_tokentype_qstring
) {
1156 * "$ORIGIN" and "$INCLUDE" can both take domain names.
1157 * The processing of "$ORIGIN" and "$INCLUDE" extends
1158 * across the normal domain name processing.
1161 if (strcasecmp(DNS_AS_STR(token
), "$ORIGIN") == 0) {
1162 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1163 finish_origin
= ISC_TRUE
;
1164 } else if (strcasecmp(DNS_AS_STR(token
),
1166 GETTOKENERR(lctx
->lex
, 0, &token
, ISC_FALSE
,
1168 lctx
->default_ttl_known
= ISC_TRUE
;);
1170 dns_ttl_fromtext(&token
.value
.as_textregion
,
1172 if (MANYERRS(lctx
, result
)) {
1173 SETRESULT(lctx
, result
);
1175 } else if (result
!= ISC_R_SUCCESS
)
1176 goto insist_and_cleanup
;
1177 limit_ttl(callbacks
, source
, line
, &lctx
->ttl
);
1178 lctx
->default_ttl
= lctx
->ttl
;
1179 lctx
->default_ttl_known
= ISC_TRUE
;
1182 } else if (strcasecmp(DNS_AS_STR(token
),
1185 if ((lctx
->options
& DNS_MASTER_NOINCLUDE
)
1188 (callbacks
->error
)(callbacks
,
1189 "%s: %s:%lu: $INCLUDE not allowed",
1192 result
= DNS_R_REFUSED
;
1193 goto insist_and_cleanup
;
1195 if (ttl_offset
!= 0) {
1196 (callbacks
->error
)(callbacks
,
1197 "%s: %s:%lu: $INCLUDE "
1198 "may not be used with $DATE",
1201 result
= DNS_R_SYNTAX
;
1202 goto insist_and_cleanup
;
1204 GETTOKEN(lctx
->lex
, ISC_LEXOPT_QSTRING
, &token
,
1206 if (include_file
!= NULL
)
1207 isc_mem_free(mctx
, include_file
);
1208 include_file
= isc_mem_strdup(mctx
,
1210 if (include_file
== NULL
) {
1211 result
= ISC_R_NOMEMORY
;
1212 goto log_and_cleanup
;
1214 GETTOKEN(lctx
->lex
, 0, &token
, ISC_TRUE
);
1216 if (token
.type
== isc_tokentype_eol
||
1217 token
.type
== isc_tokentype_eof
) {
1218 if (token
.type
== isc_tokentype_eof
)
1219 WARNUNEXPECTEDEOF(lctx
->lex
);
1223 result
= pushfile(include_file
,
1224 ictx
->origin
, lctx
);
1225 if (MANYERRS(lctx
, result
)) {
1226 SETRESULT(lctx
, result
);
1227 LOGITFILE(result
, include_file
);
1229 } else if (result
!= ISC_R_SUCCESS
) {
1230 LOGITFILE(result
, include_file
);
1231 goto insist_and_cleanup
;
1235 isc_lex_getsourcename(lctx
->lex
);
1236 line
= isc_lex_getsourceline(lctx
->lex
);
1241 * There is an origin field. Fall through
1242 * to domain name processing code and do
1243 * the actual inclusion later.
1245 finish_include
= ISC_TRUE
;
1246 } else if (strcasecmp(DNS_AS_STR(token
),
1248 isc_int64_t dump_time64
;
1249 isc_stdtime_t dump_time
, current_time
;
1250 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1251 isc_stdtime_get(¤t_time
);
1252 result
= dns_time64_fromtext(DNS_AS_STR(token
),
1254 if (MANYERRS(lctx
, result
)) {
1255 SETRESULT(lctx
, result
);
1258 } else if (result
!= ISC_R_SUCCESS
)
1259 goto log_and_cleanup
;
1260 dump_time
= (isc_stdtime_t
)dump_time64
;
1261 if (dump_time
!= dump_time64
) {
1262 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1263 "%s: %s:%lu: $DATE outside epoch",
1264 "dns_master_load", source
, line
);
1265 result
= ISC_R_UNEXPECTED
;
1266 goto insist_and_cleanup
;
1268 if (dump_time
> current_time
) {
1269 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1271 "$DATE in future, using current date",
1272 "dns_master_load", source
, line
);
1273 dump_time
= current_time
;
1275 ttl_offset
= current_time
- dump_time
;
1278 } else if (strcasecmp(DNS_AS_STR(token
),
1279 "$GENERATE") == 0) {
1284 isc_mem_free(mctx
, range
);
1286 isc_mem_free(mctx
, lhs
);
1288 isc_mem_free(mctx
, gtype
);
1290 isc_mem_free(mctx
, rhs
);
1291 range
= lhs
= gtype
= rhs
= NULL
;
1293 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1294 range
= isc_mem_strdup(mctx
,
1296 if (range
== NULL
) {
1297 result
= ISC_R_NOMEMORY
;
1298 goto log_and_cleanup
;
1301 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1302 lhs
= isc_mem_strdup(mctx
, DNS_AS_STR(token
));
1304 result
= ISC_R_NOMEMORY
;
1305 goto log_and_cleanup
;
1308 explicit_ttl
= ISC_FALSE
;
1310 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1311 if (dns_rdataclass_fromtext(&rdclass
,
1312 &token
.value
.as_textregion
)
1314 GETTOKEN(lctx
->lex
, 0, &token
,
1318 if (dns_ttl_fromtext(&token
.value
.as_textregion
,
1321 limit_ttl(callbacks
, source
, line
,
1323 lctx
->ttl_known
= ISC_TRUE
;
1324 explicit_ttl
= ISC_TRUE
;
1325 GETTOKEN(lctx
->lex
, 0, &token
,
1330 dns_rdataclass_fromtext(&rdclass
,
1331 &token
.value
.as_textregion
)
1333 GETTOKEN(lctx
->lex
, 0, &token
,
1336 gtype
= isc_mem_strdup(mctx
,
1338 if (gtype
== NULL
) {
1339 result
= ISC_R_NOMEMORY
;
1340 goto log_and_cleanup
;
1343 GETTOKEN(lctx
->lex
, ISC_LEXOPT_QSTRING
,
1345 rhs
= isc_mem_strdup(mctx
, DNS_AS_STR(token
));
1347 result
= ISC_R_NOMEMORY
;
1348 goto log_and_cleanup
;
1350 if (!lctx
->ttl_known
&&
1351 !lctx
->default_ttl_known
) {
1352 (*callbacks
->error
)(callbacks
,
1353 "%s: %s:%lu: no TTL specified",
1354 "dns_master_load", source
, line
);
1355 result
= DNS_R_NOTTL
;
1356 if (MANYERRS(lctx
, result
)) {
1357 SETRESULT(lctx
, result
);
1359 } else if (result
!= ISC_R_SUCCESS
)
1360 goto insist_and_cleanup
;
1361 } else if (!explicit_ttl
&&
1362 lctx
->default_ttl_known
) {
1363 lctx
->ttl
= lctx
->default_ttl
;
1366 * If the class specified does not match the
1367 * zone's class print out a error message and
1370 if (rdclass
!= 0 && rdclass
!= lctx
->zclass
) {
1373 result
= generate(lctx
, range
, lhs
, gtype
, rhs
,
1375 if (MANYERRS(lctx
, result
)) {
1376 SETRESULT(lctx
, result
);
1377 } else if (result
!= ISC_R_SUCCESS
)
1378 goto insist_and_cleanup
;
1381 } else if (strncasecmp(DNS_AS_STR(token
),
1383 (callbacks
->error
)(callbacks
,
1385 "unknown $ directive '%s'",
1386 "dns_master_load", source
, line
,
1388 result
= DNS_R_SYNTAX
;
1389 if (MANYERRS(lctx
, result
)) {
1390 SETRESULT(lctx
, result
);
1391 } else if (result
!= ISC_R_SUCCESS
)
1392 goto insist_and_cleanup
;
1396 * Normal processing resumes.
1398 * Find a free name buffer.
1400 for (new_in_use
= 0; new_in_use
< NBUFS
; new_in_use
++)
1401 if (!ictx
->in_use
[new_in_use
])
1403 INSIST(new_in_use
< NBUFS
);
1404 dns_fixedname_init(&ictx
->fixed
[new_in_use
]);
1405 new_name
= dns_fixedname_name(&ictx
->fixed
[new_in_use
]);
1406 isc_buffer_init(&buffer
, token
.value
.as_region
.base
,
1407 token
.value
.as_region
.length
);
1408 isc_buffer_add(&buffer
, token
.value
.as_region
.length
);
1409 isc_buffer_setactive(&buffer
,
1410 token
.value
.as_region
.length
);
1411 result
= dns_name_fromtext(new_name
, &buffer
,
1412 ictx
->origin
, 0, NULL
);
1413 if (MANYERRS(lctx
, result
)) {
1414 SETRESULT(lctx
, result
);
1416 read_till_eol
= ISC_TRUE
;
1418 } else if (result
!= ISC_R_SUCCESS
)
1419 goto log_and_cleanup
;
1422 * Finish $ORIGIN / $INCLUDE processing if required.
1424 if (finish_origin
) {
1425 if (ictx
->origin_in_use
!= -1)
1426 ictx
->in_use
[ictx
->origin_in_use
] =
1428 ictx
->origin_in_use
= new_in_use
;
1429 ictx
->in_use
[ictx
->origin_in_use
] = ISC_TRUE
;
1430 ictx
->origin
= new_name
;
1431 ictx
->origin_changed
= ISC_TRUE
;
1432 finish_origin
= ISC_FALSE
;
1436 if (finish_include
) {
1437 finish_include
= ISC_FALSE
;
1439 result
= pushfile(include_file
, new_name
, lctx
);
1440 if (MANYERRS(lctx
, result
)) {
1441 SETRESULT(lctx
, result
);
1442 LOGITFILE(result
, include_file
);
1444 } else if (result
!= ISC_R_SUCCESS
) {
1445 LOGITFILE(result
, include_file
);
1446 goto insist_and_cleanup
;
1449 ictx
->origin_changed
= ISC_TRUE
;
1450 source
= isc_lex_getsourcename(lctx
->lex
);
1451 line
= isc_lex_getsourceline(lctx
->lex
);
1457 * "$" Processing Finished
1461 * If we are processing glue and the new name does
1462 * not match the current glue name, commit the glue
1463 * and pop stacks leaving us in 'normal' processing
1464 * state. Linked lists are undone by commit().
1466 if (ictx
->glue
!= NULL
&&
1467 dns_name_compare(ictx
->glue
, new_name
) != 0) {
1468 result
= commit(callbacks
, lctx
, &glue_list
,
1471 if (MANYERRS(lctx
, result
)) {
1472 SETRESULT(lctx
, result
);
1473 } else if (result
!= ISC_R_SUCCESS
)
1474 goto insist_and_cleanup
;
1475 if (ictx
->glue_in_use
!= -1)
1476 ictx
->in_use
[ictx
->glue_in_use
] =
1478 ictx
->glue_in_use
= -1;
1480 rdcount
= rdcount_save
;
1481 rdlcount
= rdlcount_save
;
1482 target
= target_save
;
1486 * If we are in 'normal' processing state and the new
1487 * name does not match the current name, see if the
1488 * new name is for glue and treat it as such,
1489 * otherwise we have a new name so commit what we
1492 if ((ictx
->glue
== NULL
) && (ictx
->current
== NULL
||
1493 dns_name_compare(ictx
->current
, new_name
) != 0)) {
1494 if (current_has_delegation
&&
1495 is_glue(¤t_list
, new_name
)) {
1496 rdcount_save
= rdcount
;
1497 rdlcount_save
= rdlcount
;
1498 target_save
= target
;
1499 ictx
->glue
= new_name
;
1500 ictx
->glue_in_use
= new_in_use
;
1501 ictx
->in_use
[ictx
->glue_in_use
] =
1504 result
= commit(callbacks
, lctx
,
1508 ictx
->current_line
);
1509 if (MANYERRS(lctx
, result
)) {
1510 SETRESULT(lctx
, result
);
1511 } else if (result
!= ISC_R_SUCCESS
)
1512 goto insist_and_cleanup
;
1515 if (ictx
->current_in_use
!= -1)
1516 ictx
->in_use
[ictx
->current_in_use
] =
1518 ictx
->current_in_use
= new_in_use
;
1519 ictx
->in_use
[ictx
->current_in_use
] =
1521 ictx
->current
= new_name
;
1522 current_has_delegation
= ISC_FALSE
;
1523 isc_buffer_init(&target
, target_mem
,
1527 * Check for internal wildcards.
1529 if ((lctx
->options
& DNS_MASTER_CHECKWILDCARD
)
1531 check_wildcard(ictx
, source
, line
,
1535 if ((lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
1536 (lctx
->options
& DNS_MASTER_SLAVE
) == 0 &&
1537 (lctx
->options
& DNS_MASTER_KEY
) == 0 &&
1538 !dns_name_issubdomain(new_name
, lctx
->top
))
1540 char namebuf
[DNS_NAME_FORMATSIZE
];
1541 dns_name_format(new_name
, namebuf
,
1544 * Ignore out-of-zone data.
1546 (*callbacks
->warn
)(callbacks
,
1548 "ignoring out-of-zone data (%s)",
1549 source
, line
, namebuf
);
1550 ictx
->drop
= ISC_TRUE
;
1552 ictx
->drop
= ISC_FALSE
;
1554 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1555 "%s:%lu: isc_lex_gettoken() returned "
1556 "unexpected token type (%d)",
1557 source
, line
, token
.type
);
1558 result
= ISC_R_UNEXPECTED
;
1559 if (MANYERRS(lctx
, result
)) {
1560 SETRESULT(lctx
, result
);
1563 } else if (result
!= ISC_R_SUCCESS
)
1564 goto insist_and_cleanup
;
1568 * Find TTL, class and type. Both TTL and class are optional
1569 * and may occur in any order if they exist. TTL and class
1570 * come before type which must exist.
1572 * [<TTL>] [<class>] <type> <RDATA>
1573 * [<class>] [<TTL>] <type> <RDATA>
1579 GETTOKEN(lctx
->lex
, 0, &token
, initialws
);
1582 if (token
.type
== isc_tokentype_eol
) {
1583 read_till_eol
= ISC_FALSE
;
1584 continue; /* blank line */
1587 if (token
.type
== isc_tokentype_eof
) {
1588 WARNUNEXPECTEDEOF(lctx
->lex
);
1589 read_till_eol
= ISC_FALSE
;
1590 isc_lex_ungettoken(lctx
->lex
, &token
);
1594 if (ictx
->current
== NULL
) {
1595 (*callbacks
->error
)(callbacks
,
1596 "%s:%lu: no current owner name",
1598 result
= DNS_R_NOOWNER
;
1599 if (MANYERRS(lctx
, result
)) {
1600 SETRESULT(lctx
, result
);
1601 read_till_eol
= ISC_TRUE
;
1603 } else if (result
!= ISC_R_SUCCESS
)
1604 goto insist_and_cleanup
;
1607 if (ictx
->origin_changed
) {
1608 char cbuf
[DNS_NAME_FORMATSIZE
];
1609 char obuf
[DNS_NAME_FORMATSIZE
];
1610 dns_name_format(ictx
->current
, cbuf
,
1612 dns_name_format(ictx
->origin
, obuf
,
1614 (*callbacks
->warn
)(callbacks
,
1615 "%s:%lu: record with inherited "
1616 "owner (%s) immediately after "
1617 "$ORIGIN (%s)", source
, line
,
1622 ictx
->origin_changed
= ISC_FALSE
;
1624 if (dns_rdataclass_fromtext(&rdclass
,
1625 &token
.value
.as_textregion
)
1627 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1629 explicit_ttl
= ISC_FALSE
;
1630 result
= dns_ttl_fromtext(&token
.value
.as_textregion
,
1632 if (result
== ISC_R_SUCCESS
) {
1633 limit_ttl(callbacks
, source
, line
, &lctx
->ttl
);
1634 explicit_ttl
= ISC_TRUE
;
1635 lctx
->ttl_known
= ISC_TRUE
;
1636 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1639 if (token
.type
!= isc_tokentype_string
) {
1640 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1641 "isc_lex_gettoken() returned unexpected token type");
1642 result
= ISC_R_UNEXPECTED
;
1643 if (MANYERRS(lctx
, result
)) {
1644 SETRESULT(lctx
, result
);
1645 read_till_eol
= ISC_TRUE
;
1647 } else if (result
!= ISC_R_SUCCESS
)
1648 goto insist_and_cleanup
;
1652 dns_rdataclass_fromtext(&rdclass
,
1653 &token
.value
.as_textregion
)
1655 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1657 if (token
.type
!= isc_tokentype_string
) {
1658 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1659 "isc_lex_gettoken() returned unexpected token type");
1660 result
= ISC_R_UNEXPECTED
;
1661 if (MANYERRS(lctx
, result
)) {
1662 SETRESULT(lctx
, result
);
1663 read_till_eol
= ISC_TRUE
;
1665 } else if (result
!= ISC_R_SUCCESS
)
1666 goto insist_and_cleanup
;
1669 result
= dns_rdatatype_fromtext(&type
,
1670 &token
.value
.as_textregion
);
1671 if (result
!= ISC_R_SUCCESS
) {
1672 (*callbacks
->warn
)(callbacks
,
1673 "%s:%lu: unknown RR type '%.*s'",
1675 token
.value
.as_textregion
.length
,
1676 token
.value
.as_textregion
.base
);
1677 if (MANYERRS(lctx
, result
)) {
1678 SETRESULT(lctx
, result
);
1679 read_till_eol
= ISC_TRUE
;
1681 } else if (result
!= ISC_R_SUCCESS
)
1682 goto insist_and_cleanup
;
1686 * If the class specified does not match the zone's class
1687 * print out a error message and exit.
1689 if (rdclass
!= 0 && rdclass
!= lctx
->zclass
) {
1692 dns_rdataclass_format(rdclass
, classname1
,
1693 sizeof(classname1
));
1694 dns_rdataclass_format(lctx
->zclass
, classname2
,
1695 sizeof(classname2
));
1696 (*callbacks
->error
)(callbacks
,
1697 "%s:%lu: class '%s' != "
1700 classname1
, classname2
);
1701 result
= DNS_R_BADCLASS
;
1702 if (MANYERRS(lctx
, result
)) {
1703 SETRESULT(lctx
, result
);
1704 read_till_eol
= ISC_TRUE
;
1706 } else if (result
!= ISC_R_SUCCESS
)
1707 goto insist_and_cleanup
;
1710 if (type
== dns_rdatatype_ns
&& ictx
->glue
== NULL
)
1711 current_has_delegation
= ISC_TRUE
;
1714 * RFC1123: MD and MF are not allowed to be loaded from
1717 if ((lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
1718 (lctx
->options
& DNS_MASTER_SLAVE
) == 0 &&
1719 (type
== dns_rdatatype_md
|| type
== dns_rdatatype_mf
)) {
1720 char typename
[DNS_RDATATYPE_FORMATSIZE
];
1722 result
= DNS_R_OBSOLETE
;
1724 dns_rdatatype_format(type
, typename
, sizeof(typename
));
1725 (*callbacks
->error
)(callbacks
,
1726 "%s:%lu: %s '%s': %s",
1729 dns_result_totext(result
));
1730 if (MANYERRS(lctx
, result
)) {
1731 SETRESULT(lctx
, result
);
1733 goto insist_and_cleanup
;
1737 * Find a rdata structure.
1739 if (rdcount
== rdata_size
) {
1740 new_rdata
= grow_rdata(rdata_size
+ RDSZ
, rdata
,
1741 rdata_size
, ¤t_list
,
1743 if (new_rdata
== NULL
) {
1744 result
= ISC_R_NOMEMORY
;
1745 goto log_and_cleanup
;
1752 * Peek at the NS record.
1754 if (type
== dns_rdatatype_ns
&&
1755 lctx
->zclass
== dns_rdataclass_in
&&
1756 (lctx
->options
& DNS_MASTER_CHECKNS
) != 0) {
1758 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1759 result
= check_ns(lctx
, &token
, source
, line
);
1760 isc_lex_ungettoken(lctx
->lex
, &token
);
1761 if ((lctx
->options
& DNS_MASTER_FATALNS
) != 0) {
1762 if (MANYERRS(lctx
, result
)) {
1763 SETRESULT(lctx
, result
);
1764 } else if (result
!= ISC_R_SUCCESS
)
1765 goto insist_and_cleanup
;
1772 options
&= ~DNS_RDATA_CHECKREVERSE
;
1773 if ((lctx
->options
& DNS_MASTER_CHECKNAMES
) != 0) {
1777 name
= (ictx
->glue
!= NULL
) ? ictx
->glue
:
1779 ok
= dns_rdata_checkowner(name
, lctx
->zclass
, type
,
1782 char namebuf
[DNS_NAME_FORMATSIZE
];
1784 dns_name_format(name
, namebuf
, sizeof(namebuf
));
1785 result
= DNS_R_BADOWNERNAME
;
1786 desc
= dns_result_totext(result
);
1787 if (CHECKNAMESFAIL(lctx
->options
) ||
1788 type
== dns_rdatatype_nsec3
) {
1789 (*callbacks
->error
)(callbacks
,
1793 if (MANYERRS(lctx
, result
)) {
1794 SETRESULT(lctx
, result
);
1795 } else if (result
!= ISC_R_SUCCESS
)
1798 (*callbacks
->warn
)(callbacks
,
1804 if (type
== dns_rdatatype_ptr
&&
1805 (dns_name_issubdomain(name
, &in_addr_arpa
) ||
1806 dns_name_issubdomain(name
, &ip6_arpa
) ||
1807 dns_name_issubdomain(name
, &ip6_int
)))
1808 options
|= DNS_RDATA_CHECKREVERSE
;
1812 * Read rdata contents.
1814 dns_rdata_init(&rdata
[rdcount
]);
1816 result
= dns_rdata_fromtext(&rdata
[rdcount
], lctx
->zclass
,
1817 type
, lctx
->lex
, ictx
->origin
,
1818 options
, lctx
->mctx
, &target
,
1820 if (MANYERRS(lctx
, result
)) {
1821 SETRESULT(lctx
, result
);
1823 } else if (result
!= ISC_R_SUCCESS
)
1824 goto insist_and_cleanup
;
1831 if (type
== dns_rdatatype_soa
&&
1832 (lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
1833 dns_name_compare(ictx
->current
, lctx
->top
) != 0) {
1834 char namebuf
[DNS_NAME_FORMATSIZE
];
1835 dns_name_format(ictx
->current
, namebuf
,
1837 (*callbacks
->error
)(callbacks
, "%s:%lu: SOA "
1838 "record not at top of zone (%s)",
1839 source
, line
, namebuf
);
1840 result
= DNS_R_NOTZONETOP
;
1841 if (MANYERRS(lctx
, result
)) {
1842 SETRESULT(lctx
, result
);
1843 read_till_eol
= ISC_TRUE
;
1846 } else if (result
!= ISC_R_SUCCESS
)
1847 goto insist_and_cleanup
;
1851 if (type
== dns_rdatatype_rrsig
||
1852 type
== dns_rdatatype_sig
)
1853 covers
= dns_rdata_covers(&rdata
[rdcount
]);
1857 if (!lctx
->ttl_known
&& !lctx
->default_ttl_known
) {
1858 if (type
== dns_rdatatype_soa
) {
1859 (*callbacks
->warn
)(callbacks
,
1860 "%s:%lu: no TTL specified; "
1861 "using SOA MINTTL instead",
1863 lctx
->ttl
= dns_soa_getminimum(&rdata
[rdcount
]);
1864 limit_ttl(callbacks
, source
, line
, &lctx
->ttl
);
1865 lctx
->default_ttl
= lctx
->ttl
;
1866 lctx
->default_ttl_known
= ISC_TRUE
;
1867 } else if ((lctx
->options
& DNS_MASTER_HINT
) != 0) {
1869 * Zero TTL's are fine for hints.
1872 lctx
->default_ttl
= lctx
->ttl
;
1873 lctx
->default_ttl_known
= ISC_TRUE
;
1875 (*callbacks
->warn
)(callbacks
,
1876 "%s:%lu: no TTL specified; "
1879 result
= DNS_R_NOTTL
;
1880 if (MANYERRS(lctx
, result
)) {
1881 SETRESULT(lctx
, result
);
1884 goto insist_and_cleanup
;
1887 } else if (!explicit_ttl
&& lctx
->default_ttl_known
) {
1888 lctx
->ttl
= lctx
->default_ttl
;
1889 } else if (!explicit_ttl
&& lctx
->warn_1035
) {
1890 (*callbacks
->warn
)(callbacks
,
1892 "using RFC1035 TTL semantics",
1894 lctx
->warn_1035
= ISC_FALSE
;
1897 if (type
== dns_rdatatype_rrsig
&& lctx
->warn_sigexpired
) {
1898 dns_rdata_rrsig_t sig
;
1899 result
= dns_rdata_tostruct(&rdata
[rdcount
], &sig
,
1901 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1902 if (isc_serial_lt(sig
.timeexpire
, now
)) {
1903 (*callbacks
->warn
)(callbacks
,
1905 "signature has expired",
1907 lctx
->warn_sigexpired
= ISC_FALSE
;
1911 if ((type
== dns_rdatatype_sig
|| type
== dns_rdatatype_nxt
) &&
1912 lctx
->warn_tcr
&& (lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
1913 (lctx
->options
& DNS_MASTER_SLAVE
) == 0) {
1914 (*callbacks
->warn
)(callbacks
, "%s:%lu: old style DNSSEC "
1915 " zone detected", source
, line
);
1916 lctx
->warn_tcr
= ISC_FALSE
;
1919 if ((lctx
->options
& DNS_MASTER_AGETTL
) != 0) {
1921 * Adjust the TTL for $DATE. If the RR has already
1922 * expired, ignore it.
1924 if (lctx
->ttl
< ttl_offset
)
1926 lctx
->ttl
-= ttl_offset
;
1930 * Find type in rdatalist.
1931 * If it does not exist create new one and prepend to list
1932 * as this will minimise list traversal.
1934 if (ictx
->glue
!= NULL
)
1935 this = ISC_LIST_HEAD(glue_list
);
1937 this = ISC_LIST_HEAD(current_list
);
1939 while (this != NULL
) {
1940 if (this->type
== type
&& this->covers
== covers
)
1942 this = ISC_LIST_NEXT(this, link
);
1946 if (rdlcount
== rdatalist_size
) {
1948 grow_rdatalist(rdatalist_size
+ RDLSZ
,
1954 if (new_rdatalist
== NULL
) {
1955 result
= ISC_R_NOMEMORY
;
1956 goto log_and_cleanup
;
1958 rdatalist
= new_rdatalist
;
1959 rdatalist_size
+= RDLSZ
;
1961 this = &rdatalist
[rdlcount
++];
1963 this->covers
= covers
;
1964 this->rdclass
= lctx
->zclass
;
1965 this->ttl
= lctx
->ttl
;
1966 ISC_LIST_INIT(this->rdata
);
1967 if (ictx
->glue
!= NULL
)
1968 ISC_LIST_INITANDPREPEND(glue_list
, this, link
);
1970 ISC_LIST_INITANDPREPEND(current_list
, this,
1972 } else if (this->ttl
!= lctx
->ttl
) {
1973 (*callbacks
->warn
)(callbacks
,
1975 "TTL set to prior TTL (%lu)",
1976 source
, line
, this->ttl
);
1977 lctx
->ttl
= this->ttl
;
1980 if ((lctx
->options
& DNS_MASTER_CHECKTTL
) != 0 &&
1981 lctx
->ttl
> lctx
->maxttl
)
1983 (callbacks
->error
)(callbacks
,
1984 "dns_master_load: %s:%lu: "
1985 "TTL %d exceeds configured max-zone-ttl %d",
1986 source
, line
, lctx
->ttl
, lctx
->maxttl
);
1987 result
= ISC_R_RANGE
;
1988 goto log_and_cleanup
;
1991 ISC_LIST_APPEND(this->rdata
, &rdata
[rdcount
], link
);
1992 if (ictx
->glue
!= NULL
)
1993 ictx
->glue_line
= line
;
1995 ictx
->current_line
= line
;
1999 * We must have at least 64k as rdlen is 16 bits.
2000 * If we don't commit everything we have so far.
2002 if ((target
.length
- target
.used
) < MINTSIZ
)
2006 } while (!done
&& (lctx
->loop_cnt
== 0 || loop_cnt
++ < lctx
->loop_cnt
));
2009 * Commit what has not yet been committed.
2011 result
= commit(callbacks
, lctx
, ¤t_list
, ictx
->current
,
2012 source
, ictx
->current_line
);
2013 if (MANYERRS(lctx
, result
)) {
2014 SETRESULT(lctx
, result
);
2015 } else if (result
!= ISC_R_SUCCESS
)
2016 goto insist_and_cleanup
;
2017 result
= commit(callbacks
, lctx
, &glue_list
, ictx
->glue
,
2018 source
, ictx
->glue_line
);
2019 if (MANYERRS(lctx
, result
)) {
2020 SETRESULT(lctx
, result
);
2021 } else if (result
!= ISC_R_SUCCESS
)
2022 goto insist_and_cleanup
;
2025 INSIST(lctx
->done
!= NULL
&& lctx
->task
!= NULL
);
2026 result
= DNS_R_CONTINUE
;
2027 } else if (result
== ISC_R_SUCCESS
&& lctx
->result
!= ISC_R_SUCCESS
) {
2028 result
= lctx
->result
;
2029 } else if (result
== ISC_R_SUCCESS
&& lctx
->seen_include
)
2030 result
= DNS_R_SEENINCLUDE
;
2037 INSIST(result
!= ISC_R_SUCCESS
);
2040 while ((this = ISC_LIST_HEAD(current_list
)) != NULL
)
2041 ISC_LIST_UNLINK(current_list
, this, link
);
2042 while ((this = ISC_LIST_HEAD(glue_list
)) != NULL
)
2043 ISC_LIST_UNLINK(glue_list
, this, link
);
2044 if (rdatalist
!= NULL
)
2045 isc_mem_put(mctx
, rdatalist
,
2046 rdatalist_size
* sizeof(*rdatalist
));
2048 isc_mem_put(mctx
, rdata
, rdata_size
* sizeof(*rdata
));
2049 if (target_mem
!= NULL
)
2050 isc_mem_put(mctx
, target_mem
, target_size
);
2051 if (include_file
!= NULL
)
2052 isc_mem_free(mctx
, include_file
);
2054 isc_mem_free(mctx
, range
);
2056 isc_mem_free(mctx
, lhs
);
2058 isc_mem_free(mctx
, gtype
);
2060 isc_mem_free(mctx
, rhs
);
2065 pushfile(const char *master_file
, dns_name_t
*origin
, dns_loadctx_t
*lctx
) {
2066 isc_result_t result
;
2068 dns_incctx_t
*new = NULL
;
2072 REQUIRE(master_file
!= NULL
);
2073 REQUIRE(DNS_LCTX_VALID(lctx
));
2076 lctx
->seen_include
= ISC_TRUE
;
2078 result
= incctx_create(lctx
->mctx
, origin
, &new);
2079 if (result
!= ISC_R_SUCCESS
)
2083 * Push origin_changed.
2085 new->origin_changed
= ictx
->origin_changed
;
2087 /* Set current domain. */
2088 if (ictx
->glue
!= NULL
|| ictx
->current
!= NULL
) {
2089 for (new_in_use
= 0; new_in_use
< NBUFS
; new_in_use
++)
2090 if (!new->in_use
[new_in_use
])
2092 INSIST(new_in_use
< NBUFS
);
2093 new->current_in_use
= new_in_use
;
2095 dns_fixedname_name(&new->fixed
[new->current_in_use
]);
2096 new->in_use
[new->current_in_use
] = ISC_TRUE
;
2097 dns_name_toregion((ictx
->glue
!= NULL
) ?
2098 ictx
->glue
: ictx
->current
, &r
);
2099 dns_name_fromregion(new->current
, &r
);
2100 new->drop
= ictx
->drop
;
2103 result
= (lctx
->openfile
)(lctx
, master_file
);
2104 if (result
!= ISC_R_SUCCESS
)
2109 if (lctx
->include_cb
!= NULL
)
2110 lctx
->include_cb(master_file
, lctx
->include_arg
);
2111 return (ISC_R_SUCCESS
);
2114 incctx_destroy(lctx
->mctx
, new);
2118 static inline isc_result_t
2119 read_and_check(isc_boolean_t do_read
, isc_buffer_t
*buffer
,
2120 size_t len
, FILE *f
)
2122 isc_result_t result
;
2125 INSIST(isc_buffer_availablelength(buffer
) >= len
);
2126 result
= isc_stdio_read(isc_buffer_used(buffer
), 1, len
,
2128 if (result
!= ISC_R_SUCCESS
)
2130 isc_buffer_add(buffer
, (unsigned int)len
);
2131 } else if (isc_buffer_remaininglength(buffer
) < len
)
2132 return (ISC_R_RANGE
);
2134 return (ISC_R_SUCCESS
);
2138 load_header(dns_loadctx_t
*lctx
) {
2139 isc_result_t result
= ISC_R_SUCCESS
;
2140 dns_masterrawheader_t header
;
2141 dns_rdatacallbacks_t
*callbacks
;
2142 size_t commonlen
= sizeof(header
.format
) + sizeof(header
.version
);
2144 unsigned char data
[sizeof(header
)];
2145 isc_buffer_t target
;
2147 REQUIRE(DNS_LCTX_VALID(lctx
));
2149 if (lctx
->format
!= dns_masterformat_raw
&&
2150 lctx
->format
!= dns_masterformat_map
)
2151 return (ISC_R_NOTIMPLEMENTED
);
2153 callbacks
= lctx
->callbacks
;
2154 dns_master_initrawheader(&header
);
2156 INSIST(commonlen
<= sizeof(header
));
2157 isc_buffer_init(&target
, data
, sizeof(data
));
2159 result
= isc_stdio_read(data
, 1, commonlen
, lctx
->f
, NULL
);
2160 if (result
!= ISC_R_SUCCESS
) {
2161 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2162 "isc_stdio_read failed: %s",
2163 isc_result_totext(result
));
2167 isc_buffer_add(&target
, (unsigned int)commonlen
);
2168 header
.format
= isc_buffer_getuint32(&target
);
2169 if (header
.format
!= lctx
->format
) {
2170 (*callbacks
->error
)(callbacks
, "dns_master_load: "
2171 "file format mismatch (not %s)",
2172 lctx
->format
== dns_masterformat_map
2175 return (ISC_R_NOTIMPLEMENTED
);
2178 header
.version
= isc_buffer_getuint32(&target
);
2180 switch (header
.version
) {
2182 remainder
= sizeof(header
.dumptime
);
2184 case DNS_RAWFORMAT_VERSION
:
2185 remainder
= sizeof(header
) - commonlen
;
2188 (*callbacks
->error
)(callbacks
,
2190 "unsupported file format version");
2191 return (ISC_R_NOTIMPLEMENTED
);
2194 result
= isc_stdio_read(data
+ commonlen
, 1, remainder
, lctx
->f
, NULL
);
2195 if (result
!= ISC_R_SUCCESS
) {
2196 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2197 "isc_stdio_read failed: %s",
2198 isc_result_totext(result
));
2202 isc_buffer_add(&target
, (unsigned int)remainder
);
2203 header
.dumptime
= isc_buffer_getuint32(&target
);
2204 if (header
.version
== DNS_RAWFORMAT_VERSION
) {
2205 header
.flags
= isc_buffer_getuint32(&target
);
2206 header
.sourceserial
= isc_buffer_getuint32(&target
);
2207 header
.lastxfrin
= isc_buffer_getuint32(&target
);
2210 lctx
->first
= ISC_FALSE
;
2211 lctx
->header
= header
;
2213 return (ISC_R_SUCCESS
);
2217 openfile_map(dns_loadctx_t
*lctx
, const char *master_file
) {
2218 isc_result_t result
;
2220 result
= isc_stdio_open(master_file
, "rb", &lctx
->f
);
2221 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_FILENOTFOUND
) {
2222 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2223 "isc_stdio_open() failed: %s",
2224 isc_result_totext(result
));
2231 * Load a map format file, using mmap() to access RBT trees directly
2234 load_map(dns_loadctx_t
*lctx
) {
2235 isc_result_t result
= ISC_R_SUCCESS
;
2236 dns_rdatacallbacks_t
*callbacks
;
2238 REQUIRE(DNS_LCTX_VALID(lctx
));
2240 callbacks
= lctx
->callbacks
;
2243 result
= load_header(lctx
);
2244 if (result
!= ISC_R_SUCCESS
)
2247 result
= (*callbacks
->deserialize
)
2248 (callbacks
->deserialize_private
,
2249 lctx
->f
, sizeof(dns_masterrawheader_t
));
2256 openfile_raw(dns_loadctx_t
*lctx
, const char *master_file
) {
2257 isc_result_t result
;
2259 result
= isc_stdio_open(master_file
, "rb", &lctx
->f
);
2260 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_FILENOTFOUND
) {
2261 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2262 "isc_stdio_open() failed: %s",
2263 isc_result_totext(result
));
2270 load_raw(dns_loadctx_t
*lctx
) {
2271 isc_result_t result
= ISC_R_SUCCESS
;
2272 isc_boolean_t done
= ISC_FALSE
;
2273 unsigned int loop_cnt
= 0;
2274 dns_rdatacallbacks_t
*callbacks
;
2275 unsigned char namebuf
[DNS_NAME_MAXWIRE
];
2276 dns_fixedname_t fixed
;
2278 rdatalist_head_t head
, dummy
;
2279 dns_rdatalist_t rdatalist
;
2280 isc_mem_t
*mctx
= lctx
->mctx
;
2281 dns_rdata_t
*rdata
= NULL
;
2282 unsigned int rdata_size
= 0;
2283 int target_size
= TSIZ
;
2284 isc_buffer_t target
, buf
;
2285 unsigned char *target_mem
= NULL
;
2286 dns_decompress_t dctx
;
2288 REQUIRE(DNS_LCTX_VALID(lctx
));
2289 callbacks
= lctx
->callbacks
;
2290 dns_decompress_init(&dctx
, -1, DNS_DECOMPRESS_NONE
);
2293 result
= load_header(lctx
);
2294 if (result
!= ISC_R_SUCCESS
)
2298 ISC_LIST_INIT(head
);
2299 ISC_LIST_INIT(dummy
);
2300 dns_rdatalist_init(&rdatalist
);
2303 * Allocate target_size of buffer space. This is greater than twice
2304 * the maximum individual RR data size.
2306 target_mem
= isc_mem_get(mctx
, target_size
);
2307 if (target_mem
== NULL
) {
2308 result
= ISC_R_NOMEMORY
;
2311 isc_buffer_init(&target
, target_mem
, target_size
);
2313 dns_fixedname_init(&fixed
);
2314 name
= dns_fixedname_name(&fixed
);
2317 * In the following loop, we regard any error fatal regardless of
2318 * whether "MANYERRORS" is set in the context option. This is because
2319 * normal errors should already have been checked at creation time.
2320 * Besides, it is very unlikely that we can recover from an error
2321 * in this format, and so trying to continue parsing erroneous data
2322 * does not really make sense.
2325 (lctx
->loop_cnt
== 0 || loop_cnt
< lctx
->loop_cnt
);
2327 unsigned int i
, rdcount
;
2328 isc_uint16_t namelen
;
2329 isc_uint32_t totallen
;
2330 size_t minlen
, readlen
;
2331 isc_boolean_t sequential_read
= ISC_FALSE
;
2333 /* Read the data length */
2334 isc_buffer_clear(&target
);
2335 INSIST(isc_buffer_availablelength(&target
) >=
2337 result
= isc_stdio_read(target
.base
, 1, sizeof(totallen
),
2339 if (result
== ISC_R_EOF
) {
2340 result
= ISC_R_SUCCESS
;
2344 if (result
!= ISC_R_SUCCESS
)
2346 isc_buffer_add(&target
, sizeof(totallen
));
2347 totallen
= isc_buffer_getuint32(&target
);
2349 * Validation: the input data must at least contain the common
2352 minlen
= sizeof(totallen
) + sizeof(isc_uint16_t
) +
2353 sizeof(isc_uint16_t
) + sizeof(isc_uint16_t
) +
2354 sizeof(isc_uint32_t
) + sizeof(isc_uint32_t
);
2355 if (totallen
< minlen
) {
2356 result
= ISC_R_RANGE
;
2359 totallen
-= sizeof(totallen
);
2361 isc_buffer_clear(&target
);
2362 if (totallen
> isc_buffer_availablelength(&target
)) {
2364 * The default buffer size should typically be large
2365 * enough to store the entire RRset. We could try to
2366 * allocate enough space if this is not the case, but
2367 * it might cause a hazardous result when "totallen"
2368 * is forged. Thus, we'd rather take an inefficient
2369 * but robust approach in this atypical case: read
2370 * data step by step, and commit partial data when
2371 * necessary. Note that the buffer must be large
2372 * enough to store the "header part", owner name, and
2373 * at least one rdata (however large it is).
2375 sequential_read
= ISC_TRUE
;
2376 readlen
= minlen
- sizeof(totallen
);
2379 * Typical case. We can read the whole RRset at once
2380 * with the default buffer.
2384 result
= isc_stdio_read(target
.base
, 1, readlen
,
2386 if (result
!= ISC_R_SUCCESS
)
2388 isc_buffer_add(&target
, (unsigned int)readlen
);
2390 /* Construct RRset headers */
2391 rdatalist
.rdclass
= isc_buffer_getuint16(&target
);
2392 rdatalist
.type
= isc_buffer_getuint16(&target
);
2393 rdatalist
.covers
= isc_buffer_getuint16(&target
);
2394 rdatalist
.ttl
= isc_buffer_getuint32(&target
);
2395 rdcount
= isc_buffer_getuint32(&target
);
2396 if (rdcount
== 0 || rdcount
> 0xffff) {
2397 result
= ISC_R_RANGE
;
2400 INSIST(isc_buffer_consumedlength(&target
) <= readlen
);
2402 /* Owner name: length followed by name */
2403 result
= read_and_check(sequential_read
, &target
,
2404 sizeof(namelen
), lctx
->f
);
2405 if (result
!= ISC_R_SUCCESS
)
2407 namelen
= isc_buffer_getuint16(&target
);
2408 if (namelen
> sizeof(namebuf
)) {
2409 result
= ISC_R_RANGE
;
2413 result
= read_and_check(sequential_read
, &target
, namelen
,
2415 if (result
!= ISC_R_SUCCESS
)
2418 isc_buffer_setactive(&target
, (unsigned int)namelen
);
2419 result
= dns_name_fromwire(name
, &target
, &dctx
, 0, NULL
);
2420 if (result
!= ISC_R_SUCCESS
)
2423 if ((lctx
->options
& DNS_MASTER_CHECKTTL
) != 0 &&
2424 rdatalist
.ttl
> lctx
->maxttl
)
2426 (callbacks
->error
)(callbacks
,
2428 "TTL %d exceeds configured "
2430 rdatalist
.ttl
, lctx
->maxttl
);
2431 result
= ISC_R_RANGE
;
2435 /* Rdata contents. */
2436 if (rdcount
> rdata_size
) {
2437 dns_rdata_t
*new_rdata
= NULL
;
2439 new_rdata
= grow_rdata(rdcount
+ RDSZ
, rdata
,
2442 if (new_rdata
== NULL
) {
2443 result
= ISC_R_NOMEMORY
;
2446 rdata_size
= rdcount
+ RDSZ
;
2451 for (i
= 0; i
< rdcount
; i
++) {
2454 dns_rdata_init(&rdata
[i
]);
2456 if (sequential_read
&&
2457 isc_buffer_availablelength(&target
) < MINTSIZ
) {
2460 INSIST(i
> 0); /* detect an infinite loop */
2462 /* Partial Commit. */
2463 ISC_LIST_APPEND(head
, &rdatalist
, link
);
2464 result
= commit(callbacks
, lctx
, &head
, name
,
2466 for (j
= 0; j
< i
; j
++) {
2467 ISC_LIST_UNLINK(rdatalist
.rdata
,
2469 dns_rdata_reset(&rdata
[j
]);
2471 if (result
!= ISC_R_SUCCESS
)
2474 /* Rewind the buffer and continue */
2475 isc_buffer_clear(&target
);
2483 result
= read_and_check(sequential_read
, &target
,
2484 sizeof(rdlen
), lctx
->f
);
2485 if (result
!= ISC_R_SUCCESS
)
2487 rdlen
= isc_buffer_getuint16(&target
);
2490 result
= read_and_check(sequential_read
, &target
,
2492 if (result
!= ISC_R_SUCCESS
)
2494 isc_buffer_setactive(&target
, (unsigned int)rdlen
);
2496 * It is safe to have the source active region and
2497 * the target available region be the same if
2498 * decompression is disabled (see dctx above) and we
2499 * are not downcasing names (options == 0).
2501 isc_buffer_init(&buf
, isc_buffer_current(&target
),
2502 (unsigned int)rdlen
);
2503 result
= dns_rdata_fromwire(&rdata
[i
],
2505 rdatalist
.type
, &target
,
2507 if (result
!= ISC_R_SUCCESS
)
2509 ISC_LIST_APPEND(rdatalist
.rdata
, &rdata
[i
], link
);
2513 * Sanity check. Still having remaining space is not
2514 * necessarily critical, but it very likely indicates broken
2515 * or malformed data.
2517 if (isc_buffer_remaininglength(&target
) != 0) {
2518 result
= ISC_R_RANGE
;
2522 ISC_LIST_APPEND(head
, &rdatalist
, link
);
2524 /* Commit this RRset. rdatalist will be unlinked. */
2525 result
= commit(callbacks
, lctx
, &head
, name
, NULL
, 0);
2527 for (i
= 0; i
< rdcount
; i
++) {
2528 ISC_LIST_UNLINK(rdatalist
.rdata
, &rdata
[i
], link
);
2529 dns_rdata_reset(&rdata
[i
]);
2532 if (result
!= ISC_R_SUCCESS
)
2537 INSIST(lctx
->done
!= NULL
&& lctx
->task
!= NULL
);
2538 result
= DNS_R_CONTINUE
;
2539 } else if (result
== ISC_R_SUCCESS
&& lctx
->result
!= ISC_R_SUCCESS
)
2540 result
= lctx
->result
;
2542 if (result
== ISC_R_SUCCESS
&& callbacks
->rawdata
!= NULL
)
2543 (*callbacks
->rawdata
)(callbacks
->zone
, &lctx
->header
);
2547 isc_mem_put(mctx
, rdata
, rdata_size
* sizeof(*rdata
));
2548 if (target_mem
!= NULL
)
2549 isc_mem_put(mctx
, target_mem
, target_size
);
2550 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_CONTINUE
) {
2551 (*callbacks
->error
)(callbacks
, "dns_master_load: %s",
2552 dns_result_totext(result
));
2559 dns_master_loadfile(const char *master_file
, dns_name_t
*top
,
2561 dns_rdataclass_t zclass
, unsigned int options
,
2562 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
)
2564 return (dns_master_loadfile5(master_file
, top
, origin
, zclass
,
2565 options
, 0, callbacks
, NULL
, NULL
,
2566 mctx
, dns_masterformat_text
, 0));
2570 dns_master_loadfile2(const char *master_file
, dns_name_t
*top
,
2572 dns_rdataclass_t zclass
, unsigned int options
,
2573 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
,
2574 dns_masterformat_t format
)
2576 return (dns_master_loadfile5(master_file
, top
, origin
, zclass
,
2577 options
, 0, callbacks
, NULL
, NULL
,
2582 dns_master_loadfile3(const char *master_file
, dns_name_t
*top
,
2583 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2584 unsigned int options
, isc_uint32_t resign
,
2585 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
,
2586 dns_masterformat_t format
)
2588 return (dns_master_loadfile5(master_file
, top
, origin
, zclass
,
2589 options
, resign
, callbacks
, NULL
, NULL
,
2594 dns_master_loadfile4(const char *master_file
, dns_name_t
*top
,
2595 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2596 unsigned int options
, isc_uint32_t resign
,
2597 dns_rdatacallbacks_t
*callbacks
,
2598 dns_masterincludecb_t include_cb
, void *include_arg
,
2599 isc_mem_t
*mctx
, dns_masterformat_t format
)
2601 return (dns_master_loadfile5(master_file
, top
, origin
, zclass
,
2602 options
, resign
, callbacks
,
2603 include_cb
, include_arg
,
2608 dns_master_loadfile5(const char *master_file
, dns_name_t
*top
,
2609 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2610 unsigned int options
, isc_uint32_t resign
,
2611 dns_rdatacallbacks_t
*callbacks
,
2612 dns_masterincludecb_t include_cb
, void *include_arg
,
2613 isc_mem_t
*mctx
, dns_masterformat_t format
,
2616 dns_loadctx_t
*lctx
= NULL
;
2617 isc_result_t result
;
2619 result
= loadctx_create(format
, mctx
, options
, resign
, top
, zclass
,
2620 origin
, callbacks
, NULL
, NULL
, NULL
,
2621 include_cb
, include_arg
, NULL
, &lctx
);
2622 if (result
!= ISC_R_SUCCESS
)
2625 lctx
->maxttl
= maxttl
;
2627 result
= (lctx
->openfile
)(lctx
, master_file
);
2628 if (result
!= ISC_R_SUCCESS
)
2631 result
= (lctx
->load
)(lctx
);
2632 INSIST(result
!= DNS_R_CONTINUE
);
2635 dns_loadctx_detach(&lctx
);
2640 dns_master_loadfileinc(const char *master_file
, dns_name_t
*top
,
2641 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2642 unsigned int options
, dns_rdatacallbacks_t
*callbacks
,
2643 isc_task_t
*task
, dns_loaddonefunc_t done
,
2644 void *done_arg
, dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
)
2646 return (dns_master_loadfileinc4(master_file
, top
, origin
, zclass
,
2647 options
, 0, callbacks
, task
, done
,
2648 done_arg
, lctxp
, NULL
, NULL
, mctx
,
2649 dns_masterformat_text
));
2653 dns_master_loadfileinc2(const char *master_file
, dns_name_t
*top
,
2654 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2655 unsigned int options
, dns_rdatacallbacks_t
*callbacks
,
2656 isc_task_t
*task
, dns_loaddonefunc_t done
,
2657 void *done_arg
, dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
,
2658 dns_masterformat_t format
)
2660 return (dns_master_loadfileinc4(master_file
, top
, origin
, zclass
,
2661 options
, 0, callbacks
, task
, done
,
2662 done_arg
, lctxp
, NULL
, NULL
, mctx
,
2667 dns_master_loadfileinc3(const char *master_file
, dns_name_t
*top
,
2668 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2669 unsigned int options
, isc_uint32_t resign
,
2670 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
2671 dns_loaddonefunc_t done
, void *done_arg
,
2672 dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
,
2673 dns_masterformat_t format
)
2675 return (dns_master_loadfileinc4(master_file
, top
, origin
, zclass
,
2676 options
, resign
, callbacks
, task
,
2677 done
, done_arg
, lctxp
, NULL
, NULL
,
2682 dns_master_loadfileinc4(const char *master_file
, dns_name_t
*top
,
2683 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2684 unsigned int options
, isc_uint32_t resign
,
2685 dns_rdatacallbacks_t
*callbacks
,
2686 isc_task_t
*task
, dns_loaddonefunc_t done
,
2687 void *done_arg
, dns_loadctx_t
**lctxp
,
2688 dns_masterincludecb_t include_cb
, void *include_arg
,
2689 isc_mem_t
*mctx
, dns_masterformat_t format
)
2691 options
&= ~DNS_MASTER_CHECKTTL
;
2692 return (dns_master_loadfileinc5(master_file
, top
, origin
, zclass
,
2693 options
, resign
, callbacks
, task
,
2694 done
, done_arg
, lctxp
, include_cb
,
2695 include_arg
, mctx
, format
, 0));
2699 dns_master_loadfileinc5(const char *master_file
, dns_name_t
*top
,
2700 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2701 unsigned int options
, isc_uint32_t resign
,
2702 dns_rdatacallbacks_t
*callbacks
,
2703 isc_task_t
*task
, dns_loaddonefunc_t done
,
2704 void *done_arg
, dns_loadctx_t
**lctxp
,
2705 dns_masterincludecb_t include_cb
, void *include_arg
,
2706 isc_mem_t
*mctx
, dns_masterformat_t format
,
2707 isc_uint32_t maxttl
)
2709 dns_loadctx_t
*lctx
= NULL
;
2710 isc_result_t result
;
2712 REQUIRE(task
!= NULL
);
2713 REQUIRE(done
!= NULL
);
2715 result
= loadctx_create(format
, mctx
, options
, resign
, top
, zclass
,
2716 origin
, callbacks
, task
, done
, done_arg
,
2717 include_cb
, include_arg
, NULL
, &lctx
);
2718 if (result
!= ISC_R_SUCCESS
)
2721 lctx
->maxttl
= maxttl
;
2723 result
= (lctx
->openfile
)(lctx
, master_file
);
2724 if (result
!= ISC_R_SUCCESS
)
2727 result
= task_send(lctx
);
2728 if (result
== ISC_R_SUCCESS
) {
2729 dns_loadctx_attach(lctx
, lctxp
);
2730 return (DNS_R_CONTINUE
);
2734 dns_loadctx_detach(&lctx
);
2739 dns_master_loadstream(FILE *stream
, dns_name_t
*top
, dns_name_t
*origin
,
2740 dns_rdataclass_t zclass
, unsigned int options
,
2741 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
)
2743 isc_result_t result
;
2744 dns_loadctx_t
*lctx
= NULL
;
2746 REQUIRE(stream
!= NULL
);
2748 result
= loadctx_create(dns_masterformat_text
, mctx
, options
, 0, top
,
2749 zclass
, origin
, callbacks
, NULL
, NULL
, NULL
,
2750 NULL
, NULL
, NULL
, &lctx
);
2751 if (result
!= ISC_R_SUCCESS
)
2754 result
= isc_lex_openstream(lctx
->lex
, stream
);
2755 if (result
!= ISC_R_SUCCESS
)
2758 result
= (lctx
->load
)(lctx
);
2759 INSIST(result
!= DNS_R_CONTINUE
);
2763 dns_loadctx_detach(&lctx
);
2768 dns_master_loadstreaminc(FILE *stream
, dns_name_t
*top
, dns_name_t
*origin
,
2769 dns_rdataclass_t zclass
, unsigned int options
,
2770 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
2771 dns_loaddonefunc_t done
, void *done_arg
,
2772 dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
)
2774 isc_result_t result
;
2775 dns_loadctx_t
*lctx
= NULL
;
2777 REQUIRE(stream
!= NULL
);
2778 REQUIRE(task
!= NULL
);
2779 REQUIRE(done
!= NULL
);
2781 result
= loadctx_create(dns_masterformat_text
, mctx
, options
, 0, top
,
2782 zclass
, origin
, callbacks
, task
, done
,
2783 done_arg
, NULL
, NULL
, NULL
, &lctx
);
2784 if (result
!= ISC_R_SUCCESS
)
2787 result
= isc_lex_openstream(lctx
->lex
, stream
);
2788 if (result
!= ISC_R_SUCCESS
)
2791 result
= task_send(lctx
);
2792 if (result
== ISC_R_SUCCESS
) {
2793 dns_loadctx_attach(lctx
, lctxp
);
2794 return (DNS_R_CONTINUE
);
2799 dns_loadctx_detach(&lctx
);
2804 dns_master_loadbuffer(isc_buffer_t
*buffer
, dns_name_t
*top
,
2805 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2806 unsigned int options
,
2807 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
)
2809 isc_result_t result
;
2810 dns_loadctx_t
*lctx
= NULL
;
2812 REQUIRE(buffer
!= NULL
);
2814 result
= loadctx_create(dns_masterformat_text
, mctx
, options
, 0, top
,
2815 zclass
, origin
, callbacks
, NULL
, NULL
, NULL
,
2816 NULL
, NULL
, NULL
, &lctx
);
2817 if (result
!= ISC_R_SUCCESS
)
2820 result
= isc_lex_openbuffer(lctx
->lex
, buffer
);
2821 if (result
!= ISC_R_SUCCESS
)
2824 result
= (lctx
->load
)(lctx
);
2825 INSIST(result
!= DNS_R_CONTINUE
);
2828 dns_loadctx_detach(&lctx
);
2833 dns_master_loadbufferinc(isc_buffer_t
*buffer
, dns_name_t
*top
,
2834 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2835 unsigned int options
,
2836 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
2837 dns_loaddonefunc_t done
, void *done_arg
,
2838 dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
)
2840 isc_result_t result
;
2841 dns_loadctx_t
*lctx
= NULL
;
2843 REQUIRE(buffer
!= NULL
);
2844 REQUIRE(task
!= NULL
);
2845 REQUIRE(done
!= NULL
);
2847 result
= loadctx_create(dns_masterformat_text
, mctx
, options
, 0, top
,
2848 zclass
, origin
, callbacks
, task
, done
,
2849 done_arg
, NULL
, NULL
, NULL
, &lctx
);
2850 if (result
!= ISC_R_SUCCESS
)
2853 result
= isc_lex_openbuffer(lctx
->lex
, buffer
);
2854 if (result
!= ISC_R_SUCCESS
)
2857 result
= task_send(lctx
);
2858 if (result
== ISC_R_SUCCESS
) {
2859 dns_loadctx_attach(lctx
, lctxp
);
2860 return (DNS_R_CONTINUE
);
2864 dns_loadctx_detach(&lctx
);
2869 dns_master_loadlexer(isc_lex_t
*lex
, dns_name_t
*top
,
2870 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2871 unsigned int options
,
2872 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
)
2874 isc_result_t result
;
2875 dns_loadctx_t
*lctx
= NULL
;
2877 REQUIRE(lex
!= NULL
);
2879 result
= loadctx_create(dns_masterformat_text
, mctx
, options
, 0, top
,
2880 zclass
, origin
, callbacks
, NULL
, NULL
, NULL
,
2881 NULL
, NULL
, lex
, &lctx
);
2882 if (result
!= ISC_R_SUCCESS
)
2885 result
= (lctx
->load
)(lctx
);
2886 INSIST(result
!= DNS_R_CONTINUE
);
2888 dns_loadctx_detach(&lctx
);
2893 dns_master_loadlexerinc(isc_lex_t
*lex
, dns_name_t
*top
,
2894 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2895 unsigned int options
,
2896 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
2897 dns_loaddonefunc_t done
, void *done_arg
,
2898 dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
)
2900 isc_result_t result
;
2901 dns_loadctx_t
*lctx
= NULL
;
2903 REQUIRE(lex
!= NULL
);
2904 REQUIRE(task
!= NULL
);
2905 REQUIRE(done
!= NULL
);
2907 result
= loadctx_create(dns_masterformat_text
, mctx
, options
, 0, top
,
2908 zclass
, origin
, callbacks
, task
, done
,
2909 done_arg
, NULL
, NULL
, lex
, &lctx
);
2910 if (result
!= ISC_R_SUCCESS
)
2913 result
= task_send(lctx
);
2914 if (result
== ISC_R_SUCCESS
) {
2915 dns_loadctx_attach(lctx
, lctxp
);
2916 return (DNS_R_CONTINUE
);
2919 dns_loadctx_detach(&lctx
);
2924 * Grow the slab of dns_rdatalist_t structures.
2925 * Re-link glue and current list.
2927 static dns_rdatalist_t
*
2928 grow_rdatalist(int new_len
, dns_rdatalist_t
*old
, int old_len
,
2929 rdatalist_head_t
*current
, rdatalist_head_t
*glue
,
2932 dns_rdatalist_t
*new;
2934 ISC_LIST(dns_rdatalist_t
) save
;
2935 dns_rdatalist_t
*this;
2937 new = isc_mem_get(mctx
, new_len
* sizeof(*new));
2941 ISC_LIST_INIT(save
);
2942 while ((this = ISC_LIST_HEAD(*current
)) != NULL
) {
2943 ISC_LIST_UNLINK(*current
, this, link
);
2944 ISC_LIST_APPEND(save
, this, link
);
2946 while ((this = ISC_LIST_HEAD(save
)) != NULL
) {
2947 ISC_LIST_UNLINK(save
, this, link
);
2948 INSIST(rdlcount
< new_len
);
2949 new[rdlcount
] = *this;
2950 ISC_LIST_APPEND(*current
, &new[rdlcount
], link
);
2954 ISC_LIST_INIT(save
);
2955 while ((this = ISC_LIST_HEAD(*glue
)) != NULL
) {
2956 ISC_LIST_UNLINK(*glue
, this, link
);
2957 ISC_LIST_APPEND(save
, this, link
);
2959 while ((this = ISC_LIST_HEAD(save
)) != NULL
) {
2960 ISC_LIST_UNLINK(save
, this, link
);
2961 INSIST(rdlcount
< new_len
);
2962 new[rdlcount
] = *this;
2963 ISC_LIST_APPEND(*glue
, &new[rdlcount
], link
);
2967 INSIST(rdlcount
== old_len
);
2969 isc_mem_put(mctx
, old
, old_len
* sizeof(*old
));
2974 * Grow the slab of rdata structs.
2975 * Re-link the current and glue chains.
2977 static dns_rdata_t
*
2978 grow_rdata(int new_len
, dns_rdata_t
*old
, int old_len
,
2979 rdatalist_head_t
*current
, rdatalist_head_t
*glue
,
2984 ISC_LIST(dns_rdata_t
) save
;
2985 dns_rdatalist_t
*this;
2988 new = isc_mem_get(mctx
, new_len
* sizeof(*new));
2991 memset(new, 0, new_len
* sizeof(*new));
2994 * Copy current relinking.
2996 this = ISC_LIST_HEAD(*current
);
2997 while (this != NULL
) {
2998 ISC_LIST_INIT(save
);
2999 while ((rdata
= ISC_LIST_HEAD(this->rdata
)) != NULL
) {
3000 ISC_LIST_UNLINK(this->rdata
, rdata
, link
);
3001 ISC_LIST_APPEND(save
, rdata
, link
);
3003 while ((rdata
= ISC_LIST_HEAD(save
)) != NULL
) {
3004 ISC_LIST_UNLINK(save
, rdata
, link
);
3005 INSIST(rdcount
< new_len
);
3006 new[rdcount
] = *rdata
;
3007 ISC_LIST_APPEND(this->rdata
, &new[rdcount
], link
);
3010 this = ISC_LIST_NEXT(this, link
);
3014 * Copy glue relinking.
3016 this = ISC_LIST_HEAD(*glue
);
3017 while (this != NULL
) {
3018 ISC_LIST_INIT(save
);
3019 while ((rdata
= ISC_LIST_HEAD(this->rdata
)) != NULL
) {
3020 ISC_LIST_UNLINK(this->rdata
, rdata
, link
);
3021 ISC_LIST_APPEND(save
, rdata
, link
);
3023 while ((rdata
= ISC_LIST_HEAD(save
)) != NULL
) {
3024 ISC_LIST_UNLINK(save
, rdata
, link
);
3025 INSIST(rdcount
< new_len
);
3026 new[rdcount
] = *rdata
;
3027 ISC_LIST_APPEND(this->rdata
, &new[rdcount
], link
);
3030 this = ISC_LIST_NEXT(this, link
);
3032 INSIST(rdcount
== old_len
|| rdcount
== 0);
3034 isc_mem_put(mctx
, old
, old_len
* sizeof(*old
));
3039 resign_fromlist(dns_rdatalist_t
*this, isc_uint32_t resign
) {
3041 dns_rdata_rrsig_t sig
;
3044 rdata
= ISC_LIST_HEAD(this->rdata
);
3045 INSIST(rdata
!= NULL
);
3046 (void)dns_rdata_tostruct(rdata
, &sig
, NULL
);
3047 when
= sig
.timeexpire
- resign
;
3049 rdata
= ISC_LIST_NEXT(rdata
, link
);
3050 while (rdata
!= NULL
) {
3051 (void)dns_rdata_tostruct(rdata
, &sig
, NULL
);
3052 if (sig
.timeexpire
- resign
< when
)
3053 when
= sig
.timeexpire
- resign
;
3054 rdata
= ISC_LIST_NEXT(rdata
, link
);
3060 * Convert each element from a rdatalist_t to rdataset then call commit.
3061 * Unlink each element as we go.
3065 commit(dns_rdatacallbacks_t
*callbacks
, dns_loadctx_t
*lctx
,
3066 rdatalist_head_t
*head
, dns_name_t
*owner
,
3067 const char *source
, unsigned int line
)
3069 dns_rdatalist_t
*this;
3070 dns_rdataset_t dataset
;
3071 isc_result_t result
;
3072 char namebuf
[DNS_NAME_FORMATSIZE
];
3073 void (*error
)(struct dns_rdatacallbacks
*, const char *, ...);
3075 this = ISC_LIST_HEAD(*head
);
3076 error
= callbacks
->error
;
3079 return (ISC_R_SUCCESS
);
3081 dns_rdataset_init(&dataset
);
3082 RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset
)
3084 dataset
.trust
= dns_trust_ultimate
;
3086 * If this is a secure dynamic zone set the re-signing time.
3088 if (dataset
.type
== dns_rdatatype_rrsig
&&
3089 (lctx
->options
& DNS_MASTER_RESIGN
) != 0) {
3090 dataset
.attributes
|= DNS_RDATASETATTR_RESIGN
;
3091 dataset
.resign
= resign_fromlist(this, lctx
->resign
);
3093 result
= ((*callbacks
->add
)(callbacks
->add_private
, owner
,
3095 if (result
== ISC_R_NOMEMORY
) {
3096 (*error
)(callbacks
, "dns_master_load: %s",
3097 dns_result_totext(result
));
3098 } else if (result
!= ISC_R_SUCCESS
) {
3099 dns_name_format(owner
, namebuf
, sizeof(namebuf
));
3100 if (source
!= NULL
) {
3101 (*error
)(callbacks
, "%s: %s:%lu: %s: %s",
3102 "dns_master_load", source
, line
,
3103 namebuf
, dns_result_totext(result
));
3105 (*error
)(callbacks
, "%s: %s: %s",
3106 "dns_master_load", namebuf
,
3107 dns_result_totext(result
));
3110 if (MANYERRS(lctx
, result
))
3111 SETRESULT(lctx
, result
);
3112 else if (result
!= ISC_R_SUCCESS
)
3114 ISC_LIST_UNLINK(*head
, this, link
);
3115 this = ISC_LIST_HEAD(*head
);
3116 } while (this != NULL
);
3117 return (ISC_R_SUCCESS
);
3121 * Returns ISC_TRUE if one of the NS rdata's contains 'owner'.
3124 static isc_boolean_t
3125 is_glue(rdatalist_head_t
*head
, dns_name_t
*owner
) {
3126 dns_rdatalist_t
*this;
3128 isc_region_t region
;
3134 this = ISC_LIST_HEAD(*head
);
3135 while (this != NULL
) {
3136 if (this->type
== dns_rdatatype_ns
)
3138 this = ISC_LIST_NEXT(this, link
);
3143 rdata
= ISC_LIST_HEAD(this->rdata
);
3144 while (rdata
!= NULL
) {
3145 dns_name_init(&name
, NULL
);
3146 dns_rdata_toregion(rdata
, ®ion
);
3147 dns_name_fromregion(&name
, ®ion
);
3148 if (dns_name_compare(&name
, owner
) == 0)
3150 rdata
= ISC_LIST_NEXT(rdata
, link
);
3156 load_quantum(isc_task_t
*task
, isc_event_t
*event
) {
3157 isc_result_t result
;
3158 dns_loadctx_t
*lctx
;
3160 REQUIRE(event
!= NULL
);
3161 lctx
= event
->ev_arg
;
3162 REQUIRE(DNS_LCTX_VALID(lctx
));
3165 result
= ISC_R_CANCELED
;
3167 result
= (lctx
->load
)(lctx
);
3168 if (result
== DNS_R_CONTINUE
) {
3169 event
->ev_arg
= lctx
;
3170 isc_task_send(task
, &event
);
3172 (lctx
->done
)(lctx
->done_arg
, result
);
3173 isc_event_free(&event
);
3174 dns_loadctx_detach(&lctx
);
3179 task_send(dns_loadctx_t
*lctx
) {
3182 event
= isc_event_allocate(lctx
->mctx
, NULL
,
3183 DNS_EVENT_MASTERQUANTUM
,
3184 load_quantum
, lctx
, sizeof(*event
));
3186 return (ISC_R_NOMEMORY
);
3187 isc_task_send(lctx
->task
, &event
);
3188 return (ISC_R_SUCCESS
);
3192 dns_loadctx_cancel(dns_loadctx_t
*lctx
) {
3193 REQUIRE(DNS_LCTX_VALID(lctx
));
3196 lctx
->canceled
= ISC_TRUE
;
3197 UNLOCK(&lctx
->lock
);
3201 dns_master_initrawheader(dns_masterrawheader_t
*header
) {
3202 memset(header
, 0, sizeof(dns_masterrawheader_t
));