1 /* $NetBSD: master.c,v 1.1.1.2 2009/10/25 00:02:30 christos Exp $ */
4 * Copyright (C) 2004-2009 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.
20 /* Id: master.c,v 1.178 2009/09/01 00:22:26 jinmei Exp */
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 (65535 - 12 - 1 - 2 - 2 - 4 - 2)
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 typedef ISC_LIST(dns_rdatalist_t
) rdatalist_head_t
;
98 typedef struct dns_incctx dns_incctx_t
;
101 * Master file load state.
107 dns_masterformat_t format
;
109 dns_rdatacallbacks_t
*callbacks
;
111 dns_loaddonefunc_t done
;
115 isc_result_t (*openfile
)(dns_loadctx_t
*lctx
,
116 const char *filename
);
117 isc_result_t (*load
)(dns_loadctx_t
*lctx
);
119 /* Members specific to the text format: */
121 isc_boolean_t keep_lex
;
122 unsigned int options
;
123 isc_boolean_t ttl_known
;
124 isc_boolean_t default_ttl_known
;
125 isc_boolean_t warn_1035
;
126 isc_boolean_t warn_tcr
;
127 isc_boolean_t warn_sigexpired
;
128 isc_boolean_t seen_include
;
130 isc_uint32_t default_ttl
;
131 dns_rdataclass_t zclass
;
132 dns_fixedname_t fixed_top
;
133 dns_name_t
*top
; /*%< top of zone */
135 /* Members specific to the raw format: */
139 /* Which fixed buffers we are using? */
140 unsigned int loop_cnt
; /*% records per quantum,
142 isc_boolean_t canceled
;
146 isc_uint32_t references
;
152 dns_incctx_t
*parent
;
156 dns_fixedname_t fixed
[NBUFS
]; /* working buffers */
157 unsigned int in_use
[NBUFS
]; /* covert to bitmap? */
162 unsigned int glue_line
;
163 unsigned int current_line
;
166 #define DNS_LCTX_MAGIC ISC_MAGIC('L','c','t','x')
167 #define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
169 #define DNS_AS_STR(t) ((t).value.as_textregion.base)
172 openfile_text(dns_loadctx_t
*lctx
, const char *master_file
);
175 openfile_raw(dns_loadctx_t
*lctx
, const char *master_file
);
178 load_text(dns_loadctx_t
*lctx
);
181 load_raw(dns_loadctx_t
*lctx
);
184 pushfile(const char *master_file
, dns_name_t
*origin
, dns_loadctx_t
*lctx
);
187 commit(dns_rdatacallbacks_t
*, dns_loadctx_t
*, rdatalist_head_t
*,
188 dns_name_t
*, const char *, unsigned int);
191 is_glue(rdatalist_head_t
*, dns_name_t
*);
193 static dns_rdatalist_t
*
194 grow_rdatalist(int, dns_rdatalist_t
*, int, rdatalist_head_t
*,
195 rdatalist_head_t
*, isc_mem_t
*mctx
);
198 grow_rdata(int, dns_rdata_t
*, int, rdatalist_head_t
*, rdatalist_head_t
*,
202 load_quantum(isc_task_t
*task
, isc_event_t
*event
);
205 task_send(dns_loadctx_t
*lctx
);
208 loadctx_destroy(dns_loadctx_t
*lctx
);
210 #define GETTOKEN(lexer, options, token, eol) \
212 result = gettoken(lexer, options, token, eol, callbacks); \
214 case ISC_R_SUCCESS: \
216 case ISC_R_UNEXPECTED: \
217 goto insist_and_cleanup; \
219 if (MANYERRS(lctx, result)) { \
220 SETRESULT(lctx, result); \
222 read_till_eol = ISC_TRUE; \
225 goto log_and_cleanup; \
227 if ((token)->type == isc_tokentype_special) { \
228 result = DNS_R_SYNTAX; \
229 if (MANYERRS(lctx, result)) { \
230 SETRESULT(lctx, result); \
232 read_till_eol = ISC_TRUE; \
235 goto log_and_cleanup; \
241 result = commit(callbacks, lctx, ¤t_list, \
242 ictx->current, source, ictx->current_line); \
243 if (MANYERRS(lctx, result)) { \
244 SETRESULT(lctx, result); \
245 } else if (result != ISC_R_SUCCESS) \
246 goto insist_and_cleanup; \
247 result = commit(callbacks, lctx, &glue_list, \
248 ictx->glue, source, ictx->glue_line); \
249 if (MANYERRS(lctx, result)) { \
250 SETRESULT(lctx, result); \
251 } else if (result != ISC_R_SUCCESS) \
252 goto insist_and_cleanup; \
255 isc_buffer_init(&target, target_mem, target_size); \
256 rdcount_save = rdcount; \
257 rdlcount_save = rdlcount; \
260 #define WARNUNEXPECTEDEOF(lexer) \
262 if (isc_lex_isfile(lexer)) \
263 (*callbacks->warn)(callbacks, \
264 "%s: file does not end with newline", \
270 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE); \
271 if (token.type != isc_tokentype_eol) { \
272 isc_lex_ungettoken(lctx->lex, &token); \
273 result = DNS_R_EXTRATOKEN; \
274 if (MANYERRS(lctx, result)) { \
275 SETRESULT(lctx, result); \
277 read_till_eol = ISC_TRUE; \
279 } else if (result != ISC_R_SUCCESS) \
280 goto log_and_cleanup; \
284 #define MANYERRS(lctx, result) \
285 ((result != ISC_R_SUCCESS) && \
286 (result != ISC_R_IOERROR) && \
287 ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
289 #define SETRESULT(lctx, r) \
291 if ((lctx)->result == ISC_R_SUCCESS) \
292 (lctx)->result = r; \
295 #define LOGITFILE(result, filename) \
296 if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \
297 result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \
298 result == ISC_R_NOPERM) \
299 (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \
300 "dns_master_load", source, line, \
301 filename, dns_result_totext(result)); \
304 #define LOGIT(result) \
305 if (result == ISC_R_NOMEMORY) \
306 (*callbacks->error)(callbacks, "dns_master_load: %s", \
307 dns_result_totext(result)); \
309 (*callbacks->error)(callbacks, "%s: %s:%lu: %s", \
311 source, line, dns_result_totext(result))
314 static unsigned char in_addr_arpa_data
[] = "\007IN-ADDR\004ARPA";
315 static unsigned char in_addr_arpa_offsets
[] = { 0, 8, 13 };
316 static const dns_name_t in_addr_arpa
=
319 in_addr_arpa_data
, 14, 3,
320 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
321 in_addr_arpa_offsets
, NULL
,
322 {(void *)-1, (void *)-1},
326 static unsigned char ip6_int_data
[] = "\003IP6\003INT";
327 static unsigned char ip6_int_offsets
[] = { 0, 4, 8 };
328 static const dns_name_t ip6_int
=
332 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
333 ip6_int_offsets
, NULL
,
334 {(void *)-1, (void *)-1},
338 static unsigned char ip6_arpa_data
[] = "\003IP6\004ARPA";
339 static unsigned char ip6_arpa_offsets
[] = { 0, 4, 9 };
340 static const dns_name_t ip6_arpa
=
343 ip6_arpa_data
, 10, 3,
344 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
345 ip6_arpa_offsets
, NULL
,
346 {(void *)-1, (void *)-1},
351 static inline isc_result_t
352 gettoken(isc_lex_t
*lex
, unsigned int options
, isc_token_t
*token
,
353 isc_boolean_t eol
, dns_rdatacallbacks_t
*callbacks
)
357 options
|= ISC_LEXOPT_EOL
| ISC_LEXOPT_EOF
| ISC_LEXOPT_DNSMULTILINE
|
359 result
= isc_lex_gettoken(lex
, options
, token
);
360 if (result
!= ISC_R_SUCCESS
) {
363 return (ISC_R_NOMEMORY
);
365 (*callbacks
->error
)(callbacks
,
366 "dns_master_load: %s:%lu:"
367 " isc_lex_gettoken() failed: %s",
368 isc_lex_getsourcename(lex
),
369 isc_lex_getsourceline(lex
),
370 isc_result_totext(result
));
376 if (token
->type
== isc_tokentype_eol
||
377 token
->type
== isc_tokentype_eof
) {
378 (*callbacks
->error
)(callbacks
,
379 "dns_master_load: %s:%lu: unexpected end of %s",
380 isc_lex_getsourcename(lex
),
381 isc_lex_getsourceline(lex
),
385 return (ISC_R_UNEXPECTEDEND
);
387 return (ISC_R_SUCCESS
);
392 dns_loadctx_attach(dns_loadctx_t
*source
, dns_loadctx_t
**target
) {
394 REQUIRE(target
!= NULL
&& *target
== NULL
);
395 REQUIRE(DNS_LCTX_VALID(source
));
398 INSIST(source
->references
> 0);
399 source
->references
++;
400 INSIST(source
->references
!= 0); /* Overflow? */
401 UNLOCK(&source
->lock
);
407 dns_loadctx_detach(dns_loadctx_t
**lctxp
) {
409 isc_boolean_t need_destroy
= ISC_FALSE
;
411 REQUIRE(lctxp
!= NULL
);
413 REQUIRE(DNS_LCTX_VALID(lctx
));
416 INSIST(lctx
->references
> 0);
418 if (lctx
->references
== 0)
419 need_destroy
= ISC_TRUE
;
423 loadctx_destroy(lctx
);
428 incctx_destroy(isc_mem_t
*mctx
, dns_incctx_t
*ictx
) {
429 dns_incctx_t
*parent
;
432 parent
= ictx
->parent
;
435 isc_mem_put(mctx
, ictx
, sizeof(*ictx
));
437 if (parent
!= NULL
) {
444 loadctx_destroy(dns_loadctx_t
*lctx
) {
448 REQUIRE(DNS_LCTX_VALID(lctx
));
451 if (lctx
->inc
!= NULL
)
452 incctx_destroy(lctx
->mctx
, lctx
->inc
);
454 if (lctx
->f
!= NULL
) {
455 result
= isc_stdio_close(lctx
->f
);
456 if (result
!= ISC_R_SUCCESS
) {
457 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
458 "isc_stdio_close() failed: %s",
459 isc_result_totext(result
));
463 /* isc_lex_destroy() will close all open streams */
464 if (lctx
->lex
!= NULL
&& !lctx
->keep_lex
)
465 isc_lex_destroy(&lctx
->lex
);
467 if (lctx
->task
!= NULL
)
468 isc_task_detach(&lctx
->task
);
469 DESTROYLOCK(&lctx
->lock
);
471 isc_mem_attach(lctx
->mctx
, &mctx
);
472 isc_mem_detach(&lctx
->mctx
);
473 isc_mem_put(mctx
, lctx
, sizeof(*lctx
));
474 isc_mem_detach(&mctx
);
478 incctx_create(isc_mem_t
*mctx
, dns_name_t
*origin
, dns_incctx_t
**ictxp
) {
483 ictx
= isc_mem_get(mctx
, sizeof(*ictx
));
485 return (ISC_R_NOMEMORY
);
487 for (i
= 0; i
< NBUFS
; i
++) {
488 dns_fixedname_init(&ictx
->fixed
[i
]);
489 ictx
->in_use
[i
] = ISC_FALSE
;
492 ictx
->origin_in_use
= 0;
493 ictx
->origin
= dns_fixedname_name(&ictx
->fixed
[ictx
->origin_in_use
]);
494 ictx
->in_use
[ictx
->origin_in_use
] = ISC_TRUE
;
495 dns_name_toregion(origin
, &r
);
496 dns_name_fromregion(ictx
->origin
, &r
);
499 ictx
->current
= NULL
;
500 ictx
->glue_in_use
= -1;
501 ictx
->current_in_use
= -1;
503 ictx
->drop
= ISC_FALSE
;
505 ictx
->current_line
= 0;
508 return (ISC_R_SUCCESS
);
512 loadctx_create(dns_masterformat_t format
, isc_mem_t
*mctx
,
513 unsigned int options
, isc_uint32_t resign
, dns_name_t
*top
,
514 dns_rdataclass_t zclass
, dns_name_t
*origin
,
515 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
516 dns_loaddonefunc_t done
, void *done_arg
, isc_lex_t
*lex
,
517 dns_loadctx_t
**lctxp
)
522 isc_lexspecials_t specials
;
524 REQUIRE(lctxp
!= NULL
&& *lctxp
== NULL
);
525 REQUIRE(callbacks
!= NULL
);
526 REQUIRE(callbacks
->add
!= NULL
);
527 REQUIRE(callbacks
->error
!= NULL
);
528 REQUIRE(callbacks
->warn
!= NULL
);
529 REQUIRE(mctx
!= NULL
);
530 REQUIRE(dns_name_isabsolute(top
));
531 REQUIRE(dns_name_isabsolute(origin
));
532 REQUIRE((task
== NULL
&& done
== NULL
) ||
533 (task
!= NULL
&& done
!= NULL
));
535 lctx
= isc_mem_get(mctx
, sizeof(*lctx
));
537 return (ISC_R_NOMEMORY
);
538 result
= isc_mutex_init(&lctx
->lock
);
539 if (result
!= ISC_R_SUCCESS
) {
540 isc_mem_put(mctx
, lctx
, sizeof(*lctx
));
545 result
= incctx_create(mctx
, origin
, &lctx
->inc
);
546 if (result
!= ISC_R_SUCCESS
)
549 lctx
->format
= format
;
553 case dns_masterformat_text
:
554 lctx
->openfile
= openfile_text
;
555 lctx
->load
= load_text
;
557 case dns_masterformat_raw
:
558 lctx
->openfile
= openfile_raw
;
559 lctx
->load
= load_raw
;
565 lctx
->keep_lex
= ISC_TRUE
;
568 result
= isc_lex_create(mctx
, TOKENSIZ
, &lctx
->lex
);
569 if (result
!= ISC_R_SUCCESS
)
571 lctx
->keep_lex
= ISC_FALSE
;
572 memset(specials
, 0, sizeof(specials
));
576 isc_lex_setspecials(lctx
->lex
, specials
);
577 isc_lex_setcomments(lctx
->lex
, ISC_LEXCOMMENT_DNSMASTERFILE
);
580 lctx
->ttl_known
= ISC_FALSE
;
582 lctx
->default_ttl_known
= ISC_FALSE
;
583 lctx
->default_ttl
= 0;
584 lctx
->warn_1035
= ISC_TRUE
; /* XXX Argument? */
585 lctx
->warn_tcr
= ISC_TRUE
; /* XXX Argument? */
586 lctx
->warn_sigexpired
= ISC_TRUE
; /* XXX Argument? */
587 lctx
->options
= options
;
588 lctx
->seen_include
= ISC_FALSE
;
589 lctx
->zclass
= zclass
;
590 lctx
->resign
= resign
;
591 lctx
->result
= ISC_R_SUCCESS
;
593 dns_fixedname_init(&lctx
->fixed_top
);
594 lctx
->top
= dns_fixedname_name(&lctx
->fixed_top
);
595 dns_name_toregion(top
, &r
);
596 dns_name_fromregion(lctx
->top
, &r
);
599 lctx
->first
= ISC_TRUE
;
601 lctx
->loop_cnt
= (done
!= NULL
) ? 100 : 0;
602 lctx
->callbacks
= callbacks
;
605 isc_task_attach(task
, &lctx
->task
);
607 lctx
->done_arg
= done_arg
;
608 lctx
->canceled
= ISC_FALSE
;
610 isc_mem_attach(mctx
, &lctx
->mctx
);
611 lctx
->references
= 1; /* Implicit attach. */
612 lctx
->magic
= DNS_LCTX_MAGIC
;
614 return (ISC_R_SUCCESS
);
617 incctx_destroy(mctx
, lctx
->inc
);
619 isc_mem_put(mctx
, lctx
, sizeof(*lctx
));
623 static const char *hex
= "0123456789abcdef0123456789ABCDEF";
626 * Convert value into a nibble sequence from least significant to most
627 * significant nibble. Zero fill upper most significant nibbles if
628 * required to make the width.
630 * Returns the number of characters that should have been written without
631 * counting the terminating NUL.
634 nibbles(char *numbuf
, size_t length
, unsigned int width
, char mode
, int value
) {
635 unsigned int count
= 0;
638 * This reserve space for the NUL string terminator.
645 char val
= hex
[(value
& 0x0f) + ((mode
== 'n') ? 0 : 16)];
656 * If width is non zero then we need to add a label seperator.
657 * If value is non zero then we need to add another label and
658 * that requires a label seperator.
660 if (width
> 0 || value
!= 0) {
670 } while (value
!= 0 || width
> 0);
675 genname(char *name
, int it
, char *buffer
, size_t length
) {
676 char fmt
[sizeof("%04000000000d")];
684 isc_boolean_t nibblemode
;
689 while (*name
!= '\0') {
694 return (ISC_R_NOSPACE
);
696 isc_textregion_consume(&r
, 1);
699 nibblemode
= ISC_FALSE
;
701 /* Get format specifier. */
703 n
= sscanf(name
, "{%d,%u,%1[doxXnN]}",
704 &delta
, &width
, mode
);
709 n
= snprintf(fmt
, sizeof(fmt
),
713 if (mode
[0] == 'n' || mode
[0] == 'N')
714 nibblemode
= ISC_TRUE
;
715 n
= snprintf(fmt
, sizeof(fmt
),
716 "%%0%u%c", width
, mode
[0]);
719 return (DNS_R_SYNTAX
);
721 if (n
>= sizeof(fmt
))
722 return (ISC_R_NOSPACE
);
723 /* Skip past closing brace. */
724 while (*name
!= '\0' && *name
++ != '}')
728 n
= nibbles(numbuf
, sizeof(numbuf
), width
,
729 mode
[0], it
+ delta
);
731 n
= snprintf(numbuf
, sizeof(numbuf
), fmt
,
733 if (n
>= sizeof(numbuf
))
734 return (ISC_R_NOSPACE
);
736 while (*cp
!= '\0') {
738 return (ISC_R_NOSPACE
);
740 isc_textregion_consume(&r
, 1);
742 } else if (*name
== '\\') {
744 return (ISC_R_NOSPACE
);
746 isc_textregion_consume(&r
, 1);
750 return (ISC_R_NOSPACE
);
752 isc_textregion_consume(&r
, 1);
755 return (ISC_R_NOSPACE
);
757 isc_textregion_consume(&r
, 1);
761 return (ISC_R_NOSPACE
);
763 return (ISC_R_SUCCESS
);
767 openfile_text(dns_loadctx_t
*lctx
, const char *master_file
) {
768 return (isc_lex_openfile(lctx
->lex
, master_file
));
772 openfile_raw(dns_loadctx_t
*lctx
, const char *master_file
) {
775 result
= isc_stdio_open(master_file
, "r", &lctx
->f
);
776 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_FILENOTFOUND
) {
777 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
778 "isc_stdio_open() failed: %s",
779 isc_result_totext(result
));
786 generate(dns_loadctx_t
*lctx
, char *range
, char *lhs
, char *gtype
, char *rhs
,
787 const char *source
, unsigned int line
)
789 char *target_mem
= NULL
;
792 dns_fixedname_t ownerfixed
;
794 dns_rdata_t rdata
= DNS_RDATA_INIT
;
795 dns_rdatacallbacks_t
*callbacks
;
796 dns_rdatalist_t rdatalist
;
797 dns_rdatatype_t type
;
798 rdatalist_head_t head
;
800 int target_size
= MINTSIZ
; /* only one rdata at a time */
805 unsigned int start
, stop
, step
, i
;
809 callbacks
= lctx
->callbacks
;
810 dns_fixedname_init(&ownerfixed
);
811 owner
= dns_fixedname_name(&ownerfixed
);
814 target_mem
= isc_mem_get(lctx
->mctx
, target_size
);
815 rhsbuf
= isc_mem_get(lctx
->mctx
, DNS_MASTER_RHS
);
816 lhsbuf
= isc_mem_get(lctx
->mctx
, DNS_MASTER_LHS
);
817 if (target_mem
== NULL
|| rhsbuf
== NULL
|| lhsbuf
== NULL
) {
818 result
= ISC_R_NOMEMORY
;
821 isc_buffer_init(&target
, target_mem
, target_size
);
823 n
= sscanf(range
, "%u-%u/%u", &start
, &stop
, &step
);
824 if (n
< 2 || stop
< start
) {
825 (*callbacks
->error
)(callbacks
,
826 "%s: %s:%lu: invalid range '%s'",
827 "$GENERATE", source
, line
, range
);
828 result
= DNS_R_SYNTAX
;
838 r
.length
= strlen(gtype
);
839 result
= dns_rdatatype_fromtext(&type
, &r
);
840 if (result
!= ISC_R_SUCCESS
) {
841 (*callbacks
->error
)(callbacks
,
842 "%s: %s:%lu: unknown RR type '%s'",
843 "$GENERATE", source
, line
, gtype
);
847 ISC_LIST_INIT(rdatalist
.rdata
);
848 ISC_LINK_INIT(&rdatalist
, link
);
849 for (i
= start
; i
<= stop
; i
+= step
) {
850 result
= genname(lhs
, i
, lhsbuf
, DNS_MASTER_LHS
);
851 if (result
!= ISC_R_SUCCESS
)
853 result
= genname(rhs
, i
, rhsbuf
, DNS_MASTER_RHS
);
854 if (result
!= ISC_R_SUCCESS
)
857 isc_buffer_init(&buffer
, lhsbuf
, strlen(lhsbuf
));
858 isc_buffer_add(&buffer
, strlen(lhsbuf
));
859 isc_buffer_setactive(&buffer
, strlen(lhsbuf
));
860 result
= dns_name_fromtext(owner
, &buffer
, ictx
->origin
,
862 if (result
!= ISC_R_SUCCESS
)
865 if ((lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
866 (lctx
->options
& DNS_MASTER_SLAVE
) == 0 &&
867 (lctx
->options
& DNS_MASTER_KEY
) == 0 &&
868 !dns_name_issubdomain(owner
, lctx
->top
))
870 char namebuf
[DNS_NAME_FORMATSIZE
];
871 dns_name_format(owner
, namebuf
, sizeof(namebuf
));
873 * Ignore out-of-zone data.
875 (*callbacks
->warn
)(callbacks
,
877 "ignoring out-of-zone data (%s)",
878 source
, line
, namebuf
);
882 isc_buffer_init(&buffer
, rhsbuf
, strlen(rhsbuf
));
883 isc_buffer_add(&buffer
, strlen(rhsbuf
));
884 isc_buffer_setactive(&buffer
, strlen(rhsbuf
));
886 result
= isc_lex_openbuffer(lctx
->lex
, &buffer
);
887 if (result
!= ISC_R_SUCCESS
)
890 isc_buffer_init(&target
, target_mem
, target_size
);
891 result
= dns_rdata_fromtext(&rdata
, lctx
->zclass
, type
,
892 lctx
->lex
, ictx
->origin
, 0,
893 lctx
->mctx
, &target
, callbacks
);
894 RUNTIME_CHECK(isc_lex_close(lctx
->lex
) == ISC_R_SUCCESS
);
895 if (result
!= ISC_R_SUCCESS
)
898 rdatalist
.type
= type
;
899 rdatalist
.covers
= 0;
900 rdatalist
.rdclass
= lctx
->zclass
;
901 rdatalist
.ttl
= lctx
->ttl
;
902 ISC_LIST_PREPEND(head
, &rdatalist
, link
);
903 ISC_LIST_APPEND(rdatalist
.rdata
, &rdata
, link
);
904 result
= commit(callbacks
, lctx
, &head
, owner
, source
, line
);
905 ISC_LIST_UNLINK(rdatalist
.rdata
, &rdata
, link
);
906 if (result
!= ISC_R_SUCCESS
)
908 dns_rdata_reset(&rdata
);
910 result
= ISC_R_SUCCESS
;
914 if (result
== ISC_R_NOMEMORY
)
915 (*callbacks
->error
)(callbacks
, "$GENERATE: %s",
916 dns_result_totext(result
));
918 (*callbacks
->error
)(callbacks
, "$GENERATE: %s:%lu: %s",
919 source
, line
, dns_result_totext(result
));
922 INSIST(result
!= ISC_R_SUCCESS
);
925 if (target_mem
!= NULL
)
926 isc_mem_put(lctx
->mctx
, target_mem
, target_size
);
928 isc_mem_put(lctx
->mctx
, lhsbuf
, DNS_MASTER_LHS
);
930 isc_mem_put(lctx
->mctx
, rhsbuf
, DNS_MASTER_RHS
);
935 limit_ttl(dns_rdatacallbacks_t
*callbacks
, const char *source
, unsigned int line
,
938 if (*ttlp
> 0x7fffffffUL
) {
939 (callbacks
->warn
)(callbacks
,
941 "$TTL %lu > MAXTTL, "
951 check_ns(dns_loadctx_t
*lctx
, isc_token_t
*token
, const char *source
,
955 isc_result_t result
= ISC_R_SUCCESS
;
956 void (*callback
)(struct dns_rdatacallbacks
*, const char *, ...);
958 if ((lctx
->options
& DNS_MASTER_FATALNS
) != 0)
959 callback
= lctx
->callbacks
->error
;
961 callback
= lctx
->callbacks
->warn
;
963 if (token
->type
== isc_tokentype_string
) {
965 struct in6_addr addr6
;
967 tmp
= isc_mem_strdup(lctx
->mctx
, DNS_AS_STR(*token
));
969 return (ISC_R_NOMEMORY
);
971 * Catch both "1.2.3.4" and "1.2.3.4."
973 if (tmp
[strlen(tmp
) - 1] == '.')
974 tmp
[strlen(tmp
) - 1] = '\0';
975 if (inet_aton(tmp
, &addr
) == 1 ||
976 inet_pton(AF_INET6
, tmp
, &addr6
) == 1)
977 result
= DNS_R_NSISADDRESS
;
979 if (result
!= ISC_R_SUCCESS
)
980 (*callback
)(lctx
->callbacks
, "%s:%lu: NS record '%s' "
981 "appears to be an address",
982 source
, line
, DNS_AS_STR(*token
));
984 isc_mem_free(lctx
->mctx
, tmp
);
989 check_wildcard(dns_incctx_t
*ictx
, const char *source
, unsigned long line
,
990 dns_rdatacallbacks_t
*callbacks
)
994 name
= (ictx
->glue
!= NULL
) ? ictx
->glue
: ictx
->current
;
995 if (dns_name_internalwildcard(name
)) {
996 char namebuf
[DNS_NAME_FORMATSIZE
];
998 dns_name_format(name
, namebuf
, sizeof(namebuf
));
999 (*callbacks
->warn
)(callbacks
, "%s:%lu: warning: ownername "
1000 "'%s' contains an non-terminal wildcard",
1001 source
, line
, namebuf
);
1006 load_text(dns_loadctx_t
*lctx
) {
1007 dns_rdataclass_t rdclass
;
1008 dns_rdatatype_t type
, covers
;
1009 isc_uint32_t ttl_offset
= 0;
1010 dns_name_t
*new_name
;
1011 isc_boolean_t current_has_delegation
= ISC_FALSE
;
1012 isc_boolean_t done
= ISC_FALSE
;
1013 isc_boolean_t finish_origin
= ISC_FALSE
;
1014 isc_boolean_t finish_include
= ISC_FALSE
;
1015 isc_boolean_t read_till_eol
= ISC_FALSE
;
1016 isc_boolean_t initialws
;
1017 char *include_file
= NULL
;
1019 isc_result_t result
= ISC_R_UNEXPECTED
;
1020 rdatalist_head_t glue_list
;
1021 rdatalist_head_t current_list
;
1022 dns_rdatalist_t
*this;
1023 dns_rdatalist_t
*rdatalist
= NULL
;
1024 dns_rdatalist_t
*new_rdatalist
;
1026 int rdlcount_save
= 0;
1027 int rdatalist_size
= 0;
1028 isc_buffer_t buffer
;
1029 isc_buffer_t target
;
1030 isc_buffer_t target_ft
;
1031 isc_buffer_t target_save
;
1032 dns_rdata_t
*rdata
= NULL
;
1033 dns_rdata_t
*new_rdata
;
1035 int rdcount_save
= 0;
1037 unsigned char *target_mem
= NULL
;
1038 int target_size
= TSIZ
;
1040 unsigned int loop_cnt
= 0;
1042 dns_rdatacallbacks_t
*callbacks
;
1048 const char *source
= "";
1049 unsigned long line
= 0;
1050 isc_boolean_t explicit_ttl
;
1052 char classname1
[DNS_RDATACLASS_FORMATSIZE
];
1053 char classname2
[DNS_RDATACLASS_FORMATSIZE
];
1054 unsigned int options
= 0;
1056 REQUIRE(DNS_LCTX_VALID(lctx
));
1057 callbacks
= lctx
->callbacks
;
1061 ISC_LIST_INIT(glue_list
);
1062 ISC_LIST_INIT(current_list
);
1064 isc_stdtime_get(&now
);
1067 * Allocate target_size of buffer space. This is greater than twice
1068 * the maximum individual RR data size.
1070 target_mem
= isc_mem_get(mctx
, target_size
);
1071 if (target_mem
== NULL
) {
1072 result
= ISC_R_NOMEMORY
;
1073 goto log_and_cleanup
;
1075 isc_buffer_init(&target
, target_mem
, target_size
);
1076 target_save
= target
;
1078 if ((lctx
->options
& DNS_MASTER_CHECKNAMES
) != 0)
1079 options
|= DNS_RDATA_CHECKNAMES
;
1080 if ((lctx
->options
& DNS_MASTER_CHECKNAMESFAIL
) != 0)
1081 options
|= DNS_RDATA_CHECKNAMESFAIL
;
1082 if ((lctx
->options
& DNS_MASTER_CHECKMX
) != 0)
1083 options
|= DNS_RDATA_CHECKMX
;
1084 if ((lctx
->options
& DNS_MASTER_CHECKMXFAIL
) != 0)
1085 options
|= DNS_RDATA_CHECKMXFAIL
;
1086 source
= isc_lex_getsourcename(lctx
->lex
);
1088 initialws
= ISC_FALSE
;
1089 line
= isc_lex_getsourceline(lctx
->lex
);
1090 GETTOKEN(lctx
->lex
, ISC_LEXOPT_INITIALWS
| ISC_LEXOPT_QSTRING
,
1092 line
= isc_lex_getsourceline(lctx
->lex
);
1094 if (token
.type
== isc_tokentype_eof
) {
1096 WARNUNEXPECTEDEOF(lctx
->lex
);
1097 /* Pop the include stack? */
1098 if (ictx
->parent
!= NULL
) {
1100 lctx
->inc
= ictx
->parent
;
1101 ictx
->parent
= NULL
;
1102 incctx_destroy(lctx
->mctx
, ictx
);
1103 RUNTIME_CHECK(isc_lex_close(lctx
->lex
) == ISC_R_SUCCESS
);
1104 line
= isc_lex_getsourceline(lctx
->lex
);
1105 source
= isc_lex_getsourcename(lctx
->lex
);
1114 if (token
.type
== isc_tokentype_eol
) {
1115 read_till_eol
= ISC_FALSE
;
1116 continue; /* blank line */
1122 if (token
.type
== isc_tokentype_initialws
) {
1124 * Still working on the same name.
1126 initialws
= ISC_TRUE
;
1127 } else if (token
.type
== isc_tokentype_string
||
1128 token
.type
== isc_tokentype_qstring
) {
1133 * "$ORIGIN" and "$INCLUDE" can both take domain names.
1134 * The processing of "$ORIGIN" and "$INCLUDE" extends
1135 * across the normal domain name processing.
1138 if (strcasecmp(DNS_AS_STR(token
), "$ORIGIN") == 0) {
1139 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1140 finish_origin
= ISC_TRUE
;
1141 } else if (strcasecmp(DNS_AS_STR(token
),
1143 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1145 dns_ttl_fromtext(&token
.value
.as_textregion
,
1147 if (MANYERRS(lctx
, result
)) {
1148 SETRESULT(lctx
, result
);
1150 } else if (result
!= ISC_R_SUCCESS
)
1151 goto insist_and_cleanup
;
1152 limit_ttl(callbacks
, source
, line
, &lctx
->ttl
);
1153 lctx
->default_ttl
= lctx
->ttl
;
1154 lctx
->default_ttl_known
= ISC_TRUE
;
1157 } else if (strcasecmp(DNS_AS_STR(token
),
1160 if ((lctx
->options
& DNS_MASTER_NOINCLUDE
)
1163 (callbacks
->error
)(callbacks
,
1164 "%s: %s:%lu: $INCLUDE not allowed",
1167 result
= DNS_R_REFUSED
;
1168 goto insist_and_cleanup
;
1170 if (ttl_offset
!= 0) {
1171 (callbacks
->error
)(callbacks
,
1172 "%s: %s:%lu: $INCLUDE "
1173 "may not be used with $DATE",
1176 result
= DNS_R_SYNTAX
;
1177 goto insist_and_cleanup
;
1179 GETTOKEN(lctx
->lex
, ISC_LEXOPT_QSTRING
, &token
,
1181 if (include_file
!= NULL
)
1182 isc_mem_free(mctx
, include_file
);
1183 include_file
= isc_mem_strdup(mctx
,
1185 if (include_file
== NULL
) {
1186 result
= ISC_R_NOMEMORY
;
1187 goto log_and_cleanup
;
1189 GETTOKEN(lctx
->lex
, 0, &token
, ISC_TRUE
);
1191 if (token
.type
== isc_tokentype_eol
||
1192 token
.type
== isc_tokentype_eof
) {
1193 if (token
.type
== isc_tokentype_eof
)
1194 WARNUNEXPECTEDEOF(lctx
->lex
);
1195 isc_lex_ungettoken(lctx
->lex
, &token
);
1199 result
= pushfile(include_file
,
1200 ictx
->origin
, lctx
);
1201 if (MANYERRS(lctx
, result
)) {
1202 SETRESULT(lctx
, result
);
1203 LOGITFILE(result
, include_file
);
1205 } else if (result
!= ISC_R_SUCCESS
) {
1206 LOGITFILE(result
, include_file
);
1207 goto insist_and_cleanup
;
1210 line
= isc_lex_getsourceline(lctx
->lex
);
1212 isc_lex_getsourcename(lctx
->lex
);
1216 * There is an origin field. Fall through
1217 * to domain name processing code and do
1218 * the actual inclusion later.
1220 finish_include
= ISC_TRUE
;
1221 } else if (strcasecmp(DNS_AS_STR(token
),
1223 isc_int64_t dump_time64
;
1224 isc_stdtime_t dump_time
, current_time
;
1225 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1226 isc_stdtime_get(¤t_time
);
1227 result
= dns_time64_fromtext(DNS_AS_STR(token
),
1229 if (MANYERRS(lctx
, result
)) {
1230 SETRESULT(lctx
, result
);
1233 } else if (result
!= ISC_R_SUCCESS
)
1234 goto log_and_cleanup
;
1235 dump_time
= (isc_stdtime_t
)dump_time64
;
1236 if (dump_time
!= dump_time64
) {
1237 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1238 "%s: %s:%lu: $DATE outside epoch",
1239 "dns_master_load", source
, line
);
1240 result
= ISC_R_UNEXPECTED
;
1241 goto insist_and_cleanup
;
1243 if (dump_time
> current_time
) {
1244 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1246 "$DATE in future, using current date",
1247 "dns_master_load", source
, line
);
1248 dump_time
= current_time
;
1250 ttl_offset
= current_time
- dump_time
;
1253 } else if (strcasecmp(DNS_AS_STR(token
),
1254 "$GENERATE") == 0) {
1259 isc_mem_free(mctx
, range
);
1261 isc_mem_free(mctx
, lhs
);
1263 isc_mem_free(mctx
, gtype
);
1265 isc_mem_free(mctx
, rhs
);
1266 range
= lhs
= gtype
= rhs
= NULL
;
1268 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1269 range
= isc_mem_strdup(mctx
,
1271 if (range
== NULL
) {
1272 result
= ISC_R_NOMEMORY
;
1273 goto log_and_cleanup
;
1276 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1277 lhs
= isc_mem_strdup(mctx
, DNS_AS_STR(token
));
1279 result
= ISC_R_NOMEMORY
;
1280 goto log_and_cleanup
;
1283 explicit_ttl
= ISC_FALSE
;
1285 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1286 if (dns_rdataclass_fromtext(&rdclass
,
1287 &token
.value
.as_textregion
)
1289 GETTOKEN(lctx
->lex
, 0, &token
,
1293 if (dns_ttl_fromtext(&token
.value
.as_textregion
,
1296 limit_ttl(callbacks
, source
, line
,
1298 lctx
->ttl_known
= ISC_TRUE
;
1299 explicit_ttl
= ISC_TRUE
;
1300 GETTOKEN(lctx
->lex
, 0, &token
,
1305 dns_rdataclass_fromtext(&rdclass
,
1306 &token
.value
.as_textregion
)
1308 GETTOKEN(lctx
->lex
, 0, &token
,
1311 gtype
= isc_mem_strdup(mctx
,
1313 if (gtype
== NULL
) {
1314 result
= ISC_R_NOMEMORY
;
1315 goto log_and_cleanup
;
1318 GETTOKEN(lctx
->lex
, ISC_LEXOPT_QSTRING
,
1320 rhs
= isc_mem_strdup(mctx
, DNS_AS_STR(token
));
1322 result
= ISC_R_NOMEMORY
;
1323 goto log_and_cleanup
;
1325 if (!lctx
->ttl_known
&&
1326 !lctx
->default_ttl_known
) {
1327 (*callbacks
->error
)(callbacks
,
1328 "%s: %s:%lu: no TTL specified",
1329 "dns_master_load", source
, line
);
1330 result
= DNS_R_NOTTL
;
1331 if (MANYERRS(lctx
, result
)) {
1332 SETRESULT(lctx
, result
);
1334 } else if (result
!= ISC_R_SUCCESS
)
1335 goto insist_and_cleanup
;
1336 } else if (!explicit_ttl
&&
1337 lctx
->default_ttl_known
) {
1338 lctx
->ttl
= lctx
->default_ttl
;
1341 * If the class specified does not match the
1342 * zone's class print out a error message and
1345 if (rdclass
!= 0 && rdclass
!= lctx
->zclass
) {
1348 result
= generate(lctx
, range
, lhs
, gtype
, rhs
,
1350 if (MANYERRS(lctx
, result
)) {
1351 SETRESULT(lctx
, result
);
1352 } else if (result
!= ISC_R_SUCCESS
)
1353 goto insist_and_cleanup
;
1356 } else if (strncasecmp(DNS_AS_STR(token
),
1358 (callbacks
->error
)(callbacks
,
1360 "unknown $ directive '%s'",
1361 "dns_master_load", source
, line
,
1363 result
= DNS_R_SYNTAX
;
1364 if (MANYERRS(lctx
, result
)) {
1365 SETRESULT(lctx
, result
);
1366 } else if (result
!= ISC_R_SUCCESS
)
1367 goto insist_and_cleanup
;
1371 * Normal processing resumes.
1373 * Find a free name buffer.
1375 for (new_in_use
= 0; new_in_use
< NBUFS
; new_in_use
++)
1376 if (!ictx
->in_use
[new_in_use
])
1378 INSIST(new_in_use
< NBUFS
);
1379 dns_fixedname_init(&ictx
->fixed
[new_in_use
]);
1380 new_name
= dns_fixedname_name(&ictx
->fixed
[new_in_use
]);
1381 isc_buffer_init(&buffer
, token
.value
.as_region
.base
,
1382 token
.value
.as_region
.length
);
1383 isc_buffer_add(&buffer
, token
.value
.as_region
.length
);
1384 isc_buffer_setactive(&buffer
,
1385 token
.value
.as_region
.length
);
1386 result
= dns_name_fromtext(new_name
, &buffer
,
1387 ictx
->origin
, 0, NULL
);
1388 if (MANYERRS(lctx
, result
)) {
1389 SETRESULT(lctx
, result
);
1391 read_till_eol
= ISC_TRUE
;
1393 } else if (result
!= ISC_R_SUCCESS
)
1394 goto log_and_cleanup
;
1397 * Finish $ORIGIN / $INCLUDE processing if required.
1399 if (finish_origin
) {
1400 if (ictx
->origin_in_use
!= -1)
1401 ictx
->in_use
[ictx
->origin_in_use
] =
1403 ictx
->origin_in_use
= new_in_use
;
1404 ictx
->in_use
[ictx
->origin_in_use
] = ISC_TRUE
;
1405 ictx
->origin
= new_name
;
1406 finish_origin
= ISC_FALSE
;
1410 if (finish_include
) {
1411 finish_include
= ISC_FALSE
;
1412 result
= pushfile(include_file
, new_name
, lctx
);
1413 if (MANYERRS(lctx
, result
)) {
1414 SETRESULT(lctx
, result
);
1415 LOGITFILE(result
, include_file
);
1417 } else if (result
!= ISC_R_SUCCESS
) {
1418 LOGITFILE(result
, include_file
);
1419 goto insist_and_cleanup
;
1422 line
= isc_lex_getsourceline(lctx
->lex
);
1423 source
= isc_lex_getsourcename(lctx
->lex
);
1428 * "$" Processing Finished
1432 * If we are processing glue and the new name does
1433 * not match the current glue name, commit the glue
1434 * and pop stacks leaving us in 'normal' processing
1435 * state. Linked lists are undone by commit().
1437 if (ictx
->glue
!= NULL
&&
1438 dns_name_compare(ictx
->glue
, new_name
) != 0) {
1439 result
= commit(callbacks
, lctx
, &glue_list
,
1442 if (MANYERRS(lctx
, result
)) {
1443 SETRESULT(lctx
, result
);
1444 } else if (result
!= ISC_R_SUCCESS
)
1445 goto insist_and_cleanup
;
1446 if (ictx
->glue_in_use
!= -1)
1447 ictx
->in_use
[ictx
->glue_in_use
] =
1449 ictx
->glue_in_use
= -1;
1451 rdcount
= rdcount_save
;
1452 rdlcount
= rdlcount_save
;
1453 target
= target_save
;
1457 * If we are in 'normal' processing state and the new
1458 * name does not match the current name, see if the
1459 * new name is for glue and treat it as such,
1460 * otherwise we have a new name so commit what we
1463 if ((ictx
->glue
== NULL
) && (ictx
->current
== NULL
||
1464 dns_name_compare(ictx
->current
, new_name
) != 0)) {
1465 if (current_has_delegation
&&
1466 is_glue(¤t_list
, new_name
)) {
1467 rdcount_save
= rdcount
;
1468 rdlcount_save
= rdlcount
;
1469 target_save
= target
;
1470 ictx
->glue
= new_name
;
1471 ictx
->glue_in_use
= new_in_use
;
1472 ictx
->in_use
[ictx
->glue_in_use
] =
1475 result
= commit(callbacks
, lctx
,
1479 ictx
->current_line
);
1480 if (MANYERRS(lctx
, result
)) {
1481 SETRESULT(lctx
, result
);
1482 } else if (result
!= ISC_R_SUCCESS
)
1483 goto insist_and_cleanup
;
1486 if (ictx
->current_in_use
!= -1)
1487 ictx
->in_use
[ictx
->current_in_use
] =
1489 ictx
->current_in_use
= new_in_use
;
1490 ictx
->in_use
[ictx
->current_in_use
] =
1492 ictx
->current
= new_name
;
1493 current_has_delegation
= ISC_FALSE
;
1494 isc_buffer_init(&target
, target_mem
,
1498 * Check for internal wildcards.
1500 if ((lctx
->options
& DNS_MASTER_CHECKWILDCARD
)
1502 check_wildcard(ictx
, source
, line
,
1506 if ((lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
1507 (lctx
->options
& DNS_MASTER_SLAVE
) == 0 &&
1508 (lctx
->options
& DNS_MASTER_KEY
) == 0 &&
1509 !dns_name_issubdomain(new_name
, lctx
->top
))
1511 char namebuf
[DNS_NAME_FORMATSIZE
];
1512 dns_name_format(new_name
, namebuf
,
1515 * Ignore out-of-zone data.
1517 (*callbacks
->warn
)(callbacks
,
1519 "ignoring out-of-zone data (%s)",
1520 source
, line
, namebuf
);
1521 ictx
->drop
= ISC_TRUE
;
1523 ictx
->drop
= ISC_FALSE
;
1525 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1526 "%s:%lu: isc_lex_gettoken() returned "
1527 "unexpected token type (%d)",
1528 source
, line
, token
.type
);
1529 result
= ISC_R_UNEXPECTED
;
1530 if (MANYERRS(lctx
, result
)) {
1531 SETRESULT(lctx
, result
);
1534 } else if (result
!= ISC_R_SUCCESS
)
1535 goto insist_and_cleanup
;
1539 * Find TTL, class and type. Both TTL and class are optional
1540 * and may occur in any order if they exist. TTL and class
1541 * come before type which must exist.
1543 * [<TTL>] [<class>] <type> <RDATA>
1544 * [<class>] [<TTL>] <type> <RDATA>
1550 GETTOKEN(lctx
->lex
, 0, &token
, initialws
);
1553 if (token
.type
== isc_tokentype_eol
) {
1554 read_till_eol
= ISC_FALSE
;
1555 continue; /* blank line */
1558 if (token
.type
== isc_tokentype_eof
) {
1559 WARNUNEXPECTEDEOF(lctx
->lex
);
1560 read_till_eol
= ISC_FALSE
;
1561 isc_lex_ungettoken(lctx
->lex
, &token
);
1565 if (ictx
->current
== NULL
) {
1566 (*callbacks
->error
)(callbacks
,
1567 "%s:%lu: no current owner name",
1569 result
= DNS_R_NOOWNER
;
1570 if (MANYERRS(lctx
, result
)) {
1571 SETRESULT(lctx
, result
);
1572 read_till_eol
= ISC_TRUE
;
1574 } else if (result
!= ISC_R_SUCCESS
)
1575 goto insist_and_cleanup
;
1579 if (dns_rdataclass_fromtext(&rdclass
,
1580 &token
.value
.as_textregion
)
1582 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1584 explicit_ttl
= ISC_FALSE
;
1585 if (dns_ttl_fromtext(&token
.value
.as_textregion
, &lctx
->ttl
)
1587 limit_ttl(callbacks
, source
, line
, &lctx
->ttl
);
1588 explicit_ttl
= ISC_TRUE
;
1589 lctx
->ttl_known
= ISC_TRUE
;
1590 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1593 if (token
.type
!= isc_tokentype_string
) {
1594 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1595 "isc_lex_gettoken() returned unexpected token type");
1596 result
= ISC_R_UNEXPECTED
;
1597 if (MANYERRS(lctx
, result
)) {
1598 SETRESULT(lctx
, result
);
1599 read_till_eol
= ISC_TRUE
;
1601 } else if (result
!= ISC_R_SUCCESS
)
1602 goto insist_and_cleanup
;
1606 dns_rdataclass_fromtext(&rdclass
,
1607 &token
.value
.as_textregion
)
1609 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1611 if (token
.type
!= isc_tokentype_string
) {
1612 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1613 "isc_lex_gettoken() returned unexpected token type");
1614 result
= ISC_R_UNEXPECTED
;
1615 if (MANYERRS(lctx
, result
)) {
1616 SETRESULT(lctx
, result
);
1617 read_till_eol
= ISC_TRUE
;
1619 } else if (result
!= ISC_R_SUCCESS
)
1620 goto insist_and_cleanup
;
1623 result
= dns_rdatatype_fromtext(&type
,
1624 &token
.value
.as_textregion
);
1625 if (result
!= ISC_R_SUCCESS
) {
1626 (*callbacks
->warn
)(callbacks
,
1627 "%s:%lu: unknown RR type '%.*s'",
1629 token
.value
.as_textregion
.length
,
1630 token
.value
.as_textregion
.base
);
1631 if (MANYERRS(lctx
, result
)) {
1632 SETRESULT(lctx
, result
);
1633 read_till_eol
= ISC_TRUE
;
1635 } else if (result
!= ISC_R_SUCCESS
)
1636 goto insist_and_cleanup
;
1640 * If the class specified does not match the zone's class
1641 * print out a error message and exit.
1643 if (rdclass
!= 0 && rdclass
!= lctx
->zclass
) {
1646 dns_rdataclass_format(rdclass
, classname1
,
1647 sizeof(classname1
));
1648 dns_rdataclass_format(lctx
->zclass
, classname2
,
1649 sizeof(classname2
));
1650 (*callbacks
->error
)(callbacks
,
1651 "%s:%lu: class '%s' != "
1654 classname1
, classname2
);
1655 result
= DNS_R_BADCLASS
;
1656 if (MANYERRS(lctx
, result
)) {
1657 SETRESULT(lctx
, result
);
1658 read_till_eol
= ISC_TRUE
;
1660 } else if (result
!= ISC_R_SUCCESS
)
1661 goto insist_and_cleanup
;
1664 if (type
== dns_rdatatype_ns
&& ictx
->glue
== NULL
)
1665 current_has_delegation
= ISC_TRUE
;
1668 * RFC1123: MD and MF are not allowed to be loaded from
1671 if ((lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
1672 (lctx
->options
& DNS_MASTER_SLAVE
) == 0 &&
1673 (type
== dns_rdatatype_md
|| type
== dns_rdatatype_mf
)) {
1674 char typename
[DNS_RDATATYPE_FORMATSIZE
];
1676 result
= DNS_R_OBSOLETE
;
1678 dns_rdatatype_format(type
, typename
, sizeof(typename
));
1679 (*callbacks
->error
)(callbacks
,
1680 "%s:%lu: %s '%s': %s",
1683 dns_result_totext(result
));
1684 if (MANYERRS(lctx
, result
)) {
1685 SETRESULT(lctx
, result
);
1687 goto insist_and_cleanup
;
1691 * Find a rdata structure.
1693 if (rdcount
== rdata_size
) {
1694 new_rdata
= grow_rdata(rdata_size
+ RDSZ
, rdata
,
1695 rdata_size
, ¤t_list
,
1697 if (new_rdata
== NULL
) {
1698 result
= ISC_R_NOMEMORY
;
1699 goto log_and_cleanup
;
1706 * Peek at the NS record.
1708 if (type
== dns_rdatatype_ns
&&
1709 lctx
->zclass
== dns_rdataclass_in
&&
1710 (lctx
->options
& DNS_MASTER_CHECKNS
) != 0) {
1712 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1713 result
= check_ns(lctx
, &token
, source
, line
);
1714 isc_lex_ungettoken(lctx
->lex
, &token
);
1715 if ((lctx
->options
& DNS_MASTER_FATALNS
) != 0) {
1716 if (MANYERRS(lctx
, result
)) {
1717 SETRESULT(lctx
, result
);
1718 } else if (result
!= ISC_R_SUCCESS
)
1719 goto insist_and_cleanup
;
1726 options
&= ~DNS_RDATA_CHECKREVERSE
;
1727 if ((lctx
->options
& DNS_MASTER_CHECKNAMES
) != 0) {
1731 name
= (ictx
->glue
!= NULL
) ? ictx
->glue
:
1733 ok
= dns_rdata_checkowner(name
, lctx
->zclass
, type
,
1736 char namebuf
[DNS_NAME_FORMATSIZE
];
1738 dns_name_format(name
, namebuf
, sizeof(namebuf
));
1739 result
= DNS_R_BADOWNERNAME
;
1740 desc
= dns_result_totext(result
);
1741 if ((lctx
->options
& DNS_MASTER_CHECKNAMESFAIL
) != 0) {
1742 (*callbacks
->error
)(callbacks
,
1746 if (MANYERRS(lctx
, result
)) {
1747 SETRESULT(lctx
, result
);
1748 } else if (result
!= ISC_R_SUCCESS
)
1751 (*callbacks
->warn
)(callbacks
,
1757 if (type
== dns_rdatatype_ptr
&&
1758 (dns_name_issubdomain(name
, &in_addr_arpa
) ||
1759 dns_name_issubdomain(name
, &ip6_arpa
) ||
1760 dns_name_issubdomain(name
, &ip6_int
)))
1761 options
|= DNS_RDATA_CHECKREVERSE
;
1765 * Read rdata contents.
1767 dns_rdata_init(&rdata
[rdcount
]);
1769 result
= dns_rdata_fromtext(&rdata
[rdcount
], lctx
->zclass
,
1770 type
, lctx
->lex
, ictx
->origin
,
1771 options
, lctx
->mctx
, &target
,
1773 if (MANYERRS(lctx
, result
)) {
1774 SETRESULT(lctx
, result
);
1776 } else if (result
!= ISC_R_SUCCESS
)
1777 goto insist_and_cleanup
;
1784 if (type
== dns_rdatatype_soa
&&
1785 (lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
1786 dns_name_compare(ictx
->current
, lctx
->top
) != 0) {
1787 char namebuf
[DNS_NAME_FORMATSIZE
];
1788 dns_name_format(ictx
->current
, namebuf
,
1790 (*callbacks
->error
)(callbacks
, "%s:%lu: SOA "
1791 "record not at top of zone (%s)",
1792 source
, line
, namebuf
);
1793 result
= DNS_R_NOTZONETOP
;
1794 if (MANYERRS(lctx
, result
)) {
1795 SETRESULT(lctx
, result
);
1796 read_till_eol
= ISC_TRUE
;
1799 } else if (result
!= ISC_R_SUCCESS
)
1800 goto insist_and_cleanup
;
1804 if (type
== dns_rdatatype_rrsig
||
1805 type
== dns_rdatatype_sig
)
1806 covers
= dns_rdata_covers(&rdata
[rdcount
]);
1810 if (!lctx
->ttl_known
&& !lctx
->default_ttl_known
) {
1811 if (type
== dns_rdatatype_soa
) {
1812 (*callbacks
->warn
)(callbacks
,
1813 "%s:%lu: no TTL specified; "
1814 "using SOA MINTTL instead",
1816 lctx
->ttl
= dns_soa_getminimum(&rdata
[rdcount
]);
1817 limit_ttl(callbacks
, source
, line
, &lctx
->ttl
);
1818 lctx
->default_ttl
= lctx
->ttl
;
1819 lctx
->default_ttl_known
= ISC_TRUE
;
1820 } else if ((lctx
->options
& DNS_MASTER_HINT
) != 0) {
1822 * Zero TTL's are fine for hints.
1825 lctx
->default_ttl
= lctx
->ttl
;
1826 lctx
->default_ttl_known
= ISC_TRUE
;
1828 (*callbacks
->warn
)(callbacks
,
1829 "%s:%lu: no TTL specified; "
1832 result
= DNS_R_NOTTL
;
1833 if (MANYERRS(lctx
, result
)) {
1834 SETRESULT(lctx
, result
);
1837 goto insist_and_cleanup
;
1840 } else if (!explicit_ttl
&& lctx
->default_ttl_known
) {
1841 lctx
->ttl
= lctx
->default_ttl
;
1842 } else if (!explicit_ttl
&& lctx
->warn_1035
) {
1843 (*callbacks
->warn
)(callbacks
,
1845 "using RFC1035 TTL semantics",
1847 lctx
->warn_1035
= ISC_FALSE
;
1850 if (type
== dns_rdatatype_rrsig
&& lctx
->warn_sigexpired
) {
1851 dns_rdata_rrsig_t sig
;
1852 result
= dns_rdata_tostruct(&rdata
[rdcount
], &sig
,
1854 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1855 if (isc_serial_lt(sig
.timeexpire
, now
)) {
1856 (*callbacks
->warn
)(callbacks
,
1858 "signature has expired",
1860 lctx
->warn_sigexpired
= ISC_FALSE
;
1864 if ((type
== dns_rdatatype_sig
|| type
== dns_rdatatype_nxt
) &&
1865 lctx
->warn_tcr
&& (lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
1866 (lctx
->options
& DNS_MASTER_SLAVE
) == 0) {
1867 (*callbacks
->warn
)(callbacks
, "%s:%lu: old style DNSSEC "
1868 " zone detected", source
, line
);
1869 lctx
->warn_tcr
= ISC_FALSE
;
1872 if ((lctx
->options
& DNS_MASTER_AGETTL
) != 0) {
1874 * Adjust the TTL for $DATE. If the RR has already
1875 * expired, ignore it.
1877 if (lctx
->ttl
< ttl_offset
)
1879 lctx
->ttl
-= ttl_offset
;
1883 * Find type in rdatalist.
1884 * If it does not exist create new one and prepend to list
1885 * as this will minimise list traversal.
1887 if (ictx
->glue
!= NULL
)
1888 this = ISC_LIST_HEAD(glue_list
);
1890 this = ISC_LIST_HEAD(current_list
);
1892 while (this != NULL
) {
1893 if (this->type
== type
&& this->covers
== covers
)
1895 this = ISC_LIST_NEXT(this, link
);
1899 if (rdlcount
== rdatalist_size
) {
1901 grow_rdatalist(rdatalist_size
+ RDLSZ
,
1907 if (new_rdatalist
== NULL
) {
1908 result
= ISC_R_NOMEMORY
;
1909 goto log_and_cleanup
;
1911 rdatalist
= new_rdatalist
;
1912 rdatalist_size
+= RDLSZ
;
1914 this = &rdatalist
[rdlcount
++];
1916 this->covers
= covers
;
1917 this->rdclass
= lctx
->zclass
;
1918 this->ttl
= lctx
->ttl
;
1919 ISC_LIST_INIT(this->rdata
);
1920 if (ictx
->glue
!= NULL
)
1921 ISC_LIST_INITANDPREPEND(glue_list
, this, link
);
1923 ISC_LIST_INITANDPREPEND(current_list
, this,
1925 } else if (this->ttl
!= lctx
->ttl
) {
1926 (*callbacks
->warn
)(callbacks
,
1928 "TTL set to prior TTL (%lu)",
1929 source
, line
, this->ttl
);
1930 lctx
->ttl
= this->ttl
;
1933 ISC_LIST_APPEND(this->rdata
, &rdata
[rdcount
], link
);
1934 if (ictx
->glue
!= NULL
)
1935 ictx
->glue_line
= line
;
1937 ictx
->current_line
= line
;
1941 * We must have at least 64k as rdlen is 16 bits.
1942 * If we don't commit everything we have so far.
1944 if ((target
.length
- target
.used
) < MINTSIZ
)
1948 } while (!done
&& (lctx
->loop_cnt
== 0 || loop_cnt
++ < lctx
->loop_cnt
));
1951 * Commit what has not yet been committed.
1953 result
= commit(callbacks
, lctx
, ¤t_list
, ictx
->current
,
1954 source
, ictx
->current_line
);
1955 if (MANYERRS(lctx
, result
)) {
1956 SETRESULT(lctx
, result
);
1957 } else if (result
!= ISC_R_SUCCESS
)
1958 goto insist_and_cleanup
;
1959 result
= commit(callbacks
, lctx
, &glue_list
, ictx
->glue
,
1960 source
, ictx
->glue_line
);
1961 if (MANYERRS(lctx
, result
)) {
1962 SETRESULT(lctx
, result
);
1963 } else if (result
!= ISC_R_SUCCESS
)
1964 goto insist_and_cleanup
;
1967 INSIST(lctx
->done
!= NULL
&& lctx
->task
!= NULL
);
1968 result
= DNS_R_CONTINUE
;
1969 } else if (result
== ISC_R_SUCCESS
&& lctx
->result
!= ISC_R_SUCCESS
) {
1970 result
= lctx
->result
;
1971 } else if (result
== ISC_R_SUCCESS
&& lctx
->seen_include
)
1972 result
= DNS_R_SEENINCLUDE
;
1979 INSIST(result
!= ISC_R_SUCCESS
);
1982 while ((this = ISC_LIST_HEAD(current_list
)) != NULL
)
1983 ISC_LIST_UNLINK(current_list
, this, link
);
1984 while ((this = ISC_LIST_HEAD(glue_list
)) != NULL
)
1985 ISC_LIST_UNLINK(glue_list
, this, link
);
1986 if (rdatalist
!= NULL
)
1987 isc_mem_put(mctx
, rdatalist
,
1988 rdatalist_size
* sizeof(*rdatalist
));
1990 isc_mem_put(mctx
, rdata
, rdata_size
* sizeof(*rdata
));
1991 if (target_mem
!= NULL
)
1992 isc_mem_put(mctx
, target_mem
, target_size
);
1993 if (include_file
!= NULL
)
1994 isc_mem_free(mctx
, include_file
);
1996 isc_mem_free(mctx
, range
);
1998 isc_mem_free(mctx
, lhs
);
2000 isc_mem_free(mctx
, gtype
);
2002 isc_mem_free(mctx
, rhs
);
2007 pushfile(const char *master_file
, dns_name_t
*origin
, dns_loadctx_t
*lctx
) {
2008 isc_result_t result
;
2010 dns_incctx_t
*new = NULL
;
2014 REQUIRE(master_file
!= NULL
);
2015 REQUIRE(DNS_LCTX_VALID(lctx
));
2018 lctx
->seen_include
= ISC_TRUE
;
2020 result
= incctx_create(lctx
->mctx
, origin
, &new);
2021 if (result
!= ISC_R_SUCCESS
)
2024 /* Set current domain. */
2025 if (ictx
->glue
!= NULL
|| ictx
->current
!= NULL
) {
2026 for (new_in_use
= 0; new_in_use
< NBUFS
; new_in_use
++)
2027 if (!new->in_use
[new_in_use
])
2029 INSIST(new_in_use
< NBUFS
);
2030 new->current_in_use
= new_in_use
;
2032 dns_fixedname_name(&new->fixed
[new->current_in_use
]);
2033 new->in_use
[new->current_in_use
] = ISC_TRUE
;
2034 dns_name_toregion((ictx
->glue
!= NULL
) ?
2035 ictx
->glue
: ictx
->current
, &r
);
2036 dns_name_fromregion(new->current
, &r
);
2037 new->drop
= ictx
->drop
;
2040 result
= (lctx
->openfile
)(lctx
, master_file
);
2041 if (result
!= ISC_R_SUCCESS
)
2045 return (ISC_R_SUCCESS
);
2049 incctx_destroy(lctx
->mctx
, new);
2053 static inline isc_result_t
2054 read_and_check(isc_boolean_t do_read
, isc_buffer_t
*buffer
,
2055 size_t len
, FILE *f
)
2057 isc_result_t result
;
2060 INSIST(isc_buffer_availablelength(buffer
) >= len
);
2061 result
= isc_stdio_read(isc_buffer_used(buffer
), 1, len
,
2063 if (result
!= ISC_R_SUCCESS
)
2065 isc_buffer_add(buffer
, len
);
2066 } else if (isc_buffer_remaininglength(buffer
) < len
)
2067 return (ISC_R_RANGE
);
2069 return (ISC_R_SUCCESS
);
2073 load_raw(dns_loadctx_t
*lctx
) {
2074 isc_result_t result
= ISC_R_SUCCESS
;
2075 isc_boolean_t done
= ISC_FALSE
;
2076 unsigned int loop_cnt
= 0;
2077 dns_rdatacallbacks_t
*callbacks
;
2078 unsigned char namebuf
[DNS_NAME_MAXWIRE
];
2081 rdatalist_head_t head
, dummy
;
2082 dns_rdatalist_t rdatalist
;
2083 isc_mem_t
*mctx
= lctx
->mctx
;
2084 dns_rdata_t
*rdata
= NULL
;
2085 unsigned int rdata_size
= 0;
2086 int target_size
= TSIZ
;
2087 isc_buffer_t target
;
2088 unsigned char *target_mem
= NULL
;
2090 REQUIRE(DNS_LCTX_VALID(lctx
));
2091 callbacks
= lctx
->callbacks
;
2094 dns_masterrawheader_t header
;
2095 isc_uint32_t format
, version
, dumptime
;
2096 size_t hdrlen
= sizeof(format
) + sizeof(version
) +
2099 INSIST(hdrlen
<= sizeof(header
));
2100 isc_buffer_init(&target
, &header
, sizeof(header
));
2102 result
= isc_stdio_read(&header
, 1, hdrlen
, lctx
->f
, NULL
);
2103 if (result
!= ISC_R_SUCCESS
) {
2104 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2105 "isc_stdio_read failed: %s",
2106 isc_result_totext(result
));
2109 isc_buffer_add(&target
, hdrlen
);
2110 format
= isc_buffer_getuint32(&target
);
2111 if (format
!= dns_masterformat_raw
) {
2112 (*callbacks
->error
)(callbacks
,
2114 "file format mismatch");
2115 return (ISC_R_NOTIMPLEMENTED
);
2118 version
= isc_buffer_getuint32(&target
);
2119 if (version
> DNS_RAWFORMAT_VERSION
) {
2120 (*callbacks
->error
)(callbacks
,
2122 "unsupported file format version");
2123 return (ISC_R_NOTIMPLEMENTED
);
2126 /* Empty read: currently, we do not use dumptime */
2127 dumptime
= isc_buffer_getuint32(&target
);
2129 lctx
->first
= ISC_FALSE
;
2132 ISC_LIST_INIT(head
);
2133 ISC_LIST_INIT(dummy
);
2134 dns_rdatalist_init(&rdatalist
);
2137 * Allocate target_size of buffer space. This is greater than twice
2138 * the maximum individual RR data size.
2140 target_mem
= isc_mem_get(mctx
, target_size
);
2141 if (target_mem
== NULL
) {
2142 result
= ISC_R_NOMEMORY
;
2145 isc_buffer_init(&target
, target_mem
, target_size
);
2148 * In the following loop, we regard any error fatal regardless of
2149 * whether "MANYERRORS" is set in the context option. This is because
2150 * normal errors should already have been checked at creation time.
2151 * Besides, it is very unlikely that we can recover from an error
2152 * in this format, and so trying to continue parsing erroneous data
2153 * does not really make sense.
2156 (lctx
->loop_cnt
== 0 || loop_cnt
< lctx
->loop_cnt
);
2158 unsigned int i
, rdcount
, consumed_name
;
2159 isc_uint16_t namelen
;
2160 isc_uint32_t totallen
;
2161 size_t minlen
, readlen
;
2162 isc_boolean_t sequential_read
= ISC_FALSE
;
2164 /* Read the data length */
2165 isc_buffer_clear(&target
);
2166 INSIST(isc_buffer_availablelength(&target
) >=
2168 result
= isc_stdio_read(target
.base
, 1, sizeof(totallen
),
2170 if (result
== ISC_R_EOF
) {
2171 result
= ISC_R_SUCCESS
;
2175 if (result
!= ISC_R_SUCCESS
)
2177 isc_buffer_add(&target
, sizeof(totallen
));
2178 totallen
= isc_buffer_getuint32(&target
);
2180 * Validation: the input data must at least contain the common
2183 minlen
= sizeof(totallen
) + sizeof(isc_uint16_t
) +
2184 sizeof(isc_uint16_t
) + sizeof(isc_uint16_t
) +
2185 sizeof(isc_uint32_t
) + sizeof(isc_uint32_t
);
2186 if (totallen
< minlen
) {
2187 result
= ISC_R_RANGE
;
2190 totallen
-= sizeof(totallen
);
2192 isc_buffer_clear(&target
);
2193 if (totallen
> isc_buffer_availablelength(&target
)) {
2195 * The default buffer size should typically be large
2196 * enough to store the entire RRset. We could try to
2197 * allocate enough space if this is not the case, but
2198 * it might cause a hazardous result when "totallen"
2199 * is forged. Thus, we'd rather take an inefficient
2200 * but robust approach in this atypical case: read
2201 * data step by step, and commit partial data when
2202 * necessary. Note that the buffer must be large
2203 * enough to store the "header part", owner name, and
2204 * at least one rdata (however large it is).
2206 sequential_read
= ISC_TRUE
;
2207 readlen
= minlen
- sizeof(totallen
);
2210 * Typical case. We can read the whole RRset at once
2211 * with the default buffer.
2215 result
= isc_stdio_read(target
.base
, 1, readlen
,
2217 if (result
!= ISC_R_SUCCESS
)
2219 isc_buffer_add(&target
, readlen
);
2221 /* Construct RRset headers */
2222 rdatalist
.rdclass
= isc_buffer_getuint16(&target
);
2223 rdatalist
.type
= isc_buffer_getuint16(&target
);
2224 rdatalist
.covers
= isc_buffer_getuint16(&target
);
2225 rdatalist
.ttl
= isc_buffer_getuint32(&target
);
2226 rdcount
= isc_buffer_getuint32(&target
);
2228 result
= ISC_R_RANGE
;
2231 INSIST(isc_buffer_consumedlength(&target
) <= readlen
);
2233 /* Owner name: length followed by name */
2234 result
= read_and_check(sequential_read
, &target
,
2235 sizeof(namelen
), lctx
->f
);
2236 if (result
!= ISC_R_SUCCESS
)
2238 namelen
= isc_buffer_getuint16(&target
);
2239 if (namelen
> sizeof(namebuf
)) {
2240 result
= ISC_R_RANGE
;
2244 result
= read_and_check(sequential_read
, &target
, namelen
,
2246 if (result
!= ISC_R_SUCCESS
)
2248 isc_buffer_setactive(&target
, (unsigned int)namelen
);
2249 isc_buffer_activeregion(&target
, &r
);
2250 dns_name_init(&name
, NULL
);
2251 dns_name_fromregion(&name
, &r
);
2252 isc_buffer_forward(&target
, (unsigned int)namelen
);
2253 consumed_name
= isc_buffer_consumedlength(&target
);
2255 /* Rdata contents. */
2256 if (rdcount
> rdata_size
) {
2257 dns_rdata_t
*new_rdata
= NULL
;
2259 new_rdata
= grow_rdata(rdata_size
+ RDSZ
, rdata
,
2262 if (new_rdata
== NULL
) {
2263 result
= ISC_R_NOMEMORY
;
2271 for (i
= 0; i
< rdcount
; i
++) {
2274 dns_rdata_init(&rdata
[i
]);
2276 if (sequential_read
&&
2277 isc_buffer_availablelength(&target
) < MINTSIZ
) {
2280 INSIST(i
> 0); /* detect an infinite loop */
2282 /* Partial Commit. */
2283 ISC_LIST_APPEND(head
, &rdatalist
, link
);
2284 result
= commit(callbacks
, lctx
, &head
, &name
,
2286 for (j
= 0; j
< i
; j
++) {
2287 ISC_LIST_UNLINK(rdatalist
.rdata
,
2289 dns_rdata_reset(&rdata
[j
]);
2291 if (result
!= ISC_R_SUCCESS
)
2294 /* Rewind the buffer and continue */
2295 isc_buffer_clear(&target
);
2296 isc_buffer_add(&target
, consumed_name
);
2297 isc_buffer_forward(&target
, consumed_name
);
2306 result
= read_and_check(sequential_read
, &target
,
2307 sizeof(rdlen
), lctx
->f
);
2308 if (result
!= ISC_R_SUCCESS
)
2310 rdlen
= isc_buffer_getuint16(&target
);
2313 result
= read_and_check(sequential_read
, &target
,
2315 if (result
!= ISC_R_SUCCESS
)
2317 isc_buffer_setactive(&target
, (unsigned int)rdlen
);
2318 isc_buffer_activeregion(&target
, &r
);
2319 isc_buffer_forward(&target
, (unsigned int)rdlen
);
2320 dns_rdata_fromregion(&rdata
[i
], rdatalist
.rdclass
,
2321 rdatalist
.type
, &r
);
2323 ISC_LIST_APPEND(rdatalist
.rdata
, &rdata
[i
], link
);
2327 * Sanity check. Still having remaining space is not
2328 * necessarily critical, but it very likely indicates broken
2329 * or malformed data.
2331 if (isc_buffer_remaininglength(&target
) != 0) {
2332 result
= ISC_R_RANGE
;
2336 ISC_LIST_APPEND(head
, &rdatalist
, link
);
2338 /* Commit this RRset. rdatalist will be unlinked. */
2339 result
= commit(callbacks
, lctx
, &head
, &name
, NULL
, 0);
2341 for (i
= 0; i
< rdcount
; i
++) {
2342 ISC_LIST_UNLINK(rdatalist
.rdata
, &rdata
[i
], link
);
2343 dns_rdata_reset(&rdata
[i
]);
2346 if (result
!= ISC_R_SUCCESS
)
2351 INSIST(lctx
->done
!= NULL
&& lctx
->task
!= NULL
);
2352 result
= DNS_R_CONTINUE
;
2353 } else if (result
== ISC_R_SUCCESS
&& lctx
->result
!= ISC_R_SUCCESS
)
2354 result
= lctx
->result
;
2358 isc_mem_put(mctx
, rdata
, rdata_size
* sizeof(*rdata
));
2359 if (target_mem
!= NULL
)
2360 isc_mem_put(mctx
, target_mem
, target_size
);
2361 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_CONTINUE
) {
2362 (*callbacks
->error
)(callbacks
, "dns_master_load: %s",
2363 dns_result_totext(result
));
2370 dns_master_loadfile(const char *master_file
, dns_name_t
*top
,
2372 dns_rdataclass_t zclass
, unsigned int options
,
2373 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
)
2375 return (dns_master_loadfile3(master_file
, top
, origin
, zclass
, options
,
2376 0, callbacks
, mctx
, dns_masterformat_text
));
2380 dns_master_loadfile2(const char *master_file
, dns_name_t
*top
,
2382 dns_rdataclass_t zclass
, unsigned int options
,
2383 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
,
2384 dns_masterformat_t format
)
2386 return (dns_master_loadfile3(master_file
, top
, origin
, zclass
, options
,
2387 0, callbacks
, mctx
, format
));
2391 dns_master_loadfile3(const char *master_file
, dns_name_t
*top
,
2392 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2393 unsigned int options
, isc_uint32_t resign
,
2394 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
,
2395 dns_masterformat_t format
)
2397 dns_loadctx_t
*lctx
= NULL
;
2398 isc_result_t result
;
2400 result
= loadctx_create(format
, mctx
, options
, resign
, top
, zclass
,
2401 origin
, callbacks
, NULL
, NULL
, NULL
, NULL
,
2403 if (result
!= ISC_R_SUCCESS
)
2406 result
= (lctx
->openfile
)(lctx
, master_file
);
2407 if (result
!= ISC_R_SUCCESS
)
2410 result
= (lctx
->load
)(lctx
);
2411 INSIST(result
!= DNS_R_CONTINUE
);
2414 dns_loadctx_detach(&lctx
);
2419 dns_master_loadfileinc(const char *master_file
, dns_name_t
*top
,
2420 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2421 unsigned int options
, dns_rdatacallbacks_t
*callbacks
,
2422 isc_task_t
*task
, dns_loaddonefunc_t done
,
2423 void *done_arg
, dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
)
2425 return (dns_master_loadfileinc3(master_file
, top
, origin
, zclass
,
2426 options
, 0, callbacks
, task
, done
,
2427 done_arg
, lctxp
, mctx
,
2428 dns_masterformat_text
));
2432 dns_master_loadfileinc2(const char *master_file
, dns_name_t
*top
,
2433 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2434 unsigned int options
, dns_rdatacallbacks_t
*callbacks
,
2435 isc_task_t
*task
, dns_loaddonefunc_t done
,
2436 void *done_arg
, dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
,
2437 dns_masterformat_t format
)
2439 return (dns_master_loadfileinc3(master_file
, top
, origin
, zclass
,
2440 options
, 0, callbacks
, task
, done
,
2441 done_arg
, lctxp
, mctx
, format
));
2445 dns_master_loadfileinc3(const char *master_file
, dns_name_t
*top
,
2446 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2447 unsigned int options
, isc_uint32_t resign
,
2448 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
2449 dns_loaddonefunc_t done
, void *done_arg
,
2450 dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
,
2451 dns_masterformat_t format
)
2453 dns_loadctx_t
*lctx
= NULL
;
2454 isc_result_t result
;
2456 REQUIRE(task
!= NULL
);
2457 REQUIRE(done
!= NULL
);
2459 result
= loadctx_create(format
, mctx
, options
, resign
, top
, zclass
,
2460 origin
, callbacks
, task
, done
, done_arg
, NULL
,
2462 if (result
!= ISC_R_SUCCESS
)
2465 result
= (lctx
->openfile
)(lctx
, master_file
);
2466 if (result
!= ISC_R_SUCCESS
)
2469 result
= task_send(lctx
);
2470 if (result
== ISC_R_SUCCESS
) {
2471 dns_loadctx_attach(lctx
, lctxp
);
2472 return (DNS_R_CONTINUE
);
2476 dns_loadctx_detach(&lctx
);
2481 dns_master_loadstream(FILE *stream
, dns_name_t
*top
, dns_name_t
*origin
,
2482 dns_rdataclass_t zclass
, unsigned int options
,
2483 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
)
2485 isc_result_t result
;
2486 dns_loadctx_t
*lctx
= NULL
;
2488 REQUIRE(stream
!= NULL
);
2490 result
= loadctx_create(dns_masterformat_text
, mctx
, options
, 0, top
,
2491 zclass
, origin
, callbacks
, NULL
, NULL
, NULL
,
2493 if (result
!= ISC_R_SUCCESS
)
2496 result
= isc_lex_openstream(lctx
->lex
, stream
);
2497 if (result
!= ISC_R_SUCCESS
)
2500 result
= (lctx
->load
)(lctx
);
2501 INSIST(result
!= DNS_R_CONTINUE
);
2505 dns_loadctx_detach(&lctx
);
2510 dns_master_loadstreaminc(FILE *stream
, dns_name_t
*top
, dns_name_t
*origin
,
2511 dns_rdataclass_t zclass
, unsigned int options
,
2512 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
2513 dns_loaddonefunc_t done
, void *done_arg
,
2514 dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
)
2516 isc_result_t result
;
2517 dns_loadctx_t
*lctx
= NULL
;
2519 REQUIRE(stream
!= NULL
);
2520 REQUIRE(task
!= NULL
);
2521 REQUIRE(done
!= NULL
);
2523 result
= loadctx_create(dns_masterformat_text
, mctx
, options
, 0, top
,
2524 zclass
, origin
, callbacks
, task
, done
,
2525 done_arg
, NULL
, &lctx
);
2526 if (result
!= ISC_R_SUCCESS
)
2529 result
= isc_lex_openstream(lctx
->lex
, stream
);
2530 if (result
!= ISC_R_SUCCESS
)
2533 result
= task_send(lctx
);
2534 if (result
== ISC_R_SUCCESS
) {
2535 dns_loadctx_attach(lctx
, lctxp
);
2536 return (DNS_R_CONTINUE
);
2541 dns_loadctx_detach(&lctx
);
2546 dns_master_loadbuffer(isc_buffer_t
*buffer
, dns_name_t
*top
,
2547 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2548 unsigned int options
,
2549 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
)
2551 isc_result_t result
;
2552 dns_loadctx_t
*lctx
= NULL
;
2554 REQUIRE(buffer
!= NULL
);
2556 result
= loadctx_create(dns_masterformat_text
, mctx
, options
, 0, top
,
2557 zclass
, origin
, callbacks
, NULL
, NULL
, NULL
,
2559 if (result
!= ISC_R_SUCCESS
)
2562 result
= isc_lex_openbuffer(lctx
->lex
, buffer
);
2563 if (result
!= ISC_R_SUCCESS
)
2566 result
= (lctx
->load
)(lctx
);
2567 INSIST(result
!= DNS_R_CONTINUE
);
2570 dns_loadctx_detach(&lctx
);
2575 dns_master_loadbufferinc(isc_buffer_t
*buffer
, dns_name_t
*top
,
2576 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2577 unsigned int options
,
2578 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
2579 dns_loaddonefunc_t done
, void *done_arg
,
2580 dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
)
2582 isc_result_t result
;
2583 dns_loadctx_t
*lctx
= NULL
;
2585 REQUIRE(buffer
!= NULL
);
2586 REQUIRE(task
!= NULL
);
2587 REQUIRE(done
!= NULL
);
2589 result
= loadctx_create(dns_masterformat_text
, mctx
, options
, 0, top
,
2590 zclass
, origin
, callbacks
, task
, done
,
2591 done_arg
, NULL
, &lctx
);
2592 if (result
!= ISC_R_SUCCESS
)
2595 result
= isc_lex_openbuffer(lctx
->lex
, buffer
);
2596 if (result
!= ISC_R_SUCCESS
)
2599 result
= task_send(lctx
);
2600 if (result
== ISC_R_SUCCESS
) {
2601 dns_loadctx_attach(lctx
, lctxp
);
2602 return (DNS_R_CONTINUE
);
2606 dns_loadctx_detach(&lctx
);
2611 dns_master_loadlexer(isc_lex_t
*lex
, dns_name_t
*top
,
2612 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2613 unsigned int options
,
2614 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
)
2616 isc_result_t result
;
2617 dns_loadctx_t
*lctx
= NULL
;
2619 REQUIRE(lex
!= NULL
);
2621 result
= loadctx_create(dns_masterformat_text
, mctx
, options
, 0, top
,
2622 zclass
, origin
, callbacks
, NULL
, NULL
, NULL
,
2624 if (result
!= ISC_R_SUCCESS
)
2627 result
= (lctx
->load
)(lctx
);
2628 INSIST(result
!= DNS_R_CONTINUE
);
2630 dns_loadctx_detach(&lctx
);
2635 dns_master_loadlexerinc(isc_lex_t
*lex
, dns_name_t
*top
,
2636 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2637 unsigned int options
,
2638 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
2639 dns_loaddonefunc_t done
, void *done_arg
,
2640 dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
)
2642 isc_result_t result
;
2643 dns_loadctx_t
*lctx
= NULL
;
2645 REQUIRE(lex
!= NULL
);
2646 REQUIRE(task
!= NULL
);
2647 REQUIRE(done
!= NULL
);
2649 result
= loadctx_create(dns_masterformat_text
, mctx
, options
, 0, top
,
2650 zclass
, origin
, callbacks
, task
, done
,
2651 done_arg
, lex
, &lctx
);
2652 if (result
!= ISC_R_SUCCESS
)
2655 result
= task_send(lctx
);
2656 if (result
== ISC_R_SUCCESS
) {
2657 dns_loadctx_attach(lctx
, lctxp
);
2658 return (DNS_R_CONTINUE
);
2661 dns_loadctx_detach(&lctx
);
2666 * Grow the slab of dns_rdatalist_t structures.
2667 * Re-link glue and current list.
2669 static dns_rdatalist_t
*
2670 grow_rdatalist(int new_len
, dns_rdatalist_t
*old
, int old_len
,
2671 rdatalist_head_t
*current
, rdatalist_head_t
*glue
,
2674 dns_rdatalist_t
*new;
2676 ISC_LIST(dns_rdatalist_t
) save
;
2677 dns_rdatalist_t
*this;
2679 new = isc_mem_get(mctx
, new_len
* sizeof(*new));
2683 ISC_LIST_INIT(save
);
2684 this = ISC_LIST_HEAD(*current
);
2685 while ((this = ISC_LIST_HEAD(*current
)) != NULL
) {
2686 ISC_LIST_UNLINK(*current
, this, link
);
2687 ISC_LIST_APPEND(save
, this, link
);
2689 while ((this = ISC_LIST_HEAD(save
)) != NULL
) {
2690 ISC_LIST_UNLINK(save
, this, link
);
2691 new[rdlcount
] = *this;
2692 ISC_LIST_APPEND(*current
, &new[rdlcount
], link
);
2696 ISC_LIST_INIT(save
);
2697 this = ISC_LIST_HEAD(*glue
);
2698 while ((this = ISC_LIST_HEAD(*glue
)) != NULL
) {
2699 ISC_LIST_UNLINK(*glue
, this, link
);
2700 ISC_LIST_APPEND(save
, this, link
);
2702 while ((this = ISC_LIST_HEAD(save
)) != NULL
) {
2703 ISC_LIST_UNLINK(save
, this, link
);
2704 new[rdlcount
] = *this;
2705 ISC_LIST_APPEND(*glue
, &new[rdlcount
], link
);
2709 INSIST(rdlcount
== old_len
);
2711 isc_mem_put(mctx
, old
, old_len
* sizeof(*old
));
2716 * Grow the slab of rdata structs.
2717 * Re-link the current and glue chains.
2719 static dns_rdata_t
*
2720 grow_rdata(int new_len
, dns_rdata_t
*old
, int old_len
,
2721 rdatalist_head_t
*current
, rdatalist_head_t
*glue
,
2726 ISC_LIST(dns_rdata_t
) save
;
2727 dns_rdatalist_t
*this;
2730 new = isc_mem_get(mctx
, new_len
* sizeof(*new));
2733 memset(new, 0, new_len
* sizeof(*new));
2736 * Copy current relinking.
2738 this = ISC_LIST_HEAD(*current
);
2739 while (this != NULL
) {
2740 ISC_LIST_INIT(save
);
2741 while ((rdata
= ISC_LIST_HEAD(this->rdata
)) != NULL
) {
2742 ISC_LIST_UNLINK(this->rdata
, rdata
, link
);
2743 ISC_LIST_APPEND(save
, rdata
, link
);
2745 while ((rdata
= ISC_LIST_HEAD(save
)) != NULL
) {
2746 ISC_LIST_UNLINK(save
, rdata
, link
);
2747 new[rdcount
] = *rdata
;
2748 ISC_LIST_APPEND(this->rdata
, &new[rdcount
], link
);
2751 this = ISC_LIST_NEXT(this, link
);
2755 * Copy glue relinking.
2757 this = ISC_LIST_HEAD(*glue
);
2758 while (this != NULL
) {
2759 ISC_LIST_INIT(save
);
2760 while ((rdata
= ISC_LIST_HEAD(this->rdata
)) != NULL
) {
2761 ISC_LIST_UNLINK(this->rdata
, rdata
, link
);
2762 ISC_LIST_APPEND(save
, rdata
, link
);
2764 while ((rdata
= ISC_LIST_HEAD(save
)) != NULL
) {
2765 ISC_LIST_UNLINK(save
, rdata
, link
);
2766 new[rdcount
] = *rdata
;
2767 ISC_LIST_APPEND(this->rdata
, &new[rdcount
], link
);
2770 this = ISC_LIST_NEXT(this, link
);
2772 INSIST(rdcount
== old_len
);
2774 isc_mem_put(mctx
, old
, old_len
* sizeof(*old
));
2779 resign_fromlist(dns_rdatalist_t
*this, isc_uint32_t resign
) {
2781 dns_rdata_rrsig_t sig
;
2784 rdata
= ISC_LIST_HEAD(this->rdata
);
2785 INSIST(rdata
!= NULL
);
2786 (void)dns_rdata_tostruct(rdata
, &sig
, NULL
);
2787 when
= sig
.timeexpire
- resign
;
2789 rdata
= ISC_LIST_NEXT(rdata
, link
);
2790 while (rdata
!= NULL
) {
2791 (void)dns_rdata_tostruct(rdata
, &sig
, NULL
);
2792 if (sig
.timeexpire
- resign
< when
)
2793 when
= sig
.timeexpire
- resign
;
2794 rdata
= ISC_LIST_NEXT(rdata
, link
);
2800 * Convert each element from a rdatalist_t to rdataset then call commit.
2801 * Unlink each element as we go.
2805 commit(dns_rdatacallbacks_t
*callbacks
, dns_loadctx_t
*lctx
,
2806 rdatalist_head_t
*head
, dns_name_t
*owner
,
2807 const char *source
, unsigned int line
)
2809 dns_rdatalist_t
*this;
2810 dns_rdataset_t dataset
;
2811 isc_result_t result
;
2812 char namebuf
[DNS_NAME_FORMATSIZE
];
2813 void (*error
)(struct dns_rdatacallbacks
*, const char *, ...);
2815 this = ISC_LIST_HEAD(*head
);
2816 error
= callbacks
->error
;
2819 return (ISC_R_SUCCESS
);
2821 dns_rdataset_init(&dataset
);
2822 RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset
)
2824 dataset
.trust
= dns_trust_ultimate
;
2826 * If this is a secure dynamic zone set the re-signing time.
2828 if (dataset
.type
== dns_rdatatype_rrsig
&&
2829 (lctx
->options
& DNS_MASTER_RESIGN
) != 0) {
2830 dataset
.attributes
|= DNS_RDATASETATTR_RESIGN
;
2831 dns_name_format(owner
, namebuf
, sizeof(namebuf
));
2832 dataset
.resign
= resign_fromlist(this, lctx
->resign
);
2834 result
= ((*callbacks
->add
)(callbacks
->add_private
, owner
,
2836 if (result
== ISC_R_NOMEMORY
) {
2837 (*error
)(callbacks
, "dns_master_load: %s",
2838 dns_result_totext(result
));
2839 } else if (result
!= ISC_R_SUCCESS
) {
2840 dns_name_format(owner
, namebuf
, sizeof(namebuf
));
2841 if (source
!= NULL
) {
2842 (*error
)(callbacks
, "%s: %s:%lu: %s: %s",
2843 "dns_master_load", source
, line
,
2844 namebuf
, dns_result_totext(result
));
2846 (*error
)(callbacks
, "%s: %s: %s",
2847 "dns_master_load", namebuf
,
2848 dns_result_totext(result
));
2851 if (MANYERRS(lctx
, result
))
2852 SETRESULT(lctx
, result
);
2853 else if (result
!= ISC_R_SUCCESS
)
2855 ISC_LIST_UNLINK(*head
, this, link
);
2856 this = ISC_LIST_HEAD(*head
);
2857 } while (this != NULL
);
2858 return (ISC_R_SUCCESS
);
2862 * Returns ISC_TRUE if one of the NS rdata's contains 'owner'.
2865 static isc_boolean_t
2866 is_glue(rdatalist_head_t
*head
, dns_name_t
*owner
) {
2867 dns_rdatalist_t
*this;
2869 isc_region_t region
;
2875 this = ISC_LIST_HEAD(*head
);
2876 while (this != NULL
) {
2877 if (this->type
== dns_rdatatype_ns
)
2879 this = ISC_LIST_NEXT(this, link
);
2884 rdata
= ISC_LIST_HEAD(this->rdata
);
2885 while (rdata
!= NULL
) {
2886 dns_name_init(&name
, NULL
);
2887 dns_rdata_toregion(rdata
, ®ion
);
2888 dns_name_fromregion(&name
, ®ion
);
2889 if (dns_name_compare(&name
, owner
) == 0)
2891 rdata
= ISC_LIST_NEXT(rdata
, link
);
2897 load_quantum(isc_task_t
*task
, isc_event_t
*event
) {
2898 isc_result_t result
;
2899 dns_loadctx_t
*lctx
;
2901 REQUIRE(event
!= NULL
);
2902 lctx
= event
->ev_arg
;
2903 REQUIRE(DNS_LCTX_VALID(lctx
));
2906 result
= ISC_R_CANCELED
;
2908 result
= (lctx
->load
)(lctx
);
2909 if (result
== DNS_R_CONTINUE
) {
2910 event
->ev_arg
= lctx
;
2911 isc_task_send(task
, &event
);
2913 (lctx
->done
)(lctx
->done_arg
, result
);
2914 isc_event_free(&event
);
2915 dns_loadctx_detach(&lctx
);
2920 task_send(dns_loadctx_t
*lctx
) {
2923 event
= isc_event_allocate(lctx
->mctx
, NULL
,
2924 DNS_EVENT_MASTERQUANTUM
,
2925 load_quantum
, lctx
, sizeof(*event
));
2927 return (ISC_R_NOMEMORY
);
2928 isc_task_send(lctx
->task
, &event
);
2929 return (ISC_R_SUCCESS
);
2933 dns_loadctx_cancel(dns_loadctx_t
*lctx
) {
2934 REQUIRE(DNS_LCTX_VALID(lctx
));
2937 lctx
->canceled
= ISC_TRUE
;
2938 UNLOCK(&lctx
->lock
);