2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: master.c,v 1.122.2.8.2.14 2004/05/05 01:32:16 marka Exp $ */
22 #include <isc/event.h>
24 #include <isc/magic.h>
26 #include <isc/print.h>
27 #include <isc/serial.h>
28 #include <isc/stdtime.h>
29 #include <isc/string.h>
33 #include <dns/callbacks.h>
34 #include <dns/events.h>
35 #include <dns/fixedname.h>
36 #include <dns/master.h>
38 #include <dns/rdata.h>
39 #include <dns/rdataclass.h>
40 #include <dns/rdatalist.h>
41 #include <dns/rdataset.h>
42 #include <dns/rdatastruct.h>
43 #include <dns/rdatatype.h>
44 #include <dns/result.h>
50 * Grow the number of dns_rdatalist_t (RDLSZ) and dns_rdata_t (RDSZ) structures
51 * by these sizes when we need to.
53 * RDLSZ reflects the number of different types with the same name expected.
54 * RDSZ reflects the number of rdata expected at a give name that can fit into
65 * Target buffer size and minimum target size.
66 * MINTSIZ must be big enough to hold the largest rdata record.
70 #define TSIZ (128*1024)
72 * max message size - header - root - type - class - ttl - rdlen
74 #define MINTSIZ (65535 - 12 - 1 - 2 - 2 - 4 - 2)
76 * Size for tokens in the presentation format,
77 * The largest tokens are the base64 blocks in KEY and CERT records,
78 * Largest key allowed is about 1372 bytes but
79 * there is no fixed upper bound on CERT records.
80 * 2K is too small for some X.509s, 8K is overkill.
82 #define TOKENSIZ (8*1024)
84 #define DNS_MASTER_BUFSZ 2048
86 typedef ISC_LIST(dns_rdatalist_t
) rdatalist_head_t
;
88 typedef struct dns_incctx dns_incctx_t
;
91 * Master file load state.
98 isc_boolean_t keep_lex
;
99 dns_rdatacallbacks_t
*callbacks
;
101 dns_loaddonefunc_t done
;
103 unsigned int options
;
104 isc_boolean_t ttl_known
;
105 isc_boolean_t default_ttl_known
;
106 isc_boolean_t warn_1035
;
107 isc_boolean_t warn_tcr
;
108 isc_boolean_t warn_sigexpired
;
109 isc_boolean_t seen_include
;
111 isc_uint32_t default_ttl
;
112 dns_rdataclass_t zclass
;
113 dns_fixedname_t fixed_top
;
114 dns_name_t
*top
; /* top of zone */
115 /* Which fixed buffers we are using? */
116 unsigned int loop_cnt
; /* records per quantum,
118 isc_boolean_t canceled
;
122 isc_uint32_t references
;
127 dns_incctx_t
*parent
;
131 dns_fixedname_t fixed
[NBUFS
]; /* working buffers */
132 unsigned int in_use
[NBUFS
]; /* covert to bitmap? */
137 unsigned int glue_line
;
138 unsigned int current_line
;
141 #define DNS_LCTX_MAGIC ISC_MAGIC('L','c','t','x')
142 #define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
144 #define DNS_AS_STR(t) ((t).value.as_textregion.base)
147 pushfile(const char *master_file
, dns_name_t
*origin
, dns_loadctx_t
*lctx
);
150 commit(dns_rdatacallbacks_t
*, dns_loadctx_t
*, rdatalist_head_t
*,
151 dns_name_t
*, const char *, unsigned int);
154 is_glue(rdatalist_head_t
*, dns_name_t
*);
156 static dns_rdatalist_t
*
157 grow_rdatalist(int, dns_rdatalist_t
*, int, rdatalist_head_t
*,
158 rdatalist_head_t
*, isc_mem_t
*mctx
);
161 grow_rdata(int, dns_rdata_t
*, int, rdatalist_head_t
*, rdatalist_head_t
*,
165 load_quantum(isc_task_t
*task
, isc_event_t
*event
);
168 task_send(dns_loadctx_t
*lctx
);
171 loadctx_destroy(dns_loadctx_t
*lctx
);
173 #define GETTOKEN(lexer, options, token, eol) \
175 result = gettoken(lexer, options, token, eol, callbacks); \
177 case ISC_R_SUCCESS: \
179 case ISC_R_UNEXPECTED: \
180 goto insist_and_cleanup; \
182 if (MANYERRS(lctx, result)) { \
183 SETRESULT(lctx, result); \
185 read_till_eol = ISC_TRUE; \
188 goto log_and_cleanup; \
190 if ((token)->type == isc_tokentype_special) { \
191 result = DNS_R_SYNTAX; \
192 if (MANYERRS(lctx, result)) { \
193 SETRESULT(lctx, result); \
195 read_till_eol = ISC_TRUE; \
198 goto log_and_cleanup; \
204 result = commit(callbacks, lctx, ¤t_list, \
205 ictx->current, source, ictx->current_line); \
206 if (MANYERRS(lctx, result)) { \
207 SETRESULT(lctx, result); \
208 } else if (result != ISC_R_SUCCESS) \
209 goto insist_and_cleanup; \
210 result = commit(callbacks, lctx, &glue_list, \
211 ictx->glue, source, ictx->glue_line); \
212 if (MANYERRS(lctx, result)) { \
213 SETRESULT(lctx, result); \
214 } else if (result != ISC_R_SUCCESS) \
215 goto insist_and_cleanup; \
218 isc_buffer_init(&target, target_mem, target_size); \
219 rdcount_save = rdcount; \
220 rdlcount_save = rdlcount; \
223 #define WARNUNEXPECTEDEOF(lexer) \
225 if (isc_lex_isfile(lexer)) \
226 (*callbacks->warn)(callbacks, \
227 "%s: file does not end with newline", \
233 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE); \
234 if (token.type != isc_tokentype_eol) { \
235 isc_lex_ungettoken(lctx->lex, &token); \
236 result = DNS_R_EXTRATOKEN; \
237 if (MANYERRS(lctx, result)) { \
238 SETRESULT(lctx, result); \
240 read_till_eol = ISC_TRUE; \
242 } else if (result != ISC_R_SUCCESS) \
243 goto log_and_cleanup; \
247 #define MANYERRS(lctx, result) \
248 ((result != ISC_R_SUCCESS) && \
249 ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
251 #define SETRESULT(lctx, r) \
253 if ((lctx)->result == ISC_R_SUCCESS) \
254 (lctx)->result = r; \
257 #define LOGITFILE(result, filename) \
258 if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \
259 result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \
260 result == ISC_R_NOPERM) \
261 (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \
262 "dns_master_load", source, line, \
263 filename, dns_result_totext(result)); \
266 #define LOGIT(result) \
267 if (result == ISC_R_NOMEMORY) \
268 (*callbacks->error)(callbacks, "dns_master_load: %s", \
269 dns_result_totext(result)); \
271 (*callbacks->error)(callbacks, "%s: %s:%lu: %s", \
273 source, line, dns_result_totext(result))
276 static unsigned char in_addr_arpa_data
[] = "\007IN-ADDR\004ARPA";
277 static unsigned char in_addr_arpa_offsets
[] = { 0, 8, 13 };
278 static const dns_name_t in_addr_arpa
=
281 in_addr_arpa_data
, 14, 3,
282 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
283 in_addr_arpa_offsets
, NULL
,
284 {(void *)-1, (void *)-1},
288 static unsigned char ip6_int_data
[] = "\003IP6\003INT";
289 static unsigned char ip6_int_offsets
[] = { 0, 4, 8 };
290 static const dns_name_t ip6_int
=
294 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
295 ip6_int_offsets
, NULL
,
296 {(void *)-1, (void *)-1},
300 static unsigned char ip6_arpa_data
[] = "\003IP6\004ARPA";
301 static unsigned char ip6_arpa_offsets
[] = { 0, 4, 9 };
302 static const dns_name_t ip6_arpa
=
305 ip6_arpa_data
, 10, 3,
306 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
307 ip6_arpa_offsets
, NULL
,
308 {(void *)-1, (void *)-1},
313 static inline isc_result_t
314 gettoken(isc_lex_t
*lex
, unsigned int options
, isc_token_t
*token
,
315 isc_boolean_t eol
, dns_rdatacallbacks_t
*callbacks
)
319 options
|= ISC_LEXOPT_EOL
| ISC_LEXOPT_EOF
| ISC_LEXOPT_DNSMULTILINE
|
321 result
= isc_lex_gettoken(lex
, options
, token
);
322 if (result
!= ISC_R_SUCCESS
) {
325 return (ISC_R_NOMEMORY
);
327 (*callbacks
->error
)(callbacks
,
328 "dns_master_load: %s:%lu:"
329 " isc_lex_gettoken() failed: %s",
330 isc_lex_getsourcename(lex
),
331 isc_lex_getsourceline(lex
),
332 isc_result_totext(result
));
338 if (token
->type
== isc_tokentype_eol
||
339 token
->type
== isc_tokentype_eof
) {
340 (*callbacks
->error
)(callbacks
,
341 "dns_master_load: %s:%lu: unexpected end of %s",
342 isc_lex_getsourcename(lex
),
343 isc_lex_getsourceline(lex
),
347 return (ISC_R_UNEXPECTEDEND
);
349 return (ISC_R_SUCCESS
);
354 dns_loadctx_attach(dns_loadctx_t
*source
, dns_loadctx_t
**target
) {
356 REQUIRE(target
!= NULL
&& *target
== NULL
);
357 REQUIRE(DNS_LCTX_VALID(source
));
360 INSIST(source
->references
> 0);
361 source
->references
++;
362 INSIST(source
->references
!= 0); /* Overflow? */
363 UNLOCK(&source
->lock
);
369 dns_loadctx_detach(dns_loadctx_t
**lctxp
) {
371 isc_boolean_t need_destroy
= ISC_FALSE
;
373 REQUIRE(lctxp
!= NULL
);
375 REQUIRE(DNS_LCTX_VALID(lctx
));
378 INSIST(lctx
->references
> 0);
380 if (lctx
->references
== 0)
381 need_destroy
= ISC_TRUE
;
385 loadctx_destroy(lctx
);
390 incctx_destroy(isc_mem_t
*mctx
, dns_incctx_t
*ictx
) {
391 dns_incctx_t
*parent
;
394 parent
= ictx
->parent
;
397 isc_mem_put(mctx
, ictx
, sizeof(*ictx
));
399 if (parent
!= NULL
) {
406 loadctx_destroy(dns_loadctx_t
*lctx
) {
409 REQUIRE(DNS_LCTX_VALID(lctx
));
412 if (lctx
->inc
!= NULL
)
413 incctx_destroy(lctx
->mctx
, lctx
->inc
);
415 /* isc_lex_destroy() will close all open streams */
416 if (lctx
->lex
!= NULL
&& !lctx
->keep_lex
)
417 isc_lex_destroy(&lctx
->lex
);
419 if (lctx
->task
!= NULL
)
420 isc_task_detach(&lctx
->task
);
421 DESTROYLOCK(&lctx
->lock
);
423 isc_mem_attach(lctx
->mctx
, &mctx
);
424 isc_mem_detach(&lctx
->mctx
);
425 isc_mem_put(mctx
, lctx
, sizeof(*lctx
));
426 isc_mem_detach(&mctx
);
430 incctx_create(isc_mem_t
*mctx
, dns_name_t
*origin
, dns_incctx_t
**ictxp
) {
435 ictx
= isc_mem_get(mctx
, sizeof(*ictx
));
437 return (ISC_R_NOMEMORY
);
439 for (i
= 0; i
< NBUFS
; i
++) {
440 dns_fixedname_init(&ictx
->fixed
[i
]);
441 ictx
->in_use
[i
] = ISC_FALSE
;
444 ictx
->origin_in_use
= 0;
445 ictx
->origin
= dns_fixedname_name(&ictx
->fixed
[ictx
->origin_in_use
]);
446 ictx
->in_use
[ictx
->origin_in_use
] = ISC_TRUE
;
447 dns_name_toregion(origin
, &r
);
448 dns_name_fromregion(ictx
->origin
, &r
);
451 ictx
->current
= NULL
;
452 ictx
->glue_in_use
= -1;
453 ictx
->current_in_use
= -1;
455 ictx
->drop
= ISC_FALSE
;
457 ictx
->current_line
= 0;
460 return (ISC_R_SUCCESS
);
464 loadctx_create(isc_mem_t
*mctx
, unsigned int options
, dns_name_t
*top
,
465 dns_rdataclass_t zclass
, dns_name_t
*origin
,
466 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
467 dns_loaddonefunc_t done
, void *done_arg
, isc_lex_t
*lex
,
468 dns_loadctx_t
**lctxp
)
473 isc_lexspecials_t specials
;
475 REQUIRE(lctxp
!= NULL
&& *lctxp
== NULL
);
476 REQUIRE(callbacks
!= NULL
);
477 REQUIRE(callbacks
->add
!= NULL
);
478 REQUIRE(callbacks
->error
!= NULL
);
479 REQUIRE(callbacks
->warn
!= NULL
);
480 REQUIRE(mctx
!= NULL
);
481 REQUIRE(dns_name_isabsolute(top
));
482 REQUIRE(dns_name_isabsolute(origin
));
483 REQUIRE((task
== NULL
&& done
== NULL
) ||
484 (task
!= NULL
&& done
!= NULL
));
486 lctx
= isc_mem_get(mctx
, sizeof(*lctx
));
488 return (ISC_R_NOMEMORY
);
489 result
= isc_mutex_init(&lctx
->lock
);
490 if (result
!= ISC_R_SUCCESS
) {
491 isc_mem_put(mctx
, lctx
, sizeof(*lctx
));
492 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
493 "isc_mutex_init() failed: %s",
494 isc_result_totext(result
));
495 return (ISC_R_UNEXPECTED
);
499 result
= incctx_create(mctx
, origin
, &lctx
->inc
);
500 if (result
!= ISC_R_SUCCESS
)
505 lctx
->keep_lex
= ISC_TRUE
;
508 result
= isc_lex_create(mctx
, TOKENSIZ
, &lctx
->lex
);
509 if (result
!= ISC_R_SUCCESS
)
511 lctx
->keep_lex
= ISC_FALSE
;
512 memset(specials
, 0, sizeof(specials
));
516 isc_lex_setspecials(lctx
->lex
, specials
);
517 isc_lex_setcomments(lctx
->lex
, ISC_LEXCOMMENT_DNSMASTERFILE
);
520 lctx
->ttl_known
= ISC_FALSE
;
522 lctx
->default_ttl_known
= ISC_FALSE
;
523 lctx
->default_ttl
= 0;
524 lctx
->warn_1035
= ISC_TRUE
; /* XXX Argument? */
525 lctx
->warn_tcr
= ISC_TRUE
; /* XXX Argument? */
526 lctx
->warn_sigexpired
= ISC_TRUE
; /* XXX Argument? */
527 lctx
->options
= options
;
528 lctx
->seen_include
= ISC_FALSE
;
529 lctx
->zclass
= zclass
;
530 lctx
->result
= ISC_R_SUCCESS
;
532 dns_fixedname_init(&lctx
->fixed_top
);
533 lctx
->top
= dns_fixedname_name(&lctx
->fixed_top
);
534 dns_name_toregion(top
, &r
);
535 dns_name_fromregion(lctx
->top
, &r
);
537 lctx
->loop_cnt
= (done
!= NULL
) ? 100 : 0;
538 lctx
->callbacks
= callbacks
;
541 isc_task_attach(task
, &lctx
->task
);
543 lctx
->done_arg
= done_arg
;
544 lctx
->canceled
= ISC_FALSE
;
546 isc_mem_attach(mctx
, &lctx
->mctx
);
547 lctx
->references
= 1; /* Implicit attach. */
548 lctx
->magic
= DNS_LCTX_MAGIC
;
550 return (ISC_R_SUCCESS
);
553 incctx_destroy(mctx
, lctx
->inc
);
555 isc_mem_put(mctx
, lctx
, sizeof(*lctx
));
560 genname(char *name
, int it
, char *buffer
, size_t length
) {
561 char fmt
[sizeof("%04000000000d")];
573 while (*name
!= '\0') {
578 return (ISC_R_NOSPACE
);
580 isc_textregion_consume(&r
, 1);
584 /* Get format specifier. */
586 n
= sscanf(name
, "{%d,%u,%1[doxX]}",
587 &delta
, &width
, mode
);
592 n
= snprintf(fmt
, sizeof(fmt
),
596 n
= snprintf(fmt
, sizeof(fmt
),
597 "%%0%u%c", width
, mode
[0]);
600 return (DNS_R_SYNTAX
);
602 if (n
>= sizeof(fmt
))
603 return (ISC_R_NOSPACE
);
604 /* Skip past closing brace. */
605 while (*name
!= '\0' && *name
++ != '}')
608 n
= snprintf(numbuf
, sizeof(numbuf
), fmt
, it
+ delta
);
609 if (n
>= sizeof(numbuf
))
610 return (ISC_R_NOSPACE
);
612 while (*cp
!= '\0') {
614 return (ISC_R_NOSPACE
);
616 isc_textregion_consume(&r
, 1);
618 } else if (*name
== '\\') {
620 return (ISC_R_NOSPACE
);
622 isc_textregion_consume(&r
, 1);
626 return (ISC_R_NOSPACE
);
628 isc_textregion_consume(&r
, 1);
631 return (ISC_R_NOSPACE
);
633 isc_textregion_consume(&r
, 1);
637 return (ISC_R_NOSPACE
);
639 return (ISC_R_SUCCESS
);
643 generate(dns_loadctx_t
*lctx
, char *range
, char *lhs
, char *gtype
, char *rhs
,
644 const char *source
, unsigned int line
)
646 char *target_mem
= NULL
;
649 dns_fixedname_t ownerfixed
;
651 dns_rdata_t rdata
= DNS_RDATA_INIT
;
652 dns_rdatacallbacks_t
*callbacks
;
653 dns_rdatalist_t rdatalist
;
654 dns_rdatatype_t type
;
655 rdatalist_head_t head
;
657 int target_size
= MINTSIZ
; /* only one rdata at a time */
662 unsigned int start
, stop
, step
, i
;
666 callbacks
= lctx
->callbacks
;
667 dns_fixedname_init(&ownerfixed
);
668 owner
= dns_fixedname_name(&ownerfixed
);
671 target_mem
= isc_mem_get(lctx
->mctx
, target_size
);
672 rhsbuf
= isc_mem_get(lctx
->mctx
, DNS_MASTER_BUFSZ
);
673 lhsbuf
= isc_mem_get(lctx
->mctx
, DNS_MASTER_BUFSZ
);
674 if (target_mem
== NULL
|| rhsbuf
== NULL
|| lhsbuf
== NULL
) {
675 result
= ISC_R_NOMEMORY
;
678 isc_buffer_init(&target
, target_mem
, target_size
);
680 n
= sscanf(range
, "%u-%u/%u", &start
, &stop
, &step
);
681 if (n
< 2 || stop
< start
) {
682 (*callbacks
->error
)(callbacks
,
683 "%s: %s:%lu: invalid range '%s'",
684 "$GENERATE", source
, line
, range
);
685 result
= DNS_R_SYNTAX
;
695 r
.length
= strlen(gtype
);
696 result
= dns_rdatatype_fromtext(&type
, &r
);
697 if (result
!= ISC_R_SUCCESS
) {
698 (*callbacks
->error
)(callbacks
,
699 "%s: %s:%lu: unknown RR type '%s'",
700 "$GENERATE", source
, line
, gtype
);
705 case dns_rdatatype_ns
:
706 case dns_rdatatype_ptr
:
707 case dns_rdatatype_cname
:
708 case dns_rdatatype_dname
:
711 case dns_rdatatype_a
:
712 case dns_rdatatype_aaaa
:
713 if (lctx
->zclass
== dns_rdataclass_in
||
714 lctx
->zclass
== dns_rdataclass_hs
)
718 (*callbacks
->error
)(callbacks
,
719 "%s: %s:%lu: unsupported type '%s'",
720 "$GENERATE", source
, line
, gtype
);
721 result
= ISC_R_NOTIMPLEMENTED
;
725 ISC_LIST_INIT(rdatalist
.rdata
);
726 ISC_LINK_INIT(&rdatalist
, link
);
727 for (i
= start
; i
<= stop
; i
+= step
) {
728 result
= genname(lhs
, i
, lhsbuf
, DNS_MASTER_BUFSZ
);
729 if (result
!= ISC_R_SUCCESS
)
731 result
= genname(rhs
, i
, rhsbuf
, DNS_MASTER_BUFSZ
);
732 if (result
!= ISC_R_SUCCESS
)
735 isc_buffer_init(&buffer
, lhsbuf
, strlen(lhsbuf
));
736 isc_buffer_add(&buffer
, strlen(lhsbuf
));
737 isc_buffer_setactive(&buffer
, strlen(lhsbuf
));
738 result
= dns_name_fromtext(owner
, &buffer
, ictx
->origin
,
740 if (result
!= ISC_R_SUCCESS
)
743 if ((lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
744 (lctx
->options
& DNS_MASTER_SLAVE
) == 0 &&
745 !dns_name_issubdomain(owner
, lctx
->top
))
747 char namebuf
[DNS_NAME_FORMATSIZE
];
748 dns_name_format(owner
, namebuf
, sizeof(namebuf
));
750 * Ignore out-of-zone data.
752 (*callbacks
->warn
)(callbacks
,
754 "ignoring out-of-zone data (%s)",
755 source
, line
, namebuf
);
759 isc_buffer_init(&buffer
, rhsbuf
, strlen(rhsbuf
));
760 isc_buffer_add(&buffer
, strlen(rhsbuf
));
761 isc_buffer_setactive(&buffer
, strlen(rhsbuf
));
763 result
= isc_lex_openbuffer(lctx
->lex
, &buffer
);
764 if (result
!= ISC_R_SUCCESS
)
767 isc_buffer_init(&target
, target_mem
, target_size
);
768 result
= dns_rdata_fromtext(&rdata
, lctx
->zclass
, type
,
769 lctx
->lex
, ictx
->origin
, 0,
770 lctx
->mctx
, &target
, callbacks
);
771 RUNTIME_CHECK(isc_lex_close(lctx
->lex
) == ISC_R_SUCCESS
);
772 if (result
!= ISC_R_SUCCESS
)
775 rdatalist
.type
= type
;
776 rdatalist
.covers
= 0;
777 rdatalist
.rdclass
= lctx
->zclass
;
778 rdatalist
.ttl
= lctx
->ttl
;
779 ISC_LIST_PREPEND(head
, &rdatalist
, link
);
780 ISC_LIST_APPEND(rdatalist
.rdata
, &rdata
, link
);
781 result
= commit(callbacks
, lctx
, &head
, owner
, source
, line
);
782 ISC_LIST_UNLINK(rdatalist
.rdata
, &rdata
, link
);
783 if (result
!= ISC_R_SUCCESS
)
785 dns_rdata_reset(&rdata
);
787 result
= ISC_R_SUCCESS
;
791 if (result
== ISC_R_NOMEMORY
)
792 (*callbacks
->error
)(callbacks
, "$GENERATE: %s",
793 dns_result_totext(result
));
795 (*callbacks
->error
)(callbacks
, "$GENERATE: %s:%lu: %s",
796 source
, line
, dns_result_totext(result
));
799 INSIST(result
!= ISC_R_SUCCESS
);
802 if (target_mem
!= NULL
)
803 isc_mem_put(lctx
->mctx
, target_mem
, target_size
);
805 isc_mem_put(lctx
->mctx
, lhsbuf
, DNS_MASTER_BUFSZ
);
807 isc_mem_put(lctx
->mctx
, rhsbuf
, DNS_MASTER_BUFSZ
);
812 limit_ttl(dns_rdatacallbacks_t
*callbacks
, const char *source
, unsigned int line
,
815 if (*ttlp
> 0x7fffffffUL
) {
816 (callbacks
->warn
)(callbacks
,
818 "$TTL %lu > MAXTTL, "
828 check_ns(dns_loadctx_t
*lctx
, isc_token_t
*token
, const char *source
,
832 isc_result_t result
= ISC_R_SUCCESS
;
833 void (*callback
)(struct dns_rdatacallbacks
*, const char *, ...);
835 if ((lctx
->options
& DNS_MASTER_FATALNS
) != 0)
836 callback
= lctx
->callbacks
->error
;
838 callback
= lctx
->callbacks
->warn
;
840 if (token
->type
== isc_tokentype_string
) {
842 struct in6_addr addr6
;
844 tmp
= isc_mem_strdup(lctx
->mctx
, DNS_AS_STR(*token
));
846 return (ISC_R_NOMEMORY
);
848 * Catch both "1.2.3.4" and "1.2.3.4."
850 if (tmp
[strlen(tmp
) - 1] == '.')
851 tmp
[strlen(tmp
) - 1] = '\0';
852 if (inet_aton(tmp
, &addr
) == 1 ||
853 inet_pton(AF_INET6
, tmp
, &addr6
) == 1)
854 result
= DNS_R_NSISADDRESS
;
856 if (result
!= ISC_R_SUCCESS
)
857 (*callback
)(lctx
->callbacks
, "%s:%lu: NS record '%s' "
858 "appears to be an address",
859 source
, line
, DNS_AS_STR(*token
));
861 isc_mem_free(lctx
->mctx
, tmp
);
866 load(dns_loadctx_t
*lctx
) {
867 dns_rdataclass_t rdclass
;
868 dns_rdatatype_t type
, covers
;
869 isc_uint32_t ttl_offset
= 0;
870 dns_name_t
*new_name
;
871 isc_boolean_t current_has_delegation
= ISC_FALSE
;
872 isc_boolean_t done
= ISC_FALSE
;
873 isc_boolean_t finish_origin
= ISC_FALSE
;
874 isc_boolean_t finish_include
= ISC_FALSE
;
875 isc_boolean_t read_till_eol
= ISC_FALSE
;
876 isc_boolean_t initialws
;
877 char *include_file
= NULL
;
879 isc_result_t result
= ISC_R_UNEXPECTED
;
880 rdatalist_head_t glue_list
;
881 rdatalist_head_t current_list
;
882 dns_rdatalist_t
*this;
883 dns_rdatalist_t
*rdatalist
= NULL
;
884 dns_rdatalist_t
*new_rdatalist
;
886 int rdlcount_save
= 0;
887 int rdatalist_size
= 0;
890 isc_buffer_t target_ft
;
891 isc_buffer_t target_save
;
892 dns_rdata_t
*rdata
= NULL
;
893 dns_rdata_t
*new_rdata
;
895 int rdcount_save
= 0;
897 unsigned char *target_mem
= NULL
;
898 int target_size
= TSIZ
;
900 unsigned int loop_cnt
= 0;
902 dns_rdatacallbacks_t
*callbacks
;
908 const char *source
= "";
909 unsigned long line
= 0;
910 isc_boolean_t explicit_ttl
;
912 char classname1
[DNS_RDATACLASS_FORMATSIZE
];
913 char classname2
[DNS_RDATACLASS_FORMATSIZE
];
914 unsigned int options
= 0;
916 REQUIRE(DNS_LCTX_VALID(lctx
));
917 callbacks
= lctx
->callbacks
;
921 ISC_LIST_INIT(glue_list
);
922 ISC_LIST_INIT(current_list
);
924 isc_stdtime_get(&now
);
927 * Allocate target_size of buffer space. This is greater than twice
928 * the maximum individual RR data size.
930 target_mem
= isc_mem_get(mctx
, target_size
);
931 if (target_mem
== NULL
) {
932 result
= ISC_R_NOMEMORY
;
933 goto log_and_cleanup
;
935 isc_buffer_init(&target
, target_mem
, target_size
);
936 target_save
= target
;
938 if ((lctx
->options
& DNS_MASTER_CHECKNAMES
) != 0)
939 options
|= DNS_RDATA_CHECKNAMES
;
940 if ((lctx
->options
& DNS_MASTER_CHECKNAMESFAIL
) != 0)
941 options
|= DNS_RDATA_CHECKNAMESFAIL
;
942 source
= isc_lex_getsourcename(lctx
->lex
);
944 initialws
= ISC_FALSE
;
945 line
= isc_lex_getsourceline(lctx
->lex
);
946 GETTOKEN(lctx
->lex
, ISC_LEXOPT_INITIALWS
, &token
, ISC_TRUE
);
947 line
= isc_lex_getsourceline(lctx
->lex
);
949 if (token
.type
== isc_tokentype_eof
) {
951 WARNUNEXPECTEDEOF(lctx
->lex
);
952 /* Pop the include stack? */
953 if (ictx
->parent
!= NULL
) {
955 lctx
->inc
= ictx
->parent
;
957 incctx_destroy(lctx
->mctx
, ictx
);
958 RUNTIME_CHECK(isc_lex_close(lctx
->lex
) == ISC_R_SUCCESS
);
959 line
= isc_lex_getsourceline(lctx
->lex
);
960 source
= isc_lex_getsourcename(lctx
->lex
);
969 if (token
.type
== isc_tokentype_eol
) {
970 read_till_eol
= ISC_FALSE
;
971 continue; /* blank line */
977 if (token
.type
== isc_tokentype_initialws
) {
979 * Still working on the same name.
981 initialws
= ISC_TRUE
;
982 } else if (token
.type
== isc_tokentype_string
) {
987 * "$ORIGIN" and "$INCLUDE" can both take domain names.
988 * The processing of "$ORIGIN" and "$INCLUDE" extends
989 * across the normal domain name processing.
992 if (strcasecmp(DNS_AS_STR(token
), "$ORIGIN") == 0) {
993 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
994 finish_origin
= ISC_TRUE
;
995 } else if (strcasecmp(DNS_AS_STR(token
),
997 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
999 dns_ttl_fromtext(&token
.value
.as_textregion
,
1001 if (MANYERRS(lctx
, result
)) {
1002 SETRESULT(lctx
, result
);
1004 } else if (result
!= ISC_R_SUCCESS
)
1005 goto insist_and_cleanup
;
1006 limit_ttl(callbacks
, source
, line
, &lctx
->ttl
);
1007 lctx
->default_ttl
= lctx
->ttl
;
1008 lctx
->default_ttl_known
= ISC_TRUE
;
1011 } else if (strcasecmp(DNS_AS_STR(token
),
1014 if ((lctx
->options
& DNS_MASTER_NOINCLUDE
)
1017 (callbacks
->error
)(callbacks
,
1018 "%s: %s:%lu: $INCLUDE not allowed",
1021 result
= DNS_R_REFUSED
;
1022 goto insist_and_cleanup
;
1024 if (ttl_offset
!= 0) {
1025 (callbacks
->error
)(callbacks
,
1026 "%s: %s:%lu: $INCLUDE "
1027 "may not be used with $DATE",
1030 result
= DNS_R_SYNTAX
;
1031 goto insist_and_cleanup
;
1033 GETTOKEN(lctx
->lex
, ISC_LEXOPT_QSTRING
, &token
,
1035 if (include_file
!= NULL
)
1036 isc_mem_free(mctx
, include_file
);
1037 include_file
= isc_mem_strdup(mctx
,
1039 if (include_file
== NULL
) {
1040 result
= ISC_R_NOMEMORY
;
1041 goto log_and_cleanup
;
1043 GETTOKEN(lctx
->lex
, 0, &token
, ISC_TRUE
);
1045 if (token
.type
== isc_tokentype_eol
||
1046 token
.type
== isc_tokentype_eof
) {
1047 if (token
.type
== isc_tokentype_eof
)
1048 WARNUNEXPECTEDEOF(lctx
->lex
);
1049 isc_lex_ungettoken(lctx
->lex
, &token
);
1053 result
= pushfile(include_file
,
1054 ictx
->origin
, lctx
);
1055 if (MANYERRS(lctx
, result
)) {
1056 SETRESULT(lctx
, result
);
1057 LOGITFILE(result
, include_file
);
1059 } else if (result
!= ISC_R_SUCCESS
) {
1060 LOGITFILE(result
, include_file
);
1061 goto insist_and_cleanup
;
1064 line
= isc_lex_getsourceline(lctx
->lex
);
1066 isc_lex_getsourcename(lctx
->lex
);
1070 * There is an origin field. Fall through
1071 * to domain name processing code and do
1072 * the actual inclusion later.
1074 finish_include
= ISC_TRUE
;
1075 } else if (strcasecmp(DNS_AS_STR(token
),
1077 isc_int64_t dump_time64
;
1078 isc_stdtime_t dump_time
, current_time
;
1079 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1080 isc_stdtime_get(¤t_time
);
1081 result
= dns_time64_fromtext(DNS_AS_STR(token
),
1083 if (MANYERRS(lctx
, result
)) {
1084 SETRESULT(lctx
, result
);
1087 } else if (result
!= ISC_R_SUCCESS
)
1088 goto log_and_cleanup
;
1089 dump_time
= (isc_stdtime_t
)dump_time64
;
1090 if (dump_time
!= dump_time64
) {
1091 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1092 "%s: %s:%lu: $DATE outside epoch",
1093 "dns_master_load", source
, line
);
1094 result
= ISC_R_UNEXPECTED
;
1095 goto insist_and_cleanup
;
1097 if (dump_time
> current_time
) {
1098 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1100 "$DATE in future, using current date",
1101 "dns_master_load", source
, line
);
1102 dump_time
= current_time
;
1104 ttl_offset
= current_time
- dump_time
;
1107 } else if (strcasecmp(DNS_AS_STR(token
),
1108 "$GENERATE") == 0) {
1113 isc_mem_free(mctx
, range
);
1115 isc_mem_free(mctx
, lhs
);
1117 isc_mem_free(mctx
, gtype
);
1119 isc_mem_free(mctx
, rhs
);
1121 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1122 range
= isc_mem_strdup(mctx
,
1124 if (range
== NULL
) {
1125 result
= ISC_R_NOMEMORY
;
1126 goto log_and_cleanup
;
1129 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1130 lhs
= isc_mem_strdup(mctx
, DNS_AS_STR(token
));
1132 result
= ISC_R_NOMEMORY
;
1133 goto log_and_cleanup
;
1136 explicit_ttl
= ISC_FALSE
;
1138 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1139 if (dns_rdataclass_fromtext(&rdclass
,
1140 &token
.value
.as_textregion
)
1142 GETTOKEN(lctx
->lex
, 0, &token
,
1146 if (dns_ttl_fromtext(&token
.value
.as_textregion
,
1149 limit_ttl(callbacks
, source
, line
,
1151 lctx
->ttl_known
= ISC_TRUE
;
1152 explicit_ttl
= ISC_TRUE
;
1153 GETTOKEN(lctx
->lex
, 0, &token
,
1158 dns_rdataclass_fromtext(&rdclass
,
1159 &token
.value
.as_textregion
)
1161 GETTOKEN(lctx
->lex
, 0, &token
,
1164 gtype
= isc_mem_strdup(mctx
,
1166 if (gtype
== NULL
) {
1167 result
= ISC_R_NOMEMORY
;
1168 goto log_and_cleanup
;
1171 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1172 rhs
= isc_mem_strdup(mctx
, DNS_AS_STR(token
));
1174 result
= ISC_R_NOMEMORY
;
1175 goto log_and_cleanup
;
1177 if (!lctx
->ttl_known
&&
1178 !lctx
->default_ttl_known
) {
1179 (*callbacks
->error
)(callbacks
,
1180 "%s: %s:%lu: no TTL specified",
1181 "dns_master_load", source
, line
);
1182 result
= DNS_R_NOTTL
;
1183 if (MANYERRS(lctx
, result
)) {
1184 SETRESULT(lctx
, result
);
1186 } else if (result
!= ISC_R_SUCCESS
)
1187 goto insist_and_cleanup
;
1188 } else if (!explicit_ttl
&&
1189 lctx
->default_ttl_known
) {
1190 lctx
->ttl
= lctx
->default_ttl
;
1193 * If the class specified does not match the
1194 * zone's class print out a error message and
1197 if (rdclass
!= 0 && rdclass
!= lctx
->zclass
) {
1200 result
= generate(lctx
, range
, lhs
, gtype
, rhs
,
1202 if (MANYERRS(lctx
, result
)) {
1203 SETRESULT(lctx
, result
);
1204 } else if (result
!= ISC_R_SUCCESS
)
1205 goto insist_and_cleanup
;
1208 } else if (strncasecmp(DNS_AS_STR(token
),
1210 (callbacks
->error
)(callbacks
,
1212 "unknown $ directive '%s'",
1213 "dns_master_load", source
, line
,
1215 result
= DNS_R_SYNTAX
;
1216 if (MANYERRS(lctx
, result
)) {
1217 SETRESULT(lctx
, result
);
1218 } else if (result
!= ISC_R_SUCCESS
)
1219 goto insist_and_cleanup
;
1223 * Normal processing resumes.
1225 * Find a free name buffer.
1227 for (new_in_use
= 0; new_in_use
< NBUFS
; new_in_use
++)
1228 if (!ictx
->in_use
[new_in_use
])
1230 INSIST(new_in_use
< NBUFS
);
1231 dns_fixedname_init(&ictx
->fixed
[new_in_use
]);
1232 new_name
= dns_fixedname_name(&ictx
->fixed
[new_in_use
]);
1233 isc_buffer_init(&buffer
, token
.value
.as_region
.base
,
1234 token
.value
.as_region
.length
);
1235 isc_buffer_add(&buffer
, token
.value
.as_region
.length
);
1236 isc_buffer_setactive(&buffer
,
1237 token
.value
.as_region
.length
);
1238 result
= dns_name_fromtext(new_name
, &buffer
,
1239 ictx
->origin
, ISC_FALSE
, NULL
);
1240 if (MANYERRS(lctx
, result
)) {
1241 SETRESULT(lctx
, result
);
1243 read_till_eol
= ISC_TRUE
;
1245 } else if (result
!= ISC_R_SUCCESS
)
1246 goto log_and_cleanup
;
1249 * Finish $ORIGIN / $INCLUDE processing if required.
1251 if (finish_origin
) {
1252 if (ictx
->origin_in_use
!= -1)
1253 ictx
->in_use
[ictx
->origin_in_use
] =
1255 ictx
->origin_in_use
= new_in_use
;
1256 ictx
->in_use
[ictx
->origin_in_use
] = ISC_TRUE
;
1257 ictx
->origin
= new_name
;
1258 finish_origin
= ISC_FALSE
;
1262 if (finish_include
) {
1263 finish_include
= ISC_FALSE
;
1264 result
= pushfile(include_file
, new_name
, lctx
);
1265 if (MANYERRS(lctx
, result
)) {
1266 SETRESULT(lctx
, result
);
1267 LOGITFILE(result
, include_file
);
1269 } else if (result
!= ISC_R_SUCCESS
) {
1270 LOGITFILE(result
, include_file
);
1271 goto insist_and_cleanup
;
1274 line
= isc_lex_getsourceline(lctx
->lex
);
1275 source
= isc_lex_getsourcename(lctx
->lex
);
1280 * "$" Processing Finished
1284 * If we are processing glue and the new name does
1285 * not match the current glue name, commit the glue
1286 * and pop stacks leaving us in 'normal' processing
1287 * state. Linked lists are undone by commit().
1289 if (ictx
->glue
!= NULL
&&
1290 dns_name_compare(ictx
->glue
, new_name
) != 0) {
1291 result
= commit(callbacks
, lctx
, &glue_list
,
1294 if (MANYERRS(lctx
, result
)) {
1295 SETRESULT(lctx
, result
);
1296 } else if (result
!= ISC_R_SUCCESS
)
1297 goto insist_and_cleanup
;
1298 if (ictx
->glue_in_use
!= -1)
1299 ictx
->in_use
[ictx
->glue_in_use
] =
1301 ictx
->glue_in_use
= -1;
1303 rdcount
= rdcount_save
;
1304 rdlcount
= rdlcount_save
;
1305 target
= target_save
;
1309 * If we are in 'normal' processing state and the new
1310 * name does not match the current name, see if the
1311 * new name is for glue and treat it as such,
1312 * otherwise we have a new name so commit what we
1315 if ((ictx
->glue
== NULL
) && (ictx
->current
== NULL
||
1316 dns_name_compare(ictx
->current
, new_name
) != 0)) {
1317 if (current_has_delegation
&&
1318 is_glue(¤t_list
, new_name
)) {
1319 rdcount_save
= rdcount
;
1320 rdlcount_save
= rdlcount
;
1321 target_save
= target
;
1322 ictx
->glue
= new_name
;
1323 ictx
->glue_in_use
= new_in_use
;
1324 ictx
->in_use
[ictx
->glue_in_use
] =
1327 result
= commit(callbacks
, lctx
,
1331 ictx
->current_line
);
1332 if (MANYERRS(lctx
, result
)) {
1333 SETRESULT(lctx
, result
);
1334 } else if (result
!= ISC_R_SUCCESS
)
1335 goto insist_and_cleanup
;
1338 if (ictx
->current_in_use
!= -1)
1339 ictx
->in_use
[ictx
->current_in_use
] =
1341 ictx
->current_in_use
= new_in_use
;
1342 ictx
->in_use
[ictx
->current_in_use
] =
1344 ictx
->current
= new_name
;
1345 current_has_delegation
= ISC_FALSE
;
1346 isc_buffer_init(&target
, target_mem
,
1350 if ((lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
1351 (lctx
->options
& DNS_MASTER_SLAVE
) == 0 &&
1352 !dns_name_issubdomain(new_name
, lctx
->top
))
1354 char namebuf
[DNS_NAME_FORMATSIZE
];
1355 dns_name_format(new_name
, namebuf
,
1358 * Ignore out-of-zone data.
1360 (*callbacks
->warn
)(callbacks
,
1362 "ignoring out-of-zone data (%s)",
1363 source
, line
, namebuf
);
1364 ictx
->drop
= ISC_TRUE
;
1366 ictx
->drop
= ISC_FALSE
;
1368 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1369 "%s:%lu: isc_lex_gettoken() returned "
1370 "unexpeced token type (%d)",
1371 source
, line
, token
.type
);
1372 result
= ISC_R_UNEXPECTED
;
1373 if (MANYERRS(lctx
, result
)) {
1374 SETRESULT(lctx
, result
);
1377 } else if (result
!= ISC_R_SUCCESS
)
1378 goto insist_and_cleanup
;
1382 * Find TTL, class and type. Both TTL and class are optional
1383 * and may occur in any order if they exist. TTL and class
1384 * come before type which must exist.
1386 * [<TTL>] [<class>] <type> <RDATA>
1387 * [<class>] [<TTL>] <type> <RDATA>
1393 GETTOKEN(lctx
->lex
, 0, &token
, initialws
);
1396 if (token
.type
== isc_tokentype_eol
) {
1397 read_till_eol
= ISC_FALSE
;
1398 continue; /* blank line */
1401 if (token
.type
== isc_tokentype_eof
) {
1402 WARNUNEXPECTEDEOF(lctx
->lex
);
1403 read_till_eol
= ISC_FALSE
;
1404 isc_lex_ungettoken(lctx
->lex
, &token
);
1408 if (ictx
->current
== NULL
) {
1409 (*callbacks
->error
)(callbacks
,
1410 "%s:%lu: no current owner name",
1412 result
= DNS_R_NOOWNER
;
1413 if (MANYERRS(lctx
, result
)) {
1414 SETRESULT(lctx
, result
);
1415 read_till_eol
= ISC_TRUE
;
1417 } else if (result
!= ISC_R_SUCCESS
)
1418 goto insist_and_cleanup
;
1422 if (dns_rdataclass_fromtext(&rdclass
,
1423 &token
.value
.as_textregion
)
1425 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1427 explicit_ttl
= ISC_FALSE
;
1428 if (dns_ttl_fromtext(&token
.value
.as_textregion
, &lctx
->ttl
)
1430 limit_ttl(callbacks
, source
, line
, &lctx
->ttl
);
1431 explicit_ttl
= ISC_TRUE
;
1432 lctx
->ttl_known
= ISC_TRUE
;
1433 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1436 if (token
.type
!= isc_tokentype_string
) {
1437 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1438 "isc_lex_gettoken() returned unexpected token type");
1439 result
= ISC_R_UNEXPECTED
;
1440 if (MANYERRS(lctx
, result
)) {
1441 SETRESULT(lctx
, result
);
1442 read_till_eol
= ISC_TRUE
;
1444 } else if (result
!= ISC_R_SUCCESS
)
1445 goto insist_and_cleanup
;
1449 dns_rdataclass_fromtext(&rdclass
,
1450 &token
.value
.as_textregion
)
1452 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1454 if (token
.type
!= isc_tokentype_string
) {
1455 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1456 "isc_lex_gettoken() returned unexpected token type");
1457 result
= ISC_R_UNEXPECTED
;
1458 if (MANYERRS(lctx
, result
)) {
1459 SETRESULT(lctx
, result
);
1460 read_till_eol
= ISC_TRUE
;
1462 } else if (result
!= ISC_R_SUCCESS
)
1463 goto insist_and_cleanup
;
1466 result
= dns_rdatatype_fromtext(&type
,
1467 &token
.value
.as_textregion
);
1468 if (result
!= ISC_R_SUCCESS
) {
1469 (*callbacks
->warn
)(callbacks
,
1470 "%s:%lu: unknown RR type '%.*s'",
1472 token
.value
.as_textregion
.length
,
1473 token
.value
.as_textregion
.base
);
1474 if (MANYERRS(lctx
, result
)) {
1475 SETRESULT(lctx
, result
);
1476 read_till_eol
= ISC_TRUE
;
1478 } else if (result
!= ISC_R_SUCCESS
)
1479 goto insist_and_cleanup
;
1483 * If the class specified does not match the zone's class
1484 * print out a error message and exit.
1486 if (rdclass
!= 0 && rdclass
!= lctx
->zclass
) {
1489 dns_rdataclass_format(rdclass
, classname1
,
1490 sizeof(classname1
));
1491 dns_rdataclass_format(lctx
->zclass
, classname2
,
1492 sizeof(classname2
));
1493 (*callbacks
->error
)(callbacks
,
1494 "%s:%lu: class '%s' != "
1497 classname1
, classname2
);
1498 result
= DNS_R_BADCLASS
;
1499 if (MANYERRS(lctx
, result
)) {
1500 SETRESULT(lctx
, result
);
1501 read_till_eol
= ISC_TRUE
;
1503 } else if (result
!= ISC_R_SUCCESS
)
1504 goto insist_and_cleanup
;
1507 if (type
== dns_rdatatype_ns
&& ictx
->glue
== NULL
)
1508 current_has_delegation
= ISC_TRUE
;
1511 * RFC 1123: MD and MF are not allowed to be loaded from
1514 if ((lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
1515 (lctx
->options
& DNS_MASTER_SLAVE
) == 0 &&
1516 (type
== dns_rdatatype_md
|| type
== dns_rdatatype_mf
)) {
1517 char typename
[DNS_RDATATYPE_FORMATSIZE
];
1519 result
= DNS_R_OBSOLETE
;
1521 dns_rdatatype_format(type
, typename
, sizeof(typename
));
1522 (*callbacks
->error
)(callbacks
,
1523 "%s:%lu: %s '%s': %s",
1526 dns_result_totext(result
));
1527 if (MANYERRS(lctx
, result
)) {
1528 SETRESULT(lctx
, result
);
1530 goto insist_and_cleanup
;
1534 * Find a rdata structure.
1536 if (rdcount
== rdata_size
) {
1537 new_rdata
= grow_rdata(rdata_size
+ RDSZ
, rdata
,
1538 rdata_size
, ¤t_list
,
1540 if (new_rdata
== NULL
) {
1541 result
= ISC_R_NOMEMORY
;
1542 goto log_and_cleanup
;
1549 * Peek at the NS record.
1551 if (type
== dns_rdatatype_ns
&&
1552 lctx
->zclass
== dns_rdataclass_in
&&
1553 (lctx
->options
& DNS_MASTER_CHECKNS
) != 0) {
1555 GETTOKEN(lctx
->lex
, 0, &token
, ISC_FALSE
);
1556 result
= check_ns(lctx
, &token
, source
, line
);
1557 isc_lex_ungettoken(lctx
->lex
, &token
);
1558 if ((lctx
->options
& DNS_MASTER_FATALNS
) != 0) {
1559 if (MANYERRS(lctx
, result
)) {
1560 SETRESULT(lctx
, result
);
1561 } else if (result
!= ISC_R_SUCCESS
)
1562 goto insist_and_cleanup
;
1569 options
&= ~DNS_RDATA_CHECKREVERSE
;
1570 if ((lctx
->options
& DNS_MASTER_CHECKNAMES
) != 0) {
1574 name
= (ictx
->glue
!= NULL
) ? ictx
-> glue
:
1576 ok
= dns_rdata_checkowner(name
, lctx
->zclass
, type
,
1579 char namebuf
[DNS_NAME_FORMATSIZE
];
1581 dns_name_format(name
, namebuf
, sizeof(namebuf
));
1582 result
= DNS_R_BADOWNERNAME
;
1583 desc
= dns_result_totext(result
);
1584 if ((lctx
->options
& DNS_MASTER_CHECKNAMESFAIL
) != 0) {
1585 (*callbacks
->error
)(callbacks
,
1589 if (MANYERRS(lctx
, result
)) {
1590 SETRESULT(lctx
, result
);
1591 } else if (result
!= ISC_R_SUCCESS
)
1594 (*callbacks
->warn
)(callbacks
,
1600 if (type
== dns_rdatatype_ptr
&&
1601 (dns_name_issubdomain(name
, &in_addr_arpa
) ||
1602 dns_name_issubdomain(name
, &ip6_arpa
) ||
1603 dns_name_issubdomain(name
, &ip6_int
)))
1604 options
|= DNS_RDATA_CHECKREVERSE
;
1608 * Read rdata contents.
1610 dns_rdata_init(&rdata
[rdcount
]);
1612 result
= dns_rdata_fromtext(&rdata
[rdcount
], lctx
->zclass
,
1613 type
, lctx
->lex
, ictx
->origin
,
1614 options
, lctx
->mctx
, &target
,
1616 if (MANYERRS(lctx
, result
)) {
1617 SETRESULT(lctx
, result
);
1619 } else if (result
!= ISC_R_SUCCESS
)
1620 goto insist_and_cleanup
;
1627 if (type
== dns_rdatatype_soa
&&
1628 (lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
1629 dns_name_compare(ictx
->current
, lctx
->top
) != 0) {
1630 char namebuf
[DNS_NAME_FORMATSIZE
];
1631 dns_name_format(ictx
->current
, namebuf
,
1633 (*callbacks
->error
)(callbacks
,
1635 "record not at top of zone (%s)",
1636 source
, line
, namebuf
);
1637 result
= DNS_R_NOTZONETOP
;
1638 if (MANYERRS(lctx
, result
)) {
1639 SETRESULT(lctx
, result
);
1640 read_till_eol
= ISC_TRUE
;
1643 } else if (result
!= ISC_R_SUCCESS
)
1644 goto insist_and_cleanup
;
1648 if (type
== dns_rdatatype_rrsig
||
1649 type
== dns_rdatatype_sig
)
1650 covers
= dns_rdata_covers(&rdata
[rdcount
]);
1654 if (!lctx
->ttl_known
&& !lctx
->default_ttl_known
) {
1655 if (type
== dns_rdatatype_soa
) {
1656 (*callbacks
->warn
)(callbacks
,
1657 "%s:%lu: no TTL specified; "
1658 "using SOA MINTTL instead",
1660 lctx
->ttl
= dns_soa_getminimum(&rdata
[rdcount
]);
1661 limit_ttl(callbacks
, source
, line
, &lctx
->ttl
);
1662 lctx
->default_ttl
= lctx
->ttl
;
1663 lctx
->default_ttl_known
= ISC_TRUE
;
1664 } else if ((lctx
->options
& DNS_MASTER_HINT
) != 0) {
1666 * Zero TTL's are fine for hints.
1669 lctx
->default_ttl
= lctx
->ttl
;
1670 lctx
->default_ttl_known
= ISC_TRUE
;
1672 (*callbacks
->warn
)(callbacks
,
1673 "%s:%lu: no TTL specified; "
1676 result
= DNS_R_NOTTL
;
1677 if (MANYERRS(lctx
, result
)) {
1678 SETRESULT(lctx
, result
);
1681 goto insist_and_cleanup
;
1684 } else if (!explicit_ttl
&& lctx
->default_ttl_known
) {
1685 lctx
->ttl
= lctx
->default_ttl
;
1686 } else if (!explicit_ttl
&& lctx
->warn_1035
) {
1687 (*callbacks
->warn
)(callbacks
,
1689 "using RFC 1035 TTL semantics",
1691 lctx
->warn_1035
= ISC_FALSE
;
1694 if (type
== dns_rdatatype_rrsig
&& lctx
->warn_sigexpired
) {
1695 dns_rdata_rrsig_t sig
;
1696 (void)dns_rdata_tostruct(&rdata
[rdcount
], &sig
, NULL
);
1697 if (isc_serial_lt(sig
.timeexpire
, now
)) {
1698 (*callbacks
->warn
)(callbacks
,
1700 "signature has expired",
1702 lctx
->warn_sigexpired
= ISC_FALSE
;
1706 if ((type
== dns_rdatatype_sig
|| type
== dns_rdatatype_nxt
) &&
1707 lctx
->warn_tcr
&& (lctx
->options
& DNS_MASTER_ZONE
) != 0 &&
1708 (lctx
->options
& DNS_MASTER_SLAVE
) == 0) {
1709 (*callbacks
->warn
)(callbacks
, "%s:%lu: old style DNSSEC "
1710 " zone detected", source
, line
);
1711 lctx
->warn_tcr
= ISC_FALSE
;
1714 if ((lctx
->options
& DNS_MASTER_AGETTL
) != 0) {
1716 * Adjust the TTL for $DATE. If the RR has already
1717 * expired, ignore it.
1719 if (lctx
->ttl
< ttl_offset
)
1721 lctx
->ttl
-= ttl_offset
;
1725 * Find type in rdatalist.
1726 * If it does not exist create new one and prepend to list
1727 * as this will mimimise list traversal.
1729 if (ictx
->glue
!= NULL
)
1730 this = ISC_LIST_HEAD(glue_list
);
1732 this = ISC_LIST_HEAD(current_list
);
1734 while (this != NULL
) {
1735 if (this->type
== type
&& this->covers
== covers
)
1737 this = ISC_LIST_NEXT(this, link
);
1741 if (rdlcount
== rdatalist_size
) {
1743 grow_rdatalist(rdatalist_size
+ RDLSZ
,
1749 if (new_rdatalist
== NULL
) {
1750 result
= ISC_R_NOMEMORY
;
1751 goto log_and_cleanup
;
1753 rdatalist
= new_rdatalist
;
1754 rdatalist_size
+= RDLSZ
;
1756 this = &rdatalist
[rdlcount
++];
1758 this->covers
= covers
;
1759 this->rdclass
= lctx
->zclass
;
1760 this->ttl
= lctx
->ttl
;
1761 ISC_LIST_INIT(this->rdata
);
1762 if (ictx
->glue
!= NULL
)
1763 ISC_LIST_INITANDPREPEND(glue_list
, this, link
);
1765 ISC_LIST_INITANDPREPEND(current_list
, this,
1767 } else if (this->ttl
!= lctx
->ttl
) {
1768 (*callbacks
->warn
)(callbacks
,
1770 "TTL set to prior TTL (%lu)",
1771 source
, line
, this->ttl
);
1772 lctx
->ttl
= this->ttl
;
1775 ISC_LIST_APPEND(this->rdata
, &rdata
[rdcount
], link
);
1776 if (ictx
->glue
!= NULL
)
1777 ictx
->glue_line
= line
;
1779 ictx
->current_line
= line
;
1783 * We must have at least 64k as rdlen is 16 bits.
1784 * If we don't commit everything we have so far.
1786 if ((target
.length
- target
.used
) < MINTSIZ
)
1790 } while (!done
&& (lctx
->loop_cnt
== 0 || loop_cnt
++ < lctx
->loop_cnt
));
1793 * Commit what has not yet been committed.
1795 result
= commit(callbacks
, lctx
, ¤t_list
, ictx
->current
,
1796 source
, ictx
->current_line
);
1797 if (MANYERRS(lctx
, result
)) {
1798 SETRESULT(lctx
, result
);
1799 } else if (result
!= ISC_R_SUCCESS
)
1800 goto insist_and_cleanup
;
1801 result
= commit(callbacks
, lctx
, &glue_list
, ictx
->glue
,
1802 source
, ictx
->glue_line
);
1803 if (MANYERRS(lctx
, result
)) {
1804 SETRESULT(lctx
, result
);
1805 } else if (result
!= ISC_R_SUCCESS
)
1806 goto insist_and_cleanup
;
1809 INSIST(lctx
->done
!= NULL
&& lctx
->task
!= NULL
);
1810 result
= DNS_R_CONTINUE
;
1811 } else if (result
== ISC_R_SUCCESS
&& lctx
->result
!= ISC_R_SUCCESS
) {
1812 result
= lctx
->result
;
1813 } else if (result
== ISC_R_SUCCESS
&& lctx
->seen_include
)
1814 result
= DNS_R_SEENINCLUDE
;
1821 INSIST(result
!= ISC_R_SUCCESS
);
1824 while ((this = ISC_LIST_HEAD(current_list
)) != NULL
)
1825 ISC_LIST_UNLINK(current_list
, this, link
);
1826 while ((this = ISC_LIST_HEAD(glue_list
)) != NULL
)
1827 ISC_LIST_UNLINK(glue_list
, this, link
);
1828 if (rdatalist
!= NULL
)
1829 isc_mem_put(mctx
, rdatalist
,
1830 rdatalist_size
* sizeof(*rdatalist
));
1832 isc_mem_put(mctx
, rdata
, rdata_size
* sizeof(*rdata
));
1833 if (target_mem
!= NULL
)
1834 isc_mem_put(mctx
, target_mem
, target_size
);
1835 if (include_file
!= NULL
)
1836 isc_mem_free(mctx
, include_file
);
1838 isc_mem_free(mctx
, range
);
1840 isc_mem_free(mctx
, lhs
);
1842 isc_mem_free(mctx
, gtype
);
1844 isc_mem_free(mctx
, rhs
);
1849 pushfile(const char *master_file
, dns_name_t
*origin
, dns_loadctx_t
*lctx
) {
1850 isc_result_t result
;
1852 dns_incctx_t
*new = NULL
;
1856 REQUIRE(master_file
!= NULL
);
1857 REQUIRE(DNS_LCTX_VALID(lctx
));
1860 lctx
->seen_include
= ISC_TRUE
;
1862 result
= incctx_create(lctx
->mctx
, origin
, &new);
1863 if (result
!= ISC_R_SUCCESS
)
1866 /* Set current domain. */
1867 if (ictx
->glue
!= NULL
|| ictx
->current
!= NULL
) {
1868 for (new_in_use
= 0; new_in_use
< NBUFS
; new_in_use
++)
1869 if (!new->in_use
[new_in_use
])
1871 INSIST(new_in_use
< NBUFS
);
1872 new->current_in_use
= new_in_use
;
1874 dns_fixedname_name(&new->fixed
[new->current_in_use
]);
1875 new->in_use
[new->current_in_use
] = ISC_TRUE
;
1876 dns_name_toregion((ictx
->glue
!= NULL
) ?
1877 ictx
->glue
: ictx
->current
, &r
);
1878 dns_name_fromregion(new->current
, &r
);
1879 new->drop
= ictx
->drop
;
1882 result
= isc_lex_openfile(lctx
->lex
, master_file
);
1883 if (result
!= ISC_R_SUCCESS
)
1887 return (ISC_R_SUCCESS
);
1891 incctx_destroy(lctx
->mctx
, new);
1896 dns_master_loadfile(const char *master_file
, dns_name_t
*top
,
1898 dns_rdataclass_t zclass
, unsigned int options
,
1899 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
)
1901 dns_loadctx_t
*lctx
= NULL
;
1902 isc_result_t result
;
1904 result
= loadctx_create(mctx
, options
, top
, zclass
, origin
,
1905 callbacks
, NULL
, NULL
, NULL
, NULL
, &lctx
);
1906 if (result
!= ISC_R_SUCCESS
)
1909 result
= isc_lex_openfile(lctx
->lex
, master_file
);
1910 if (result
!= ISC_R_SUCCESS
)
1913 result
= load(lctx
);
1914 INSIST(result
!= DNS_R_CONTINUE
);
1918 dns_loadctx_detach(&lctx
);
1923 dns_master_loadfileinc(const char *master_file
, dns_name_t
*top
,
1924 dns_name_t
*origin
, dns_rdataclass_t zclass
,
1925 unsigned int options
, dns_rdatacallbacks_t
*callbacks
,
1926 isc_task_t
*task
, dns_loaddonefunc_t done
,
1927 void *done_arg
, dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
)
1929 dns_loadctx_t
*lctx
= NULL
;
1930 isc_result_t result
;
1932 REQUIRE(task
!= NULL
);
1933 REQUIRE(done
!= NULL
);
1935 result
= loadctx_create(mctx
, options
, top
, zclass
, origin
,
1936 callbacks
, task
, done
, done_arg
, NULL
, &lctx
);
1937 if (result
!= ISC_R_SUCCESS
)
1940 result
= isc_lex_openfile(lctx
->lex
, master_file
);
1941 if (result
!= ISC_R_SUCCESS
)
1944 result
= task_send(lctx
);
1945 if (result
== ISC_R_SUCCESS
) {
1946 dns_loadctx_attach(lctx
, lctxp
);
1947 return (DNS_R_CONTINUE
);
1952 dns_loadctx_detach(&lctx
);
1957 dns_master_loadstream(FILE *stream
, dns_name_t
*top
, dns_name_t
*origin
,
1958 dns_rdataclass_t zclass
, unsigned int options
,
1959 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
)
1961 isc_result_t result
;
1962 dns_loadctx_t
*lctx
= NULL
;
1964 REQUIRE(stream
!= NULL
);
1966 result
= loadctx_create(mctx
, options
, top
, zclass
, origin
,
1967 callbacks
, NULL
, NULL
, NULL
, NULL
, &lctx
);
1968 if (result
!= ISC_R_SUCCESS
)
1971 result
= isc_lex_openstream(lctx
->lex
, stream
);
1972 if (result
!= ISC_R_SUCCESS
)
1975 result
= load(lctx
);
1976 INSIST(result
!= DNS_R_CONTINUE
);
1980 dns_loadctx_detach(&lctx
);
1985 dns_master_loadstreaminc(FILE *stream
, dns_name_t
*top
, dns_name_t
*origin
,
1986 dns_rdataclass_t zclass
, unsigned int options
,
1987 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
1988 dns_loaddonefunc_t done
, void *done_arg
,
1989 dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
)
1991 isc_result_t result
;
1992 dns_loadctx_t
*lctx
= NULL
;
1994 REQUIRE(stream
!= NULL
);
1995 REQUIRE(task
!= NULL
);
1996 REQUIRE(done
!= NULL
);
1998 result
= loadctx_create(mctx
, options
, top
, zclass
, origin
,
1999 callbacks
, task
, done
, done_arg
, NULL
, &lctx
);
2000 if (result
!= ISC_R_SUCCESS
)
2003 result
= isc_lex_openstream(lctx
->lex
, stream
);
2004 if (result
!= ISC_R_SUCCESS
)
2007 result
= task_send(lctx
);
2008 if (result
== ISC_R_SUCCESS
) {
2009 dns_loadctx_attach(lctx
, lctxp
);
2010 return (DNS_R_CONTINUE
);
2015 dns_loadctx_detach(&lctx
);
2020 dns_master_loadbuffer(isc_buffer_t
*buffer
, dns_name_t
*top
,
2021 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2022 unsigned int options
,
2023 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
)
2025 isc_result_t result
;
2026 dns_loadctx_t
*lctx
= NULL
;
2028 REQUIRE(buffer
!= NULL
);
2030 result
= loadctx_create(mctx
, options
, top
, zclass
, origin
,
2031 callbacks
, NULL
, NULL
, NULL
, NULL
, &lctx
);
2032 if (result
!= ISC_R_SUCCESS
)
2035 result
= isc_lex_openbuffer(lctx
->lex
, buffer
);
2036 if (result
!= ISC_R_SUCCESS
)
2039 result
= load(lctx
);
2040 INSIST(result
!= DNS_R_CONTINUE
);
2044 dns_loadctx_detach(&lctx
);
2049 dns_master_loadbufferinc(isc_buffer_t
*buffer
, dns_name_t
*top
,
2050 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2051 unsigned int options
,
2052 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
2053 dns_loaddonefunc_t done
, void *done_arg
,
2054 dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
)
2056 isc_result_t result
;
2057 dns_loadctx_t
*lctx
= NULL
;
2059 REQUIRE(buffer
!= NULL
);
2060 REQUIRE(task
!= NULL
);
2061 REQUIRE(done
!= NULL
);
2063 result
= loadctx_create(mctx
, options
, top
, zclass
, origin
,
2064 callbacks
, task
, done
, done_arg
, NULL
, &lctx
);
2065 if (result
!= ISC_R_SUCCESS
)
2068 result
= isc_lex_openbuffer(lctx
->lex
, buffer
);
2069 if (result
!= ISC_R_SUCCESS
)
2072 result
= task_send(lctx
);
2073 if (result
== ISC_R_SUCCESS
) {
2074 dns_loadctx_attach(lctx
, lctxp
);
2075 return (DNS_R_CONTINUE
);
2080 dns_loadctx_detach(&lctx
);
2085 dns_master_loadlexer(isc_lex_t
*lex
, dns_name_t
*top
,
2086 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2087 unsigned int options
,
2088 dns_rdatacallbacks_t
*callbacks
, isc_mem_t
*mctx
)
2090 isc_result_t result
;
2091 dns_loadctx_t
*lctx
= NULL
;
2093 REQUIRE(lex
!= NULL
);
2095 result
= loadctx_create(mctx
, options
, top
, zclass
, origin
,
2096 callbacks
, NULL
, NULL
, NULL
, lex
, &lctx
);
2097 if (result
!= ISC_R_SUCCESS
)
2100 result
= load(lctx
);
2101 INSIST(result
!= DNS_R_CONTINUE
);
2103 dns_loadctx_detach(&lctx
);
2108 dns_master_loadlexerinc(isc_lex_t
*lex
, dns_name_t
*top
,
2109 dns_name_t
*origin
, dns_rdataclass_t zclass
,
2110 unsigned int options
,
2111 dns_rdatacallbacks_t
*callbacks
, isc_task_t
*task
,
2112 dns_loaddonefunc_t done
, void *done_arg
,
2113 dns_loadctx_t
**lctxp
, isc_mem_t
*mctx
)
2115 isc_result_t result
;
2116 dns_loadctx_t
*lctx
= NULL
;
2118 REQUIRE(lex
!= NULL
);
2119 REQUIRE(task
!= NULL
);
2120 REQUIRE(done
!= NULL
);
2122 result
= loadctx_create(mctx
, options
, top
, zclass
, origin
,
2123 callbacks
, task
, done
, done_arg
, lex
, &lctx
);
2124 if (result
!= ISC_R_SUCCESS
)
2127 result
= task_send(lctx
);
2128 if (result
== ISC_R_SUCCESS
) {
2129 dns_loadctx_attach(lctx
, lctxp
);
2130 return (DNS_R_CONTINUE
);
2133 dns_loadctx_detach(&lctx
);
2138 * Grow the slab of dns_rdatalist_t structures.
2139 * Re-link glue and current list.
2141 static dns_rdatalist_t
*
2142 grow_rdatalist(int new_len
, dns_rdatalist_t
*old
, int old_len
,
2143 rdatalist_head_t
*current
, rdatalist_head_t
*glue
,
2146 dns_rdatalist_t
*new;
2148 ISC_LIST(dns_rdatalist_t
) save
;
2149 dns_rdatalist_t
*this;
2151 new = isc_mem_get(mctx
, new_len
* sizeof(*new));
2155 ISC_LIST_INIT(save
);
2156 this = ISC_LIST_HEAD(*current
);
2157 while ((this = ISC_LIST_HEAD(*current
)) != NULL
) {
2158 ISC_LIST_UNLINK(*current
, this, link
);
2159 ISC_LIST_APPEND(save
, this, link
);
2161 while ((this = ISC_LIST_HEAD(save
)) != NULL
) {
2162 ISC_LIST_UNLINK(save
, this, link
);
2163 new[rdlcount
] = *this;
2164 ISC_LIST_APPEND(*current
, &new[rdlcount
], link
);
2168 ISC_LIST_INIT(save
);
2169 this = ISC_LIST_HEAD(*glue
);
2170 while ((this = ISC_LIST_HEAD(*glue
)) != NULL
) {
2171 ISC_LIST_UNLINK(*glue
, this, link
);
2172 ISC_LIST_APPEND(save
, this, link
);
2174 while ((this = ISC_LIST_HEAD(save
)) != NULL
) {
2175 ISC_LIST_UNLINK(save
, this, link
);
2176 new[rdlcount
] = *this;
2177 ISC_LIST_APPEND(*glue
, &new[rdlcount
], link
);
2181 INSIST(rdlcount
== old_len
);
2183 isc_mem_put(mctx
, old
, old_len
* sizeof(*old
));
2188 * Grow the slab of rdata structs.
2189 * Re-link the current and glue chains.
2191 static dns_rdata_t
*
2192 grow_rdata(int new_len
, dns_rdata_t
*old
, int old_len
,
2193 rdatalist_head_t
*current
, rdatalist_head_t
*glue
,
2198 ISC_LIST(dns_rdata_t
) save
;
2199 dns_rdatalist_t
*this;
2202 new = isc_mem_get(mctx
, new_len
* sizeof(*new));
2205 memset(new, 0, new_len
* sizeof(*new));
2208 * Copy current relinking.
2210 this = ISC_LIST_HEAD(*current
);
2211 while (this != NULL
) {
2212 ISC_LIST_INIT(save
);
2213 while ((rdata
= ISC_LIST_HEAD(this->rdata
)) != NULL
) {
2214 ISC_LIST_UNLINK(this->rdata
, rdata
, link
);
2215 ISC_LIST_APPEND(save
, rdata
, link
);
2217 while ((rdata
= ISC_LIST_HEAD(save
)) != NULL
) {
2218 ISC_LIST_UNLINK(save
, rdata
, link
);
2219 new[rdcount
] = *rdata
;
2220 ISC_LIST_APPEND(this->rdata
, &new[rdcount
], link
);
2223 this = ISC_LIST_NEXT(this, link
);
2227 * Copy glue relinking.
2229 this = ISC_LIST_HEAD(*glue
);
2230 while (this != NULL
) {
2231 ISC_LIST_INIT(save
);
2232 while ((rdata
= ISC_LIST_HEAD(this->rdata
)) != NULL
) {
2233 ISC_LIST_UNLINK(this->rdata
, rdata
, link
);
2234 ISC_LIST_APPEND(save
, rdata
, link
);
2236 while ((rdata
= ISC_LIST_HEAD(save
)) != NULL
) {
2237 ISC_LIST_UNLINK(save
, rdata
, link
);
2238 new[rdcount
] = *rdata
;
2239 ISC_LIST_APPEND(this->rdata
, &new[rdcount
], link
);
2242 this = ISC_LIST_NEXT(this, link
);
2244 INSIST(rdcount
== old_len
);
2246 isc_mem_put(mctx
, old
, old_len
* sizeof(*old
));
2251 * Convert each element from a rdatalist_t to rdataset then call commit.
2252 * Unlink each element as we go.
2256 commit(dns_rdatacallbacks_t
*callbacks
, dns_loadctx_t
*lctx
,
2257 rdatalist_head_t
*head
, dns_name_t
*owner
,
2258 const char *source
, unsigned int line
)
2260 dns_rdatalist_t
*this;
2261 dns_rdataset_t dataset
;
2262 isc_result_t result
;
2263 char namebuf
[DNS_NAME_FORMATSIZE
];
2264 void (*error
)(struct dns_rdatacallbacks
*, const char *, ...);
2266 this = ISC_LIST_HEAD(*head
);
2267 error
= callbacks
->error
;
2270 return (ISC_R_SUCCESS
);
2272 dns_rdataset_init(&dataset
);
2273 RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset
)
2275 dataset
.trust
= dns_trust_ultimate
;
2276 result
= ((*callbacks
->add
)(callbacks
->add_private
, owner
,
2278 if (result
== ISC_R_NOMEMORY
) {
2279 (*error
)(callbacks
, "dns_master_load: %s",
2280 dns_result_totext(result
));
2281 } else if (result
!= ISC_R_SUCCESS
) {
2282 dns_name_format(owner
, namebuf
,
2284 (*error
)(callbacks
, "%s: %s:%lu: %s: %s",
2285 "dns_master_load", source
, line
,
2286 namebuf
, dns_result_totext(result
));
2288 if (MANYERRS(lctx
, result
))
2289 SETRESULT(lctx
, result
);
2290 else if (result
!= ISC_R_SUCCESS
)
2292 ISC_LIST_UNLINK(*head
, this, link
);
2293 this = ISC_LIST_HEAD(*head
);
2294 } while (this != NULL
);
2295 return (ISC_R_SUCCESS
);
2299 * Returns ISC_TRUE if one of the NS rdata's contains 'owner'.
2302 static isc_boolean_t
2303 is_glue(rdatalist_head_t
*head
, dns_name_t
*owner
) {
2304 dns_rdatalist_t
*this;
2306 isc_region_t region
;
2312 this = ISC_LIST_HEAD(*head
);
2313 while (this != NULL
) {
2314 if (this->type
== dns_rdatatype_ns
)
2316 this = ISC_LIST_NEXT(this, link
);
2321 rdata
= ISC_LIST_HEAD(this->rdata
);
2322 while (rdata
!= NULL
) {
2323 dns_name_init(&name
, NULL
);
2324 dns_rdata_toregion(rdata
, ®ion
);
2325 dns_name_fromregion(&name
, ®ion
);
2326 if (dns_name_compare(&name
, owner
) == 0)
2328 rdata
= ISC_LIST_NEXT(rdata
, link
);
2334 load_quantum(isc_task_t
*task
, isc_event_t
*event
) {
2335 isc_result_t result
;
2336 dns_loadctx_t
*lctx
;
2338 REQUIRE(event
!= NULL
);
2339 lctx
= event
->ev_arg
;
2340 REQUIRE(DNS_LCTX_VALID(lctx
));
2343 result
= ISC_R_CANCELED
;
2345 result
= load(lctx
);
2346 if (result
== DNS_R_CONTINUE
) {
2347 event
->ev_arg
= lctx
;
2348 isc_task_send(task
, &event
);
2350 (lctx
->done
)(lctx
->done_arg
, result
);
2351 isc_event_free(&event
);
2352 dns_loadctx_detach(&lctx
);
2357 task_send(dns_loadctx_t
*lctx
) {
2360 event
= isc_event_allocate(lctx
->mctx
, NULL
,
2361 DNS_EVENT_MASTERQUANTUM
,
2362 load_quantum
, lctx
, sizeof(*event
));
2364 return (ISC_R_NOMEMORY
);
2365 isc_task_send(lctx
->task
, &event
);
2366 return (ISC_R_SUCCESS
);
2370 dns_loadctx_cancel(dns_loadctx_t
*lctx
) {
2371 REQUIRE(DNS_LCTX_VALID(lctx
));
2374 lctx
->canceled
= ISC_TRUE
;
2375 UNLOCK(&lctx
->lock
);