1/*	$NetBSD: master.c,v 1.1 2024/02/18 20:57:32 christos Exp $	*/
2
3/*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16/*! \file */
17
18#include <inttypes.h>
19#include <stdbool.h>
20
21#include <isc/atomic.h>
22#include <isc/event.h>
23#include <isc/lex.h>
24#include <isc/magic.h>
25#include <isc/mem.h>
26#include <isc/print.h>
27#include <isc/refcount.h>
28#include <isc/serial.h>
29#include <isc/stdio.h>
30#include <isc/stdtime.h>
31#include <isc/string.h>
32#include <isc/task.h>
33#include <isc/util.h>
34
35#include <dns/callbacks.h>
36#include <dns/events.h>
37#include <dns/fixedname.h>
38#include <dns/master.h>
39#include <dns/name.h>
40#include <dns/rdata.h>
41#include <dns/rdataclass.h>
42#include <dns/rdatalist.h>
43#include <dns/rdataset.h>
44#include <dns/rdatastruct.h>
45#include <dns/rdatatype.h>
46#include <dns/result.h>
47#include <dns/soa.h>
48#include <dns/time.h>
49#include <dns/ttl.h>
50
51/*!
52 * Grow the number of dns_rdatalist_t (#RDLSZ) and dns_rdata_t (#RDSZ)
53 * structures by these sizes when we need to.
54 *
55 */
56/*% RDLSZ reflects the number of different types with the same name expected. */
57#define RDLSZ 32
58/*%
59 * RDSZ reflects the number of rdata expected at a give name that can fit into
60 * 64k.
61 */
62#define RDSZ 512
63
64#define NBUFS	  4
65#define MAXWIRESZ 255
66
67/*%
68 * Target buffer size and minimum target size.
69 * MINTSIZ must be big enough to hold the largest rdata record.
70 * \brief
71 * TSIZ >= MINTSIZ
72 */
73#define TSIZ (128 * 1024)
74/*%
75 * max message size - header - root - type - class - ttl - rdlen
76 */
77#define MINTSIZ DNS_RDATA_MAXLENGTH
78/*%
79 * Size for tokens in the presentation format,
80 * The largest tokens are the base64 blocks in KEY and CERT records,
81 * Largest key allowed is about 1372 bytes but
82 * there is no fixed upper bound on CERT records.
83 * 2K is too small for some X.509s, 8K is overkill.
84 */
85#define TOKENSIZ (8 * 1024)
86
87/*%
88 * Buffers sizes for $GENERATE.
89 */
90#define DNS_MASTER_LHS 2048
91#define DNS_MASTER_RHS MINTSIZ
92
93#define CHECKNAMESFAIL(x) (((x)&DNS_MASTER_CHECKNAMESFAIL) != 0)
94
95typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
96
97typedef struct dns_incctx dns_incctx_t;
98
99/*%
100 * Master file load state.
101 */
102
103struct dns_loadctx {
104	unsigned int magic;
105	isc_mem_t *mctx;
106	dns_masterformat_t format;
107
108	dns_rdatacallbacks_t *callbacks;
109	isc_task_t *task;
110	dns_loaddonefunc_t done;
111	void *done_arg;
112
113	/* Common methods */
114	isc_result_t (*openfile)(dns_loadctx_t *lctx, const char *filename);
115	isc_result_t (*load)(dns_loadctx_t *lctx);
116
117	/* Members used by all formats */
118	uint32_t maxttl;
119
120	/* Members specific to the text format: */
121	isc_lex_t *lex;
122	bool keep_lex;
123	unsigned int options;
124	bool ttl_known;
125	bool default_ttl_known;
126	bool warn_1035;
127	bool warn_tcr;
128	bool warn_sigexpired;
129	bool seen_include;
130	uint32_t ttl;
131	uint32_t default_ttl;
132	dns_rdataclass_t zclass;
133	dns_fixedname_t fixed_top;
134	dns_name_t *top; /*%< top of zone */
135
136	/* Members specific to the raw format: */
137	FILE *f;
138	bool first;
139	dns_masterrawheader_t header;
140
141	/* Which fixed buffers we are using? */
142	unsigned int loop_cnt; /*% records per quantum,
143				* 0 => all. */
144	isc_result_t result;
145
146	/* Atomic */
147	isc_refcount_t references;
148	atomic_bool canceled;
149
150	/* locked by lock */
151	dns_incctx_t *inc;
152	uint32_t resign;
153	isc_stdtime_t now;
154
155	dns_masterincludecb_t include_cb;
156	void *include_arg;
157};
158
159struct dns_incctx {
160	dns_incctx_t *parent;
161	dns_name_t *origin;
162	dns_name_t *current;
163	dns_name_t *glue;
164	dns_fixedname_t fixed[NBUFS]; /* working buffers */
165	unsigned int in_use[NBUFS];   /* covert to bitmap? */
166	int glue_in_use;
167	int current_in_use;
168	int origin_in_use;
169	bool origin_changed;
170	bool drop;
171	unsigned int glue_line;
172	unsigned int current_line;
173};
174
175#define DNS_LCTX_MAGIC	     ISC_MAGIC('L', 'c', 't', 'x')
176#define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
177
178#define DNS_AS_STR(t) ((t).value.as_textregion.base)
179
180static isc_result_t
181openfile_text(dns_loadctx_t *lctx, const char *master_file);
182
183static isc_result_t
184load_text(dns_loadctx_t *lctx);
185
186static isc_result_t
187openfile_raw(dns_loadctx_t *lctx, const char *master_file);
188
189static isc_result_t
190load_raw(dns_loadctx_t *lctx);
191
192static isc_result_t
193openfile_map(dns_loadctx_t *lctx, const char *master_file);
194
195static isc_result_t
196load_map(dns_loadctx_t *lctx);
197
198static isc_result_t
199pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx);
200
201static isc_result_t
202commit(dns_rdatacallbacks_t *, dns_loadctx_t *, rdatalist_head_t *,
203       dns_name_t *, const char *, unsigned int);
204
205static bool
206is_glue(rdatalist_head_t *, dns_name_t *);
207
208static dns_rdatalist_t *
209grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *,
210	       rdatalist_head_t *, isc_mem_t *mctx);
211
212static dns_rdata_t *
213grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *,
214	   isc_mem_t *);
215
216static void
217load_quantum(isc_task_t *task, isc_event_t *event);
218
219static isc_result_t
220task_send(dns_loadctx_t *lctx);
221
222static void
223loadctx_destroy(dns_loadctx_t *lctx);
224
225#define GETTOKENERR(lexer, options, token, eol, err)                      \
226	do {                                                              \
227		result = gettoken(lexer, options, token, eol, callbacks); \
228		switch (result) {                                         \
229		case ISC_R_SUCCESS:                                       \
230			break;                                            \
231		case ISC_R_UNEXPECTED:                                    \
232			goto insist_and_cleanup;                          \
233		default:                                                  \
234			if (MANYERRS(lctx, result)) {                     \
235				SETRESULT(lctx, result);                  \
236				LOGIT(result);                            \
237				read_till_eol = true;                     \
238				err goto next_line;                       \
239			} else                                            \
240				goto log_and_cleanup;                     \
241		}                                                         \
242		if ((token)->type == isc_tokentype_special) {             \
243			result = DNS_R_SYNTAX;                            \
244			if (MANYERRS(lctx, result)) {                     \
245				SETRESULT(lctx, result);                  \
246				LOGIT(result);                            \
247				read_till_eol = true;                     \
248				goto next_line;                           \
249			} else                                            \
250				goto log_and_cleanup;                     \
251		}                                                         \
252	} while (0)
253#define GETTOKEN(lexer, options, token, eol) \
254	GETTOKENERR(lexer, options, token, eol, {})
255
256#define COMMITALL                                                              \
257	do {                                                                   \
258		result = commit(callbacks, lctx, &current_list, ictx->current, \
259				source, ictx->current_line);                   \
260		if (MANYERRS(lctx, result)) {                                  \
261			SETRESULT(lctx, result);                               \
262		} else if (result != ISC_R_SUCCESS)                            \
263			goto insist_and_cleanup;                               \
264		result = commit(callbacks, lctx, &glue_list, ictx->glue,       \
265				source, ictx->glue_line);                      \
266		if (MANYERRS(lctx, result)) {                                  \
267			SETRESULT(lctx, result);                               \
268		} else if (result != ISC_R_SUCCESS)                            \
269			goto insist_and_cleanup;                               \
270		rdcount = 0;                                                   \
271		rdlcount = 0;                                                  \
272		isc_buffer_init(&target, target_mem, target_size);             \
273		rdcount_save = rdcount;                                        \
274		rdlcount_save = rdlcount;                                      \
275	} while (0)
276
277#define WARNUNEXPECTEDEOF(lexer)                                         \
278	do {                                                             \
279		if (isc_lex_isfile(lexer))                               \
280			(*callbacks->warn)(callbacks,                    \
281					   "%s: file does not end with " \
282					   "newline",                    \
283					   source);                      \
284	} while (0)
285
286#define EXPECTEOL                                              \
287	do {                                                   \
288		GETTOKEN(lctx->lex, 0, &token, true);          \
289		if (token.type != isc_tokentype_eol) {         \
290			isc_lex_ungettoken(lctx->lex, &token); \
291			result = DNS_R_EXTRATOKEN;             \
292			if (MANYERRS(lctx, result)) {          \
293				SETRESULT(lctx, result);       \
294				LOGIT(result);                 \
295				read_till_eol = true;          \
296				break;                         \
297			} else if (result != ISC_R_SUCCESS)    \
298				goto log_and_cleanup;          \
299		}                                              \
300	} while (0)
301
302#define MANYERRS(lctx, result)                                     \
303	((result != ISC_R_SUCCESS) && (result != ISC_R_IOERROR) && \
304	 ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
305
306#define SETRESULT(lctx, r)                           \
307	do {                                         \
308		if ((lctx)->result == ISC_R_SUCCESS) \
309			(lctx)->result = r;          \
310	} while (0)
311
312#define LOGITFILE(result, filename)                                            \
313	if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND ||     \
314	    result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES ||     \
315	    result == ISC_R_NOPERM)                                            \
316		(*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s",           \
317				    "dns_master_load", source, line, filename, \
318				    dns_result_totext(result));                \
319	else                                                                   \
320		LOGIT(result)
321
322#define LOGIT(result)                                                 \
323	if (result == ISC_R_NOMEMORY)                                 \
324		(*callbacks->error)(callbacks, "dns_master_load: %s", \
325				    dns_result_totext(result));       \
326	else                                                          \
327		(*callbacks->error)(callbacks, "%s: %s:%lu: %s",      \
328				    "dns_master_load", source, line,  \
329				    dns_result_totext(result))
330
331static unsigned char in_addr_arpa_data[] = "\007IN-ADDR\004ARPA";
332static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 };
333static dns_name_t const in_addr_arpa =
334	DNS_NAME_INITABSOLUTE(in_addr_arpa_data, in_addr_arpa_offsets);
335
336static unsigned char ip6_int_data[] = "\003IP6\003INT";
337static unsigned char ip6_int_offsets[] = { 0, 4, 8 };
338static dns_name_t const ip6_int = DNS_NAME_INITABSOLUTE(ip6_int_data,
339							ip6_int_offsets);
340
341static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA";
342static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
343static dns_name_t const ip6_arpa = DNS_NAME_INITABSOLUTE(ip6_arpa_data,
344							 ip6_arpa_offsets);
345
346static bool
347dns_master_isprimary(dns_loadctx_t *lctx) {
348	return ((lctx->options & DNS_MASTER_ZONE) != 0 &&
349		(lctx->options & DNS_MASTER_SLAVE) == 0 &&
350		(lctx->options & DNS_MASTER_KEY) == 0);
351}
352
353static isc_result_t
354gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token, bool eol,
355	 dns_rdatacallbacks_t *callbacks) {
356	isc_result_t result;
357
358	options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE |
359		   ISC_LEXOPT_ESCAPE;
360	result = isc_lex_gettoken(lex, options, token);
361	if (result != ISC_R_SUCCESS) {
362		switch (result) {
363		case ISC_R_NOMEMORY:
364			return (ISC_R_NOMEMORY);
365		default:
366			(*callbacks->error)(callbacks,
367					    "dns_master_load: %s:%lu:"
368					    " isc_lex_gettoken() failed: %s",
369					    isc_lex_getsourcename(lex),
370					    isc_lex_getsourceline(lex),
371					    isc_result_totext(result));
372			return (result);
373		}
374		/*NOTREACHED*/
375	}
376	if (eol != true) {
377		if (token->type == isc_tokentype_eol ||
378		    token->type == isc_tokentype_eof)
379		{
380			{
381				unsigned long int line;
382				const char *what;
383				const char *file;
384				file = isc_lex_getsourcename(lex);
385				line = isc_lex_getsourceline(lex);
386				if (token->type == isc_tokentype_eol) {
387					line--;
388					what = "line";
389				} else {
390					what = "file";
391				}
392				(*callbacks->error)(callbacks,
393						    "dns_master_load: %s:%lu: "
394						    "unexpected end of %s",
395						    file, line, what);
396				return (ISC_R_UNEXPECTEDEND);
397			}
398		}
399	}
400	return (ISC_R_SUCCESS);
401}
402
403void
404dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
405	REQUIRE(target != NULL && *target == NULL);
406	REQUIRE(DNS_LCTX_VALID(source));
407
408	isc_refcount_increment(&source->references);
409
410	*target = source;
411}
412
413void
414dns_loadctx_detach(dns_loadctx_t **lctxp) {
415	dns_loadctx_t *lctx;
416
417	REQUIRE(lctxp != NULL);
418	lctx = *lctxp;
419	*lctxp = NULL;
420	REQUIRE(DNS_LCTX_VALID(lctx));
421
422	if (isc_refcount_decrement(&lctx->references) == 1) {
423		loadctx_destroy(lctx);
424	}
425}
426
427static void
428incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
429	dns_incctx_t *parent;
430
431again:
432	parent = ictx->parent;
433	ictx->parent = NULL;
434
435	isc_mem_put(mctx, ictx, sizeof(*ictx));
436
437	if (parent != NULL) {
438		ictx = parent;
439		goto again;
440	}
441}
442
443static void
444loadctx_destroy(dns_loadctx_t *lctx) {
445	REQUIRE(DNS_LCTX_VALID(lctx));
446
447	isc_refcount_destroy(&lctx->references);
448
449	lctx->magic = 0;
450	if (lctx->inc != NULL) {
451		incctx_destroy(lctx->mctx, lctx->inc);
452	}
453
454	if (lctx->f != NULL) {
455		isc_result_t 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));
460		}
461	}
462
463	/* isc_lex_destroy() will close all open streams */
464	if (lctx->lex != NULL && !lctx->keep_lex) {
465		isc_lex_destroy(&lctx->lex);
466	}
467
468	if (lctx->task != NULL) {
469		isc_task_detach(&lctx->task);
470	}
471
472	isc_mem_putanddetach(&lctx->mctx, lctx, sizeof(*lctx));
473}
474
475static isc_result_t
476incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
477	dns_incctx_t *ictx;
478	isc_region_t r;
479	int i;
480
481	ictx = isc_mem_get(mctx, sizeof(*ictx));
482
483	for (i = 0; i < NBUFS; i++) {
484		dns_fixedname_init(&ictx->fixed[i]);
485		ictx->in_use[i] = false;
486	}
487
488	ictx->origin_in_use = 0;
489	ictx->origin = dns_fixedname_name(&ictx->fixed[ictx->origin_in_use]);
490	ictx->in_use[ictx->origin_in_use] = true;
491	dns_name_toregion(origin, &r);
492	dns_name_fromregion(ictx->origin, &r);
493
494	ictx->glue = NULL;
495	ictx->current = NULL;
496	ictx->glue_in_use = -1;
497	ictx->current_in_use = -1;
498	ictx->parent = NULL;
499	ictx->drop = false;
500	ictx->glue_line = 0;
501	ictx->current_line = 0;
502	ictx->origin_changed = true;
503
504	*ictxp = ictx;
505	return (ISC_R_SUCCESS);
506}
507
508static isc_result_t
509loadctx_create(dns_masterformat_t format, isc_mem_t *mctx, unsigned int options,
510	       uint32_t resign, dns_name_t *top, dns_rdataclass_t zclass,
511	       dns_name_t *origin, dns_rdatacallbacks_t *callbacks,
512	       isc_task_t *task, dns_loaddonefunc_t done, void *done_arg,
513	       dns_masterincludecb_t include_cb, void *include_arg,
514	       isc_lex_t *lex, dns_loadctx_t **lctxp) {
515	dns_loadctx_t *lctx;
516	isc_result_t result;
517	isc_region_t r;
518	isc_lexspecials_t specials;
519
520	REQUIRE(lctxp != NULL && *lctxp == NULL);
521	REQUIRE(callbacks != NULL);
522	REQUIRE(callbacks->add != NULL);
523	REQUIRE(callbacks->error != NULL);
524	REQUIRE(callbacks->warn != NULL);
525	REQUIRE(mctx != NULL);
526	REQUIRE(dns_name_isabsolute(top));
527	REQUIRE(dns_name_isabsolute(origin));
528	REQUIRE((task == NULL && done == NULL) ||
529		(task != NULL && done != NULL));
530
531	lctx = isc_mem_get(mctx, sizeof(*lctx));
532
533	lctx->inc = NULL;
534	result = incctx_create(mctx, origin, &lctx->inc);
535	if (result != ISC_R_SUCCESS) {
536		goto cleanup_ctx;
537	}
538
539	lctx->maxttl = 0;
540
541	lctx->format = format;
542	switch (format) {
543	case dns_masterformat_text:
544		lctx->openfile = openfile_text;
545		lctx->load = load_text;
546		break;
547	case dns_masterformat_raw:
548		lctx->openfile = openfile_raw;
549		lctx->load = load_raw;
550		break;
551	case dns_masterformat_map:
552		lctx->openfile = openfile_map;
553		lctx->load = load_map;
554		break;
555	default:
556		UNREACHABLE();
557	}
558
559	if (lex != NULL) {
560		lctx->lex = lex;
561		lctx->keep_lex = true;
562	} else {
563		lctx->lex = NULL;
564		result = isc_lex_create(mctx, TOKENSIZ, &lctx->lex);
565		if (result != ISC_R_SUCCESS) {
566			goto cleanup_inc;
567		}
568		lctx->keep_lex = false;
569		/*
570		 * If specials change update dns_test_rdatafromstring()
571		 * in lib/dns/tests/dnstest.c.
572		 */
573		memset(specials, 0, sizeof(specials));
574		specials[0] = 1;
575		specials['('] = 1;
576		specials[')'] = 1;
577		specials['"'] = 1;
578		isc_lex_setspecials(lctx->lex, specials);
579		isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE);
580	}
581
582	lctx->ttl_known = ((options & DNS_MASTER_NOTTL) != 0);
583	lctx->ttl = 0;
584	lctx->default_ttl_known = lctx->ttl_known;
585	lctx->default_ttl = 0;
586	lctx->warn_1035 = true;	      /* XXX Argument? */
587	lctx->warn_tcr = true;	      /* XXX Argument? */
588	lctx->warn_sigexpired = true; /* XXX Argument? */
589	lctx->options = options;
590	lctx->seen_include = false;
591	lctx->zclass = zclass;
592	lctx->resign = resign;
593	lctx->result = ISC_R_SUCCESS;
594	lctx->include_cb = include_cb;
595	lctx->include_arg = include_arg;
596	isc_stdtime_get(&lctx->now);
597
598	lctx->top = dns_fixedname_initname(&lctx->fixed_top);
599	dns_name_toregion(top, &r);
600	dns_name_fromregion(lctx->top, &r);
601
602	lctx->f = NULL;
603	lctx->first = true;
604	dns_master_initrawheader(&lctx->header);
605
606	lctx->loop_cnt = (done != NULL) ? 100 : 0;
607	lctx->callbacks = callbacks;
608	lctx->task = NULL;
609	if (task != NULL) {
610		isc_task_attach(task, &lctx->task);
611	}
612	lctx->done = done;
613	lctx->done_arg = done_arg;
614	atomic_init(&lctx->canceled, false);
615	lctx->mctx = NULL;
616	isc_mem_attach(mctx, &lctx->mctx);
617
618	isc_refcount_init(&lctx->references, 1); /* Implicit attach. */
619
620	lctx->magic = DNS_LCTX_MAGIC;
621	*lctxp = lctx;
622	return (ISC_R_SUCCESS);
623
624cleanup_inc:
625	incctx_destroy(mctx, lctx->inc);
626cleanup_ctx:
627	isc_mem_put(mctx, lctx, sizeof(*lctx));
628	return (result);
629}
630
631static const char *hex = "0123456789abcdef0123456789ABCDEF";
632
633/*%
634 * Convert value into a nibble sequence from least significant to most
635 * significant nibble.  Zero fill upper most significant nibbles if
636 * required to make the width.
637 *
638 * Returns the number of characters that should have been written without
639 * counting the terminating NUL.
640 */
641static unsigned int
642nibbles(char *numbuf, size_t length, unsigned int width, char mode, int value) {
643	unsigned int count = 0;
644
645	/*
646	 * This reserve space for the NUL string terminator.
647	 */
648	if (length > 0U) {
649		*numbuf = '\0';
650		length--;
651	}
652	do {
653		char val = hex[(value & 0x0f) + ((mode == 'n') ? 0 : 16)];
654		value >>= 4;
655		if (length > 0U) {
656			*numbuf++ = val;
657			*numbuf = '\0';
658			length--;
659		}
660		if (width > 0) {
661			width--;
662		}
663		count++;
664		/*
665		 * If width is non zero then we need to add a label separator.
666		 * If value is non zero then we need to add another label and
667		 * that requires a label separator.
668		 */
669		if (width > 0 || value != 0) {
670			if (length > 0U) {
671				*numbuf++ = '.';
672				*numbuf = '\0';
673				length--;
674			}
675			if (width > 0) {
676				width--;
677			}
678			count++;
679		}
680	} while (value != 0 || width > 0);
681	return (count);
682}
683
684static isc_result_t
685genname(char *name, int it, char *buffer, size_t length) {
686	char fmt[sizeof("%04000000000d")];
687	char numbuf[128];
688	char *cp;
689	char mode[2] = { 0 };
690	char brace[2] = { 0 };
691	char comma1[2] = { 0 };
692	char comma2[2] = { 0 };
693	int delta = 0;
694	isc_textregion_t r;
695	unsigned int n;
696	unsigned int width;
697	bool nibblemode;
698
699	r.base = buffer;
700	r.length = (unsigned int)length;
701
702	while (*name != '\0') {
703		if (*name == '$') {
704			name++;
705			if (*name == '$') {
706				if (r.length == 0) {
707					return (ISC_R_NOSPACE);
708				}
709				r.base[0] = *name++;
710				isc_textregion_consume(&r, 1);
711				continue;
712			}
713			nibblemode = false;
714			strlcpy(fmt, "%d", sizeof(fmt));
715			/* Get format specifier. */
716			if (*name == '{') {
717				n = sscanf(name,
718					   "{%d%1[,}]%u%1[,}]%1[doxXnN]%1[}]",
719					   &delta, comma1, &width, comma2, mode,
720					   brace);
721				if (n < 2 || n > 6) {
722					return (DNS_R_SYNTAX);
723				}
724				if (comma1[0] == '}') {
725					/* %{delta} */
726				} else if (comma1[0] == ',' && comma2[0] == '}')
727				{
728					/* %{delta,width} */
729					n = snprintf(fmt, sizeof(fmt), "%%0%ud",
730						     width);
731				} else if (comma1[0] == ',' &&
732					   comma2[0] == ',' && mode[0] != 0 &&
733					   brace[0] == '}')
734				{
735					/* %{delta,width,format} */
736					if (mode[0] == 'n' || mode[0] == 'N') {
737						nibblemode = true;
738					}
739					n = snprintf(fmt, sizeof(fmt),
740						     "%%0%u%c", width, mode[0]);
741				} else {
742					return (DNS_R_SYNTAX);
743				}
744				if (n >= sizeof(fmt)) {
745					return (ISC_R_NOSPACE);
746				}
747				/* Skip past closing brace. */
748				while (*name != '\0' && *name++ != '}') {
749					continue;
750				}
751			}
752			/*
753			 * 'it' is >= 0 so we don't need to check for
754			 * underflow.
755			 */
756			if ((it > 0 && delta > INT_MAX - it)) {
757				return (ISC_R_RANGE);
758			}
759			if (nibblemode) {
760				n = nibbles(numbuf, sizeof(numbuf), width,
761					    mode[0], it + delta);
762			} else {
763				n = snprintf(numbuf, sizeof(numbuf), fmt,
764					     it + delta);
765			}
766			if (n >= sizeof(numbuf)) {
767				return (ISC_R_NOSPACE);
768			}
769			cp = numbuf;
770			while (*cp != '\0') {
771				if (r.length == 0) {
772					return (ISC_R_NOSPACE);
773				}
774				r.base[0] = *cp++;
775				isc_textregion_consume(&r, 1);
776			}
777		} else if (*name == '\\') {
778			if (r.length == 0) {
779				return (ISC_R_NOSPACE);
780			}
781			r.base[0] = *name++;
782			isc_textregion_consume(&r, 1);
783			if (*name == '\0') {
784				continue;
785			}
786			if (r.length == 0) {
787				return (ISC_R_NOSPACE);
788			}
789			r.base[0] = *name++;
790			isc_textregion_consume(&r, 1);
791		} else {
792			if (r.length == 0) {
793				return (ISC_R_NOSPACE);
794			}
795			r.base[0] = *name++;
796			isc_textregion_consume(&r, 1);
797		}
798	}
799	if (r.length == 0) {
800		return (ISC_R_NOSPACE);
801	}
802	r.base[0] = '\0';
803	return (ISC_R_SUCCESS);
804}
805
806static isc_result_t
807generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
808	 const char *source, unsigned int line) {
809	char *target_mem = NULL;
810	char *lhsbuf = NULL;
811	char *rhsbuf = NULL;
812	dns_fixedname_t ownerfixed;
813	dns_name_t *owner;
814	dns_rdata_t rdata = DNS_RDATA_INIT;
815	dns_rdatacallbacks_t *callbacks;
816	dns_rdatalist_t rdatalist;
817	dns_rdatatype_t type;
818	rdatalist_head_t head;
819	int target_size = MINTSIZ; /* only one rdata at a time */
820	isc_buffer_t buffer;
821	isc_buffer_t target;
822	isc_result_t result;
823	isc_textregion_t r;
824	int n, start, stop, step = 0;
825	unsigned int i;
826	dns_incctx_t *ictx;
827	char dummy[2];
828
829	ictx = lctx->inc;
830	callbacks = lctx->callbacks;
831	owner = dns_fixedname_initname(&ownerfixed);
832	ISC_LIST_INIT(head);
833
834	target_mem = isc_mem_get(lctx->mctx, target_size);
835	rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_RHS);
836	lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_LHS);
837	if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) {
838		result = ISC_R_NOMEMORY;
839		goto error_cleanup;
840	}
841	isc_buffer_init(&target, target_mem, target_size);
842
843	n = sscanf(range, "%d-%d%1[/]%d", &start, &stop, dummy, &step);
844	if ((n != 2 && n != 4) || (start < 0) || (stop < 0) ||
845	    (n == 4 && step < 1) || (stop < start))
846	{
847		(*callbacks->error)(callbacks, "%s: %s:%lu: invalid range '%s'",
848				    "$GENERATE", source, line, range);
849		result = DNS_R_SYNTAX;
850		goto insist_cleanup;
851	}
852	if (n == 2) {
853		step = 1;
854	}
855
856	/*
857	 * Get type.
858	 */
859	r.base = gtype;
860	r.length = strlen(gtype);
861	result = dns_rdatatype_fromtext(&type, &r);
862	if (result != ISC_R_SUCCESS) {
863		(*callbacks->error)(callbacks,
864				    "%s: %s:%lu: unknown RR type '%s'",
865				    "$GENERATE", source, line, gtype);
866		goto insist_cleanup;
867	}
868
869	/*
870	 * RFC2930: TKEY and TSIG are not allowed to be loaded
871	 * from master files.
872	 */
873	if (dns_master_isprimary(lctx) && dns_rdatatype_ismeta(type)) {
874		(*callbacks->error)(callbacks, "%s: %s:%lu: meta RR type '%s'",
875				    "$GENERATE", source, line, gtype);
876		result = DNS_R_METATYPE;
877		goto insist_cleanup;
878	}
879
880	for (i = start; i <= (unsigned int)stop; i += step) {
881		result = genname(lhs, i, lhsbuf, DNS_MASTER_LHS);
882		if (result != ISC_R_SUCCESS) {
883			goto error_cleanup;
884		}
885		result = genname(rhs, i, rhsbuf, DNS_MASTER_RHS);
886		if (result != ISC_R_SUCCESS) {
887			goto error_cleanup;
888		}
889
890		isc_buffer_init(&buffer, lhsbuf, strlen(lhsbuf));
891		isc_buffer_add(&buffer, strlen(lhsbuf));
892		isc_buffer_setactive(&buffer, strlen(lhsbuf));
893		result = dns_name_fromtext(owner, &buffer, ictx->origin, 0,
894					   NULL);
895		if (result != ISC_R_SUCCESS) {
896			goto error_cleanup;
897		}
898
899		if (dns_master_isprimary(lctx) &&
900		    !dns_name_issubdomain(owner, lctx->top))
901		{
902			char namebuf[DNS_NAME_FORMATSIZE];
903			dns_name_format(owner, namebuf, sizeof(namebuf));
904			/*
905			 * Ignore out-of-zone data.
906			 */
907			(*callbacks->warn)(callbacks,
908					   "%s:%lu: "
909					   "ignoring out-of-zone data (%s)",
910					   source, line, namebuf);
911			continue;
912		}
913
914		isc_buffer_init(&buffer, rhsbuf, strlen(rhsbuf));
915		isc_buffer_add(&buffer, strlen(rhsbuf));
916		isc_buffer_setactive(&buffer, strlen(rhsbuf));
917
918		result = isc_lex_openbuffer(lctx->lex, &buffer);
919		if (result != ISC_R_SUCCESS) {
920			goto error_cleanup;
921		}
922
923		isc_buffer_init(&target, target_mem, target_size);
924		result = dns_rdata_fromtext(&rdata, lctx->zclass, type,
925					    lctx->lex, ictx->origin, 0,
926					    lctx->mctx, &target, callbacks);
927		RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
928		if (result != ISC_R_SUCCESS) {
929			goto error_cleanup;
930		}
931
932		dns_rdatalist_init(&rdatalist);
933		rdatalist.type = type;
934		rdatalist.rdclass = lctx->zclass;
935		rdatalist.ttl = lctx->ttl;
936		ISC_LIST_PREPEND(head, &rdatalist, link);
937		ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
938		result = commit(callbacks, lctx, &head, owner, source, line);
939		ISC_LIST_UNLINK(rdatalist.rdata, &rdata, link);
940		if (result != ISC_R_SUCCESS) {
941			goto error_cleanup;
942		}
943		dns_rdata_reset(&rdata);
944	}
945	result = ISC_R_SUCCESS;
946	goto cleanup;
947
948error_cleanup:
949	if (result == ISC_R_NOMEMORY) {
950		(*callbacks->error)(callbacks, "$GENERATE: %s",
951				    dns_result_totext(result));
952	} else {
953		(*callbacks->error)(callbacks, "$GENERATE: %s:%lu: %s", source,
954				    line, dns_result_totext(result));
955	}
956
957insist_cleanup:
958	INSIST(result != ISC_R_SUCCESS);
959
960cleanup:
961	if (target_mem != NULL) {
962		isc_mem_put(lctx->mctx, target_mem, target_size);
963	}
964	if (lhsbuf != NULL) {
965		isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_LHS);
966	}
967	if (rhsbuf != NULL) {
968		isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_RHS);
969	}
970	return (result);
971}
972
973static void
974limit_ttl(dns_rdatacallbacks_t *callbacks, const char *source,
975	  unsigned int line, uint32_t *ttlp) {
976	if (*ttlp > 0x7fffffffUL) {
977		(callbacks->warn)(callbacks,
978				  "%s: %s:%lu: "
979				  "$TTL %lu > MAXTTL, "
980				  "setting $TTL to 0",
981				  "dns_master_load", source, line, *ttlp);
982		*ttlp = 0;
983	}
984}
985
986static isc_result_t
987check_ns(dns_loadctx_t *lctx, isc_token_t *token, const char *source,
988	 unsigned long line) {
989	char *tmp = NULL;
990	isc_result_t result = ISC_R_SUCCESS;
991	void (*callback)(struct dns_rdatacallbacks *, const char *, ...);
992
993	if ((lctx->options & DNS_MASTER_FATALNS) != 0) {
994		callback = lctx->callbacks->error;
995	} else {
996		callback = lctx->callbacks->warn;
997	}
998
999	if (token->type == isc_tokentype_string) {
1000		struct in_addr addr;
1001		struct in6_addr addr6;
1002
1003		tmp = isc_mem_strdup(lctx->mctx, DNS_AS_STR(*token));
1004		/*
1005		 * Catch both "1.2.3.4" and "1.2.3.4."
1006		 */
1007		if (tmp[strlen(tmp) - 1] == '.') {
1008			tmp[strlen(tmp) - 1] = '\0';
1009		}
1010		if (inet_pton(AF_INET, tmp, &addr) == 1 ||
1011		    inet_pton(AF_INET6, tmp, &addr6) == 1)
1012		{
1013			result = DNS_R_NSISADDRESS;
1014		}
1015	}
1016	if (result != ISC_R_SUCCESS) {
1017		(*callback)(lctx->callbacks,
1018			    "%s:%lu: NS record '%s' "
1019			    "appears to be an address",
1020			    source, line, DNS_AS_STR(*token));
1021	}
1022	if (tmp != NULL) {
1023		isc_mem_free(lctx->mctx, tmp);
1024	}
1025	return (result);
1026}
1027
1028static void
1029check_wildcard(dns_incctx_t *ictx, const char *source, unsigned long line,
1030	       dns_rdatacallbacks_t *callbacks) {
1031	dns_name_t *name;
1032
1033	name = (ictx->glue != NULL) ? ictx->glue : ictx->current;
1034	if (dns_name_internalwildcard(name)) {
1035		char namebuf[DNS_NAME_FORMATSIZE];
1036
1037		dns_name_format(name, namebuf, sizeof(namebuf));
1038		(*callbacks->warn)(callbacks,
1039				   "%s:%lu: warning: ownername "
1040				   "'%s' contains an non-terminal wildcard",
1041				   source, line, namebuf);
1042	}
1043}
1044
1045static isc_result_t
1046openfile_text(dns_loadctx_t *lctx, const char *master_file) {
1047	return (isc_lex_openfile(lctx->lex, master_file));
1048}
1049
1050static int
1051find_free_name(dns_incctx_t *incctx) {
1052	int i;
1053
1054	for (i = 0; i < (NBUFS - 1); i++) {
1055		if (!incctx->in_use[i]) {
1056			break;
1057		}
1058	}
1059	INSIST(!incctx->in_use[i]);
1060	return (i);
1061}
1062
1063static isc_result_t
1064load_text(dns_loadctx_t *lctx) {
1065	dns_rdataclass_t rdclass;
1066	dns_rdatatype_t type, covers;
1067	uint32_t ttl_offset = 0;
1068	dns_name_t *new_name;
1069	bool current_has_delegation = false;
1070	bool done = false;
1071	bool finish_origin = false;
1072	bool finish_include = false;
1073	bool read_till_eol = false;
1074	bool initialws;
1075	char *include_file = NULL;
1076	isc_token_t token;
1077	isc_result_t result = ISC_R_UNEXPECTED;
1078	rdatalist_head_t glue_list;
1079	rdatalist_head_t current_list;
1080	dns_rdatalist_t *this;
1081	dns_rdatalist_t *rdatalist = NULL;
1082	dns_rdatalist_t *new_rdatalist;
1083	int rdlcount = 0;
1084	int rdlcount_save = 0;
1085	int rdatalist_size = 0;
1086	isc_buffer_t buffer;
1087	isc_buffer_t target;
1088	isc_buffer_t target_ft;
1089	isc_buffer_t target_save;
1090	dns_rdata_t *rdata = NULL;
1091	dns_rdata_t *new_rdata;
1092	int rdcount = 0;
1093	int rdcount_save = 0;
1094	int rdata_size = 0;
1095	unsigned char *target_mem = NULL;
1096	int target_size = TSIZ;
1097	int new_in_use;
1098	unsigned int loop_cnt = 0;
1099	isc_mem_t *mctx;
1100	dns_rdatacallbacks_t *callbacks;
1101	dns_incctx_t *ictx;
1102	char *range = NULL;
1103	char *lhs = NULL;
1104	char *gtype = NULL;
1105	char *rhs = NULL;
1106	const char *source;
1107	unsigned long line = 0;
1108	bool explicit_ttl;
1109	char classname1[DNS_RDATACLASS_FORMATSIZE];
1110	char classname2[DNS_RDATACLASS_FORMATSIZE];
1111	unsigned int options = 0;
1112
1113	REQUIRE(DNS_LCTX_VALID(lctx));
1114	callbacks = lctx->callbacks;
1115	mctx = lctx->mctx;
1116	ictx = lctx->inc;
1117
1118	ISC_LIST_INIT(glue_list);
1119	ISC_LIST_INIT(current_list);
1120
1121	/*
1122	 * Allocate target_size of buffer space.  This is greater than twice
1123	 * the maximum individual RR data size.
1124	 */
1125	target_mem = isc_mem_get(mctx, target_size);
1126	isc_buffer_init(&target, target_mem, target_size);
1127	target_save = target;
1128
1129	if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0) {
1130		options |= DNS_RDATA_CHECKNAMES;
1131	}
1132	if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0) {
1133		options |= DNS_RDATA_CHECKNAMESFAIL;
1134	}
1135	if ((lctx->options & DNS_MASTER_CHECKMX) != 0) {
1136		options |= DNS_RDATA_CHECKMX;
1137	}
1138	if ((lctx->options & DNS_MASTER_CHECKMXFAIL) != 0) {
1139		options |= DNS_RDATA_CHECKMXFAIL;
1140	}
1141	source = isc_lex_getsourcename(lctx->lex);
1142	do {
1143		initialws = false;
1144		line = isc_lex_getsourceline(lctx->lex);
1145		GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS | ISC_LEXOPT_QSTRING,
1146			 &token, true);
1147		line = isc_lex_getsourceline(lctx->lex);
1148
1149		if (token.type == isc_tokentype_eof) {
1150			if (read_till_eol) {
1151				WARNUNEXPECTEDEOF(lctx->lex);
1152			}
1153			/* Pop the include stack? */
1154			if (ictx->parent != NULL) {
1155				COMMITALL;
1156				lctx->inc = ictx->parent;
1157				ictx->parent = NULL;
1158				incctx_destroy(lctx->mctx, ictx);
1159				RUNTIME_CHECK(isc_lex_close(lctx->lex) ==
1160					      ISC_R_SUCCESS);
1161				line = isc_lex_getsourceline(lctx->lex);
1162				POST(line);
1163				source = isc_lex_getsourcename(lctx->lex);
1164				ictx = lctx->inc;
1165				continue;
1166			}
1167			done = true;
1168			continue;
1169		}
1170
1171		if (token.type == isc_tokentype_eol) {
1172			read_till_eol = false;
1173			continue; /* blank line */
1174		}
1175
1176		if (read_till_eol) {
1177			continue;
1178		}
1179
1180		if (token.type == isc_tokentype_initialws) {
1181			/*
1182			 * Still working on the same name.
1183			 */
1184			initialws = true;
1185		} else if (token.type == isc_tokentype_string ||
1186			   token.type == isc_tokentype_qstring)
1187		{
1188			/*
1189			 * "$" Support.
1190			 *
1191			 * "$ORIGIN" and "$INCLUDE" can both take domain names.
1192			 * The processing of "$ORIGIN" and "$INCLUDE" extends
1193			 * across the normal domain name processing.
1194			 */
1195
1196			if (strcasecmp(DNS_AS_STR(token), "$ORIGIN") == 0) {
1197				GETTOKEN(lctx->lex, 0, &token, false);
1198				finish_origin = true;
1199			} else if (strcasecmp(DNS_AS_STR(token), "$TTL") == 0) {
1200				GETTOKENERR(lctx->lex, 0, &token, false,
1201					    lctx->ttl = 0;
1202					    lctx->default_ttl_known = true;);
1203				result = dns_ttl_fromtext(
1204					&token.value.as_textregion, &lctx->ttl);
1205				if (MANYERRS(lctx, result)) {
1206					SETRESULT(lctx, result);
1207					lctx->ttl = 0;
1208				} else if (result != ISC_R_SUCCESS) {
1209					goto insist_and_cleanup;
1210				}
1211				limit_ttl(callbacks, source, line, &lctx->ttl);
1212				lctx->default_ttl = lctx->ttl;
1213				lctx->default_ttl_known = true;
1214				EXPECTEOL;
1215				continue;
1216			} else if (strcasecmp(DNS_AS_STR(token), "$INCLUDE") ==
1217				   0)
1218			{
1219				COMMITALL;
1220				if ((lctx->options & DNS_MASTER_NOINCLUDE) != 0)
1221				{
1222					(callbacks->error)(callbacks,
1223							   "%s: %s:%lu: "
1224							   "$INCLUDE not "
1225							   "allowed",
1226							   "dns_master_load",
1227							   source, line);
1228					result = DNS_R_REFUSED;
1229					goto insist_and_cleanup;
1230				}
1231				if (ttl_offset != 0) {
1232					(callbacks->error)(callbacks,
1233							   "%s: %s:%lu: "
1234							   "$INCLUDE "
1235							   "may not be used "
1236							   "with $DATE",
1237							   "dns_master_load",
1238							   source, line);
1239					result = DNS_R_SYNTAX;
1240					goto insist_and_cleanup;
1241				}
1242				GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
1243					 false);
1244				if (include_file != NULL) {
1245					isc_mem_free(mctx, include_file);
1246				}
1247				include_file =
1248					isc_mem_strdup(mctx, DNS_AS_STR(token));
1249				GETTOKEN(lctx->lex, 0, &token, true);
1250
1251				if (token.type == isc_tokentype_eol ||
1252				    token.type == isc_tokentype_eof)
1253				{
1254					if (token.type == isc_tokentype_eof) {
1255						WARNUNEXPECTEDEOF(lctx->lex);
1256					}
1257					/*
1258					 * No origin field.
1259					 */
1260					result = pushfile(include_file,
1261							  ictx->origin, lctx);
1262					if (MANYERRS(lctx, result)) {
1263						SETRESULT(lctx, result);
1264						LOGITFILE(result, include_file);
1265						continue;
1266					} else if (result != ISC_R_SUCCESS) {
1267						LOGITFILE(result, include_file);
1268						goto insist_and_cleanup;
1269					}
1270					ictx = lctx->inc;
1271					source = isc_lex_getsourcename(
1272						lctx->lex);
1273					line = isc_lex_getsourceline(lctx->lex);
1274					POST(line);
1275					continue;
1276				}
1277				/*
1278				 * There is an origin field.  Fall through
1279				 * to domain name processing code and do
1280				 * the actual inclusion later.
1281				 */
1282				finish_include = true;
1283			} else if (strcasecmp(DNS_AS_STR(token), "$DATE") == 0)
1284			{
1285				int64_t dump_time64;
1286				isc_stdtime_t dump_time, current_time;
1287				GETTOKEN(lctx->lex, 0, &token, false);
1288				isc_stdtime_get(&current_time);
1289				result = dns_time64_fromtext(DNS_AS_STR(token),
1290							     &dump_time64);
1291				if (MANYERRS(lctx, result)) {
1292					SETRESULT(lctx, result);
1293					LOGIT(result);
1294					dump_time64 = 0;
1295				} else if (result != ISC_R_SUCCESS) {
1296					goto log_and_cleanup;
1297				}
1298				dump_time = (isc_stdtime_t)dump_time64;
1299				if (dump_time != dump_time64) {
1300					UNEXPECTED_ERROR(__FILE__, __LINE__,
1301							 "%s: %s:%lu: $DATE "
1302							 "outside epoch",
1303							 "dns_master_load",
1304							 source, line);
1305					result = ISC_R_UNEXPECTED;
1306					goto insist_and_cleanup;
1307				}
1308				if (dump_time > current_time) {
1309					UNEXPECTED_ERROR(__FILE__, __LINE__,
1310							 "%s: %s:%lu: "
1311							 "$DATE in future, "
1312							 "using current date",
1313							 "dns_master_load",
1314							 source, line);
1315					dump_time = current_time;
1316				}
1317				ttl_offset = current_time - dump_time;
1318				EXPECTEOL;
1319				continue;
1320			} else if (strcasecmp(DNS_AS_STR(token), "$GENERATE") ==
1321				   0)
1322			{
1323				/*
1324				 * Lazy cleanup.
1325				 */
1326				if (range != NULL) {
1327					isc_mem_free(mctx, range);
1328				}
1329				if (lhs != NULL) {
1330					isc_mem_free(mctx, lhs);
1331				}
1332				if (gtype != NULL) {
1333					isc_mem_free(mctx, gtype);
1334				}
1335				if (rhs != NULL) {
1336					isc_mem_free(mctx, rhs);
1337				}
1338				range = lhs = gtype = rhs = NULL;
1339				/* RANGE */
1340				GETTOKEN(lctx->lex, 0, &token, false);
1341				range = isc_mem_strdup(mctx, DNS_AS_STR(token));
1342				/* LHS */
1343				GETTOKEN(lctx->lex, 0, &token, false);
1344				lhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1345				rdclass = 0;
1346				explicit_ttl = false;
1347				/* CLASS? */
1348				GETTOKEN(lctx->lex, 0, &token, false);
1349				if (dns_rdataclass_fromtext(
1350					    &rdclass,
1351					    &token.value.as_textregion) ==
1352				    ISC_R_SUCCESS)
1353				{
1354					GETTOKEN(lctx->lex, 0, &token, false);
1355				}
1356				/* TTL? */
1357				if (dns_ttl_fromtext(&token.value.as_textregion,
1358						     &lctx->ttl) ==
1359				    ISC_R_SUCCESS)
1360				{
1361					limit_ttl(callbacks, source, line,
1362						  &lctx->ttl);
1363					lctx->ttl_known = true;
1364					explicit_ttl = true;
1365					GETTOKEN(lctx->lex, 0, &token, false);
1366				}
1367				/* CLASS? */
1368				if (rdclass == 0 &&
1369				    dns_rdataclass_fromtext(
1370					    &rdclass,
1371					    &token.value.as_textregion) ==
1372					    ISC_R_SUCCESS)
1373				{
1374					GETTOKEN(lctx->lex, 0, &token, false);
1375				}
1376				/* TYPE */
1377				gtype = isc_mem_strdup(mctx, DNS_AS_STR(token));
1378				/* RHS */
1379				GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
1380					 false);
1381				rhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1382				if (!lctx->ttl_known &&
1383				    !lctx->default_ttl_known)
1384				{
1385					(*callbacks->error)(callbacks,
1386							    "%s: %s:%lu: no "
1387							    "TTL specified",
1388							    "dns_master_load",
1389							    source, line);
1390					result = DNS_R_NOTTL;
1391					if (MANYERRS(lctx, result)) {
1392						SETRESULT(lctx, result);
1393						lctx->ttl = 0;
1394					} else {
1395						goto insist_and_cleanup;
1396					}
1397				} else if (!explicit_ttl &&
1398					   lctx->default_ttl_known)
1399				{
1400					lctx->ttl = lctx->default_ttl;
1401				}
1402				/*
1403				 * If the class specified does not match the
1404				 * zone's class print out a error message and
1405				 * exit.
1406				 */
1407				if (rdclass != 0 && rdclass != lctx->zclass) {
1408					goto bad_class;
1409				}
1410				result = generate(lctx, range, lhs, gtype, rhs,
1411						  source, line);
1412				if (MANYERRS(lctx, result)) {
1413					SETRESULT(lctx, result);
1414				} else if (result != ISC_R_SUCCESS) {
1415					goto insist_and_cleanup;
1416				}
1417				EXPECTEOL;
1418				continue;
1419			} else if (strncasecmp(DNS_AS_STR(token), "$", 1) == 0)
1420			{
1421				(callbacks->error)(callbacks,
1422						   "%s: %s:%lu: "
1423						   "unknown $ directive '%s'",
1424						   "dns_master_load", source,
1425						   line, DNS_AS_STR(token));
1426				result = DNS_R_SYNTAX;
1427				if (MANYERRS(lctx, result)) {
1428					SETRESULT(lctx, result);
1429				} else {
1430					goto insist_and_cleanup;
1431				}
1432			}
1433
1434			/*
1435			 * Normal processing resumes.
1436			 */
1437			new_in_use = find_free_name(ictx);
1438			new_name = dns_fixedname_initname(
1439				&ictx->fixed[new_in_use]);
1440			isc_buffer_init(&buffer, token.value.as_region.base,
1441					token.value.as_region.length);
1442			isc_buffer_add(&buffer, token.value.as_region.length);
1443			isc_buffer_setactive(&buffer,
1444					     token.value.as_region.length);
1445			result = dns_name_fromtext(new_name, &buffer,
1446						   ictx->origin, 0, NULL);
1447			if (MANYERRS(lctx, result)) {
1448				SETRESULT(lctx, result);
1449				LOGIT(result);
1450				read_till_eol = true;
1451				continue;
1452			} else if (result != ISC_R_SUCCESS) {
1453				goto log_and_cleanup;
1454			}
1455
1456			/*
1457			 * Finish $ORIGIN / $INCLUDE processing if required.
1458			 */
1459			if (finish_origin) {
1460				if (ictx->origin_in_use != -1) {
1461					ictx->in_use[ictx->origin_in_use] =
1462						false;
1463				}
1464				ictx->origin_in_use = new_in_use;
1465				ictx->in_use[ictx->origin_in_use] = true;
1466				ictx->origin = new_name;
1467				ictx->origin_changed = true;
1468				finish_origin = false;
1469				EXPECTEOL;
1470				continue;
1471			}
1472			if (finish_include) {
1473				finish_include = false;
1474				EXPECTEOL;
1475				result = pushfile(include_file, new_name, lctx);
1476				if (MANYERRS(lctx, result)) {
1477					SETRESULT(lctx, result);
1478					LOGITFILE(result, include_file);
1479					continue;
1480				} else if (result != ISC_R_SUCCESS) {
1481					LOGITFILE(result, include_file);
1482					goto insist_and_cleanup;
1483				}
1484				ictx = lctx->inc;
1485				ictx->origin_changed = true;
1486				source = isc_lex_getsourcename(lctx->lex);
1487				line = isc_lex_getsourceline(lctx->lex);
1488				POST(line);
1489				continue;
1490			}
1491
1492			/*
1493			 * "$" Processing Finished
1494			 */
1495
1496			/*
1497			 * If we are processing glue and the new name does
1498			 * not match the current glue name, commit the glue
1499			 * and pop stacks leaving us in 'normal' processing
1500			 * state.  Linked lists are undone by commit().
1501			 */
1502			if (ictx->glue != NULL &&
1503			    !dns_name_caseequal(ictx->glue, new_name))
1504			{
1505				result = commit(callbacks, lctx, &glue_list,
1506						ictx->glue, source,
1507						ictx->glue_line);
1508				if (MANYERRS(lctx, result)) {
1509					SETRESULT(lctx, result);
1510				} else if (result != ISC_R_SUCCESS) {
1511					goto insist_and_cleanup;
1512				}
1513				if (ictx->glue_in_use != -1) {
1514					ictx->in_use[ictx->glue_in_use] = false;
1515				}
1516				ictx->glue_in_use = -1;
1517				ictx->glue = NULL;
1518				rdcount = rdcount_save;
1519				rdlcount = rdlcount_save;
1520				target = target_save;
1521			}
1522
1523			/*
1524			 * If we are in 'normal' processing state and the new
1525			 * name does not match the current name, see if the
1526			 * new name is for glue and treat it as such,
1527			 * otherwise we have a new name so commit what we
1528			 * have.
1529			 */
1530			if ((ictx->glue == NULL) &&
1531			    (ictx->current == NULL ||
1532			     !dns_name_caseequal(ictx->current, new_name)))
1533			{
1534				if (current_has_delegation &&
1535				    is_glue(&current_list, new_name))
1536				{
1537					rdcount_save = rdcount;
1538					rdlcount_save = rdlcount;
1539					target_save = target;
1540					ictx->glue = new_name;
1541					ictx->glue_in_use = new_in_use;
1542					ictx->in_use[ictx->glue_in_use] = true;
1543				} else {
1544					result = commit(callbacks, lctx,
1545							&current_list,
1546							ictx->current, source,
1547							ictx->current_line);
1548					if (MANYERRS(lctx, result)) {
1549						SETRESULT(lctx, result);
1550					} else if (result != ISC_R_SUCCESS) {
1551						goto insist_and_cleanup;
1552					}
1553					rdcount = 0;
1554					rdlcount = 0;
1555					if (ictx->current_in_use != -1) {
1556						ictx->in_use
1557							[ictx->current_in_use] =
1558							false;
1559					}
1560					ictx->current_in_use = new_in_use;
1561					ictx->in_use[ictx->current_in_use] =
1562						true;
1563					ictx->current = new_name;
1564					current_has_delegation = false;
1565					isc_buffer_init(&target, target_mem,
1566							target_size);
1567				}
1568				/*
1569				 * Check for internal wildcards.
1570				 */
1571				if ((lctx->options &
1572				     DNS_MASTER_CHECKWILDCARD) != 0)
1573				{
1574					check_wildcard(ictx, source, line,
1575						       callbacks);
1576				}
1577			}
1578			if (dns_master_isprimary(lctx) &&
1579			    !dns_name_issubdomain(new_name, lctx->top))
1580			{
1581				char namebuf[DNS_NAME_FORMATSIZE];
1582				dns_name_format(new_name, namebuf,
1583						sizeof(namebuf));
1584				/*
1585				 * Ignore out-of-zone data.
1586				 */
1587				(*callbacks->warn)(callbacks,
1588						   "%s:%lu: "
1589						   "ignoring out-of-zone data "
1590						   "(%s)",
1591						   source, line, namebuf);
1592				ictx->drop = true;
1593			} else {
1594				ictx->drop = false;
1595			}
1596		} else {
1597			UNEXPECTED_ERROR(__FILE__, __LINE__,
1598					 "%s:%lu: isc_lex_gettoken() returned "
1599					 "unexpected token type (%d)",
1600					 source, line, token.type);
1601			result = ISC_R_UNEXPECTED;
1602			if (MANYERRS(lctx, result)) {
1603				SETRESULT(lctx, result);
1604				LOGIT(result);
1605				continue;
1606			} else {
1607				goto insist_and_cleanup;
1608			}
1609		}
1610
1611		/*
1612		 * Find TTL, class and type.  Both TTL and class are optional
1613		 * and may occur in any order if they exist. TTL and class
1614		 * come before type which must exist.
1615		 *
1616		 * [<TTL>] [<class>] <type> <RDATA>
1617		 * [<class>] [<TTL>] <type> <RDATA>
1618		 */
1619
1620		type = 0;
1621		rdclass = 0;
1622
1623		GETTOKEN(lctx->lex, 0, &token, initialws);
1624
1625		if (initialws) {
1626			if (token.type == isc_tokentype_eol) {
1627				read_till_eol = false;
1628				continue; /* blank line */
1629			}
1630
1631			if (token.type == isc_tokentype_eof) {
1632				WARNUNEXPECTEDEOF(lctx->lex);
1633				read_till_eol = false;
1634				isc_lex_ungettoken(lctx->lex, &token);
1635				continue;
1636			}
1637
1638			if (ictx->current == NULL) {
1639				(*callbacks->error)(callbacks,
1640						    "%s:%lu: no current owner "
1641						    "name",
1642						    source, line);
1643				result = DNS_R_NOOWNER;
1644				if (MANYERRS(lctx, result)) {
1645					SETRESULT(lctx, result);
1646					read_till_eol = true;
1647					continue;
1648				} else {
1649					goto insist_and_cleanup;
1650				}
1651			}
1652
1653			if (ictx->origin_changed) {
1654				char cbuf[DNS_NAME_FORMATSIZE];
1655				char obuf[DNS_NAME_FORMATSIZE];
1656				dns_name_format(ictx->current, cbuf,
1657						sizeof(cbuf));
1658				dns_name_format(ictx->origin, obuf,
1659						sizeof(obuf));
1660				(*callbacks->warn)(callbacks,
1661						   "%s:%lu: record with "
1662						   "inherited "
1663						   "owner (%s) immediately "
1664						   "after "
1665						   "$ORIGIN (%s)",
1666						   source, line, cbuf, obuf);
1667			}
1668		}
1669
1670		ictx->origin_changed = false;
1671
1672		if (dns_rdataclass_fromtext(&rdclass,
1673					    &token.value.as_textregion) ==
1674		    ISC_R_SUCCESS)
1675		{
1676			GETTOKEN(lctx->lex, 0, &token, false);
1677		}
1678
1679		explicit_ttl = false;
1680		result = dns_ttl_fromtext(&token.value.as_textregion,
1681					  &lctx->ttl);
1682		if (result == ISC_R_SUCCESS) {
1683			limit_ttl(callbacks, source, line, &lctx->ttl);
1684			explicit_ttl = true;
1685			lctx->ttl_known = true;
1686			GETTOKEN(lctx->lex, 0, &token, false);
1687		}
1688
1689		if (token.type != isc_tokentype_string) {
1690			UNEXPECTED_ERROR(__FILE__, __LINE__,
1691					 "isc_lex_gettoken() returned "
1692					 "unexpected token type");
1693			result = ISC_R_UNEXPECTED;
1694			if (MANYERRS(lctx, result)) {
1695				SETRESULT(lctx, result);
1696				read_till_eol = true;
1697				continue;
1698			} else {
1699				goto insist_and_cleanup;
1700			}
1701		}
1702
1703		if (rdclass == 0 &&
1704		    dns_rdataclass_fromtext(&rdclass,
1705					    &token.value.as_textregion) ==
1706			    ISC_R_SUCCESS)
1707		{
1708			GETTOKEN(lctx->lex, 0, &token, false);
1709		}
1710
1711		if (token.type != isc_tokentype_string) {
1712			UNEXPECTED_ERROR(__FILE__, __LINE__,
1713					 "isc_lex_gettoken() returned "
1714					 "unexpected token type");
1715			result = ISC_R_UNEXPECTED;
1716			if (MANYERRS(lctx, result)) {
1717				SETRESULT(lctx, result);
1718				read_till_eol = true;
1719				continue;
1720			} else {
1721				goto insist_and_cleanup;
1722			}
1723		}
1724
1725		result = dns_rdatatype_fromtext(&type,
1726						&token.value.as_textregion);
1727		if (result != ISC_R_SUCCESS) {
1728			(*callbacks->warn)(
1729				callbacks, "%s:%lu: unknown RR type '%.*s'",
1730				source, line, token.value.as_textregion.length,
1731				token.value.as_textregion.base);
1732			if (MANYERRS(lctx, result)) {
1733				SETRESULT(lctx, result);
1734				read_till_eol = true;
1735				continue;
1736			} else if (result != ISC_R_SUCCESS) {
1737				goto insist_and_cleanup;
1738			}
1739		}
1740
1741		/*
1742		 * If the class specified does not match the zone's class
1743		 * print out a error message and exit.
1744		 */
1745		if (rdclass != 0 && rdclass != lctx->zclass) {
1746		bad_class:
1747
1748			dns_rdataclass_format(rdclass, classname1,
1749					      sizeof(classname1));
1750			dns_rdataclass_format(lctx->zclass, classname2,
1751					      sizeof(classname2));
1752			(*callbacks->error)(callbacks,
1753					    "%s:%lu: class '%s' != "
1754					    "zone class '%s'",
1755					    source, line, classname1,
1756					    classname2);
1757			result = DNS_R_BADCLASS;
1758			if (MANYERRS(lctx, result)) {
1759				SETRESULT(lctx, result);
1760				read_till_eol = true;
1761				continue;
1762			} else {
1763				goto insist_and_cleanup;
1764			}
1765		}
1766
1767		if (type == dns_rdatatype_ns && ictx->glue == NULL) {
1768			current_has_delegation = true;
1769		}
1770
1771		/*
1772		 * RFC1123: MD and MF are not allowed to be loaded from
1773		 * master files.
1774		 */
1775		if (dns_master_isprimary(lctx) &&
1776		    (type == dns_rdatatype_md || type == dns_rdatatype_mf))
1777		{
1778			char typebuf[DNS_RDATATYPE_FORMATSIZE];
1779
1780			result = DNS_R_OBSOLETE;
1781
1782			dns_rdatatype_format(type, typebuf, sizeof(typebuf));
1783			(*callbacks->error)(callbacks, "%s:%lu: %s '%s': %s",
1784					    source, line, "type", typebuf,
1785					    dns_result_totext(result));
1786			if (MANYERRS(lctx, result)) {
1787				SETRESULT(lctx, result);
1788			} else {
1789				goto insist_and_cleanup;
1790			}
1791		}
1792
1793		/*
1794		 * RFC2930: TKEY and TSIG are not allowed to be loaded
1795		 * from master files.
1796		 */
1797		if (dns_master_isprimary(lctx) && dns_rdatatype_ismeta(type)) {
1798			char typebuf[DNS_RDATATYPE_FORMATSIZE];
1799
1800			result = DNS_R_METATYPE;
1801
1802			dns_rdatatype_format(type, typebuf, sizeof(typebuf));
1803			(*callbacks->error)(callbacks, "%s:%lu: %s '%s': %s",
1804					    source, line, "type", typebuf,
1805					    dns_result_totext(result));
1806			if (MANYERRS(lctx, result)) {
1807				SETRESULT(lctx, result);
1808			} else {
1809				goto insist_and_cleanup;
1810			}
1811		}
1812
1813		/*
1814		 * Find a rdata structure.
1815		 */
1816		if (rdcount == rdata_size) {
1817			new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
1818					       rdata_size, &current_list,
1819					       &glue_list, mctx);
1820			if (new_rdata == NULL) {
1821				result = ISC_R_NOMEMORY;
1822				goto log_and_cleanup;
1823			}
1824			rdata_size += RDSZ;
1825			rdata = new_rdata;
1826		}
1827
1828		/*
1829		 * Peek at the NS record.
1830		 */
1831		if (type == dns_rdatatype_ns &&
1832		    lctx->zclass == dns_rdataclass_in &&
1833		    (lctx->options & DNS_MASTER_CHECKNS) != 0)
1834		{
1835			GETTOKEN(lctx->lex, 0, &token, false);
1836			result = check_ns(lctx, &token, source, line);
1837			isc_lex_ungettoken(lctx->lex, &token);
1838			if ((lctx->options & DNS_MASTER_FATALNS) != 0) {
1839				if (MANYERRS(lctx, result)) {
1840					SETRESULT(lctx, result);
1841				} else if (result != ISC_R_SUCCESS) {
1842					goto insist_and_cleanup;
1843				}
1844			}
1845		}
1846
1847		/*
1848		 * Check owner name.
1849		 */
1850		options &= ~DNS_RDATA_CHECKREVERSE;
1851		if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0) {
1852			bool ok;
1853			dns_name_t *name;
1854
1855			name = (ictx->glue != NULL) ? ictx->glue
1856						    : ictx->current;
1857			ok = dns_rdata_checkowner(name, lctx->zclass, type,
1858						  true);
1859			if (!ok) {
1860				char namebuf[DNS_NAME_FORMATSIZE];
1861				const char *desc;
1862				dns_name_format(name, namebuf, sizeof(namebuf));
1863				result = DNS_R_BADOWNERNAME;
1864				desc = dns_result_totext(result);
1865				if (CHECKNAMESFAIL(lctx->options) ||
1866				    type == dns_rdatatype_nsec3)
1867				{
1868					(*callbacks->error)(
1869						callbacks, "%s:%lu: %s: %s",
1870						source, line, namebuf, desc);
1871					if (MANYERRS(lctx, result)) {
1872						SETRESULT(lctx, result);
1873					} else {
1874						goto cleanup;
1875					}
1876				} else {
1877					(*callbacks->warn)(
1878						callbacks, "%s:%lu: %s: %s",
1879						source, line, namebuf, desc);
1880				}
1881			}
1882			if (type == dns_rdatatype_ptr &&
1883			    !dns_name_isdnssd(name) &&
1884			    (dns_name_issubdomain(name, &in_addr_arpa) ||
1885			     dns_name_issubdomain(name, &ip6_arpa) ||
1886			     dns_name_issubdomain(name, &ip6_int)))
1887			{
1888				options |= DNS_RDATA_CHECKREVERSE;
1889			}
1890		}
1891
1892		/*
1893		 * Read rdata contents.
1894		 */
1895		dns_rdata_init(&rdata[rdcount]);
1896		target_ft = target;
1897		result = dns_rdata_fromtext(&rdata[rdcount], lctx->zclass, type,
1898					    lctx->lex, ictx->origin, options,
1899					    lctx->mctx, &target, callbacks);
1900		if (MANYERRS(lctx, result)) {
1901			SETRESULT(lctx, result);
1902			continue;
1903		} else if (result != ISC_R_SUCCESS) {
1904			goto insist_and_cleanup;
1905		}
1906
1907		if (ictx->drop) {
1908			target = target_ft;
1909			continue;
1910		}
1911
1912		if (type == dns_rdatatype_soa &&
1913		    (lctx->options & DNS_MASTER_ZONE) != 0 &&
1914		    !dns_name_equal(ictx->current, lctx->top))
1915		{
1916			char namebuf[DNS_NAME_FORMATSIZE];
1917			dns_name_format(ictx->current, namebuf,
1918					sizeof(namebuf));
1919			(*callbacks->error)(callbacks,
1920					    "%s:%lu: SOA "
1921					    "record not at top of zone (%s)",
1922					    source, line, namebuf);
1923			result = DNS_R_NOTZONETOP;
1924			if (MANYERRS(lctx, result)) {
1925				SETRESULT(lctx, result);
1926				read_till_eol = true;
1927				target = target_ft;
1928				continue;
1929			} else {
1930				goto insist_and_cleanup;
1931			}
1932		}
1933
1934		if (dns_rdatatype_atparent(type) &&
1935		    dns_master_isprimary(lctx) &&
1936		    dns_name_equal(ictx->current, lctx->top))
1937		{
1938			char namebuf[DNS_NAME_FORMATSIZE];
1939			char typebuf[DNS_RDATATYPE_FORMATSIZE];
1940
1941			dns_name_format(ictx->current, namebuf,
1942					sizeof(namebuf));
1943			dns_rdatatype_format(type, typebuf, sizeof(typebuf));
1944			(*callbacks->error)(
1945				callbacks,
1946				"%s:%lu: %s record at top of zone (%s)", source,
1947				line, typebuf, namebuf);
1948			result = DNS_R_ATZONETOP;
1949			if (MANYERRS(lctx, result)) {
1950				SETRESULT(lctx, result);
1951				target = target_ft;
1952				continue;
1953			} else {
1954				goto insist_and_cleanup;
1955			}
1956		}
1957
1958		if (type == dns_rdatatype_rrsig || type == dns_rdatatype_sig) {
1959			covers = dns_rdata_covers(&rdata[rdcount]);
1960		} else {
1961			covers = 0;
1962		}
1963
1964		if (!lctx->ttl_known && !lctx->default_ttl_known) {
1965			if (type == dns_rdatatype_soa) {
1966				(*callbacks->warn)(callbacks,
1967						   "%s:%lu: no TTL specified; "
1968						   "using SOA MINTTL instead",
1969						   source, line);
1970				lctx->ttl = dns_soa_getminimum(&rdata[rdcount]);
1971				limit_ttl(callbacks, source, line, &lctx->ttl);
1972				lctx->default_ttl = lctx->ttl;
1973				lctx->default_ttl_known = true;
1974			} else if ((lctx->options & DNS_MASTER_HINT) != 0) {
1975				/*
1976				 * Zero TTL's are fine for hints.
1977				 */
1978				lctx->ttl = 0;
1979				lctx->default_ttl = lctx->ttl;
1980				lctx->default_ttl_known = true;
1981			} else {
1982				(*callbacks->warn)(callbacks,
1983						   "%s:%lu: no TTL specified; "
1984						   "zone rejected",
1985						   source, line);
1986				result = DNS_R_NOTTL;
1987				if (MANYERRS(lctx, result)) {
1988					SETRESULT(lctx, result);
1989					lctx->ttl = 0;
1990				} else {
1991					goto insist_and_cleanup;
1992				}
1993			}
1994		} else if (!explicit_ttl && lctx->default_ttl_known) {
1995			lctx->ttl = lctx->default_ttl;
1996		} else if (!explicit_ttl && lctx->warn_1035) {
1997			(*callbacks->warn)(callbacks,
1998					   "%s:%lu: "
1999					   "using RFC1035 TTL semantics",
2000					   source, line);
2001			lctx->warn_1035 = false;
2002		}
2003
2004		if (type == dns_rdatatype_rrsig && lctx->warn_sigexpired) {
2005			dns_rdata_rrsig_t sig;
2006			result = dns_rdata_tostruct(&rdata[rdcount], &sig,
2007						    NULL);
2008			RUNTIME_CHECK(result == ISC_R_SUCCESS);
2009			if (isc_serial_lt(sig.timeexpire, lctx->now)) {
2010				(*callbacks->warn)(callbacks,
2011						   "%s:%lu: "
2012						   "signature has expired",
2013						   source, line);
2014				lctx->warn_sigexpired = false;
2015			}
2016		}
2017
2018		if ((type == dns_rdatatype_sig || type == dns_rdatatype_nxt) &&
2019		    lctx->warn_tcr && dns_master_isprimary(lctx))
2020		{
2021			(*callbacks->warn)(callbacks,
2022					   "%s:%lu: old style DNSSEC "
2023					   " zone detected",
2024					   source, line);
2025			lctx->warn_tcr = false;
2026		}
2027
2028		if ((lctx->options & DNS_MASTER_AGETTL) != 0) {
2029			/*
2030			 * Adjust the TTL for $DATE. If the RR has
2031			 * already expired, set its TTL to 0. This
2032			 * should be okay even if the TTL stretching
2033			 * feature is not in effect, because it will
2034			 * just be quickly expired by the cache, and the
2035			 * way this was written before the patch it
2036			 * could potentially add 0 TTLs anyway.
2037			 */
2038			if (lctx->ttl < ttl_offset) {
2039				lctx->ttl = 0;
2040			} else {
2041				lctx->ttl -= ttl_offset;
2042			}
2043		}
2044
2045		/*
2046		 * Find type in rdatalist.
2047		 * If it does not exist create new one and prepend to list
2048		 * as this will minimise list traversal.
2049		 */
2050		if (ictx->glue != NULL) {
2051			this = ISC_LIST_HEAD(glue_list);
2052		} else {
2053			this = ISC_LIST_HEAD(current_list);
2054		}
2055
2056		while (this != NULL) {
2057			if (this->type == type && this->covers == covers) {
2058				break;
2059			}
2060			this = ISC_LIST_NEXT(this, link);
2061		}
2062
2063		if (this == NULL) {
2064			if (rdlcount == rdatalist_size) {
2065				new_rdatalist = grow_rdatalist(
2066					rdatalist_size + RDLSZ, rdatalist,
2067					rdatalist_size, &current_list,
2068					&glue_list, mctx);
2069				if (new_rdatalist == NULL) {
2070					result = ISC_R_NOMEMORY;
2071					goto log_and_cleanup;
2072				}
2073				rdatalist = new_rdatalist;
2074				rdatalist_size += RDLSZ;
2075			}
2076			this = &rdatalist[rdlcount++];
2077			dns_rdatalist_init(this);
2078			this->type = type;
2079			this->covers = covers;
2080			this->rdclass = lctx->zclass;
2081			this->ttl = lctx->ttl;
2082			if (ictx->glue != NULL) {
2083				ISC_LIST_INITANDPREPEND(glue_list, this, link);
2084			} else {
2085				ISC_LIST_INITANDPREPEND(current_list, this,
2086							link);
2087			}
2088		} else if (this->ttl != lctx->ttl) {
2089			(*callbacks->warn)(callbacks,
2090					   "%s:%lu: "
2091					   "TTL set to prior TTL (%lu)",
2092					   source, line, this->ttl);
2093			lctx->ttl = this->ttl;
2094		}
2095
2096		if ((lctx->options & DNS_MASTER_CHECKTTL) != 0 &&
2097		    lctx->ttl > lctx->maxttl)
2098		{
2099			(callbacks->error)(callbacks,
2100					   "dns_master_load: %s:%lu: "
2101					   "TTL %d exceeds configured "
2102					   "max-zone-ttl %d",
2103					   source, line, lctx->ttl,
2104					   lctx->maxttl);
2105			result = ISC_R_RANGE;
2106			goto log_and_cleanup;
2107		}
2108
2109		ISC_LIST_APPEND(this->rdata, &rdata[rdcount], link);
2110		if (ictx->glue != NULL) {
2111			ictx->glue_line = line;
2112		} else {
2113			ictx->current_line = line;
2114		}
2115		rdcount++;
2116
2117		/*
2118		 * We must have at least 64k as rdlen is 16 bits.
2119		 * If we don't commit everything we have so far.
2120		 */
2121		if ((target.length - target.used) < MINTSIZ) {
2122			COMMITALL;
2123		}
2124	next_line:;
2125	} while (!done && (lctx->loop_cnt == 0 || loop_cnt++ < lctx->loop_cnt));
2126
2127	/*
2128	 * Commit what has not yet been committed.
2129	 */
2130	result = commit(callbacks, lctx, &current_list, ictx->current, source,
2131			ictx->current_line);
2132	if (MANYERRS(lctx, result)) {
2133		SETRESULT(lctx, result);
2134	} else if (result != ISC_R_SUCCESS) {
2135		goto insist_and_cleanup;
2136	}
2137	result = commit(callbacks, lctx, &glue_list, ictx->glue, source,
2138			ictx->glue_line);
2139	if (MANYERRS(lctx, result)) {
2140		SETRESULT(lctx, result);
2141	} else if (result != ISC_R_SUCCESS) {
2142		goto insist_and_cleanup;
2143	}
2144
2145	if (!done) {
2146		INSIST(lctx->done != NULL && lctx->task != NULL);
2147		result = DNS_R_CONTINUE;
2148	} else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) {
2149		result = lctx->result;
2150	} else if (result == ISC_R_SUCCESS && lctx->seen_include) {
2151		result = DNS_R_SEENINCLUDE;
2152	}
2153	goto cleanup;
2154
2155log_and_cleanup:
2156	LOGIT(result);
2157
2158insist_and_cleanup:
2159	INSIST(result != ISC_R_SUCCESS);
2160
2161cleanup:
2162	while ((this = ISC_LIST_HEAD(current_list)) != NULL) {
2163		ISC_LIST_UNLINK(current_list, this, link);
2164	}
2165	while ((this = ISC_LIST_HEAD(glue_list)) != NULL) {
2166		ISC_LIST_UNLINK(glue_list, this, link);
2167	}
2168	if (rdatalist != NULL) {
2169		isc_mem_put(mctx, rdatalist,
2170			    rdatalist_size * sizeof(*rdatalist));
2171	}
2172	if (rdata != NULL) {
2173		isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
2174	}
2175	if (target_mem != NULL) {
2176		isc_mem_put(mctx, target_mem, target_size);
2177	}
2178	if (include_file != NULL) {
2179		isc_mem_free(mctx, include_file);
2180	}
2181	if (range != NULL) {
2182		isc_mem_free(mctx, range);
2183	}
2184	if (lhs != NULL) {
2185		isc_mem_free(mctx, lhs);
2186	}
2187	if (gtype != NULL) {
2188		isc_mem_free(mctx, gtype);
2189	}
2190	if (rhs != NULL) {
2191		isc_mem_free(mctx, rhs);
2192	}
2193	return (result);
2194}
2195
2196static isc_result_t
2197pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) {
2198	isc_result_t result;
2199	dns_incctx_t *ictx;
2200	dns_incctx_t *newctx = NULL;
2201	isc_region_t r;
2202
2203	REQUIRE(master_file != NULL);
2204	REQUIRE(DNS_LCTX_VALID(lctx));
2205
2206	ictx = lctx->inc;
2207	lctx->seen_include = true;
2208
2209	result = incctx_create(lctx->mctx, origin, &newctx);
2210	if (result != ISC_R_SUCCESS) {
2211		return (result);
2212	}
2213
2214	/*
2215	 * Push origin_changed.
2216	 */
2217	newctx->origin_changed = ictx->origin_changed;
2218
2219	/* Set current domain. */
2220	if (ictx->glue != NULL || ictx->current != NULL) {
2221		newctx->current_in_use = find_free_name(newctx);
2222		newctx->current = dns_fixedname_name(
2223			&newctx->fixed[newctx->current_in_use]);
2224		newctx->in_use[newctx->current_in_use] = true;
2225		dns_name_toregion(
2226			(ictx->glue != NULL) ? ictx->glue : ictx->current, &r);
2227		dns_name_fromregion(newctx->current, &r);
2228		newctx->drop = ictx->drop;
2229	}
2230
2231	result = (lctx->openfile)(lctx, master_file);
2232	if (result != ISC_R_SUCCESS) {
2233		goto cleanup;
2234	}
2235	newctx->parent = ictx;
2236	lctx->inc = newctx;
2237
2238	if (lctx->include_cb != NULL) {
2239		lctx->include_cb(master_file, lctx->include_arg);
2240	}
2241	return (ISC_R_SUCCESS);
2242
2243cleanup:
2244	incctx_destroy(lctx->mctx, newctx);
2245	return (result);
2246}
2247
2248/*
2249 * Fill/check exists buffer with 'len' bytes.  Track remaining bytes to be
2250 * read when incrementally filling the buffer.
2251 */
2252static isc_result_t
2253read_and_check(bool do_read, isc_buffer_t *buffer, size_t len, FILE *f,
2254	       uint32_t *totallen) {
2255	isc_result_t result;
2256
2257	REQUIRE(totallen != NULL);
2258
2259	if (do_read) {
2260		INSIST(isc_buffer_availablelength(buffer) >= len);
2261		result = isc_stdio_read(isc_buffer_used(buffer), 1, len, f,
2262					NULL);
2263		if (result != ISC_R_SUCCESS) {
2264			return (result);
2265		}
2266		isc_buffer_add(buffer, (unsigned int)len);
2267		if (*totallen < len) {
2268			return (ISC_R_RANGE);
2269		}
2270		*totallen -= (uint32_t)len;
2271	} else if (isc_buffer_remaininglength(buffer) < len) {
2272		return (ISC_R_RANGE);
2273	}
2274
2275	return (ISC_R_SUCCESS);
2276}
2277
2278static isc_result_t
2279load_header(dns_loadctx_t *lctx) {
2280	isc_result_t result = ISC_R_SUCCESS;
2281	dns_masterrawheader_t header;
2282	dns_rdatacallbacks_t *callbacks;
2283	size_t commonlen = sizeof(header.format) + sizeof(header.version);
2284	size_t remainder;
2285	unsigned char data[sizeof(header)];
2286	isc_buffer_t target;
2287
2288	REQUIRE(DNS_LCTX_VALID(lctx));
2289
2290	if (lctx->format != dns_masterformat_raw &&
2291	    lctx->format != dns_masterformat_map)
2292	{
2293		return (ISC_R_NOTIMPLEMENTED);
2294	}
2295
2296	callbacks = lctx->callbacks;
2297	dns_master_initrawheader(&header);
2298
2299	INSIST(commonlen <= sizeof(header));
2300	isc_buffer_init(&target, data, sizeof(data));
2301
2302	result = isc_stdio_read(data, 1, commonlen, lctx->f, NULL);
2303	if (result != ISC_R_SUCCESS) {
2304		UNEXPECTED_ERROR(__FILE__, __LINE__,
2305				 "isc_stdio_read failed: %s",
2306				 isc_result_totext(result));
2307		return (result);
2308	}
2309
2310	isc_buffer_add(&target, (unsigned int)commonlen);
2311	header.format = isc_buffer_getuint32(&target);
2312	if (header.format != lctx->format) {
2313		(*callbacks->error)(callbacks,
2314				    "dns_master_load: "
2315				    "file format mismatch (not %s)",
2316				    lctx->format == dns_masterformat_map ? "map"
2317									 : "ra"
2318									   "w");
2319		return (ISC_R_NOTIMPLEMENTED);
2320	}
2321
2322	header.version = isc_buffer_getuint32(&target);
2323
2324	switch (header.version) {
2325	case 0:
2326		remainder = sizeof(header.dumptime);
2327		break;
2328	case DNS_RAWFORMAT_VERSION:
2329		remainder = sizeof(header) - commonlen;
2330		break;
2331	default:
2332		(*callbacks->error)(callbacks, "dns_master_load: "
2333					       "unsupported file format "
2334					       "version");
2335		return (ISC_R_NOTIMPLEMENTED);
2336	}
2337
2338	result = isc_stdio_read(data + commonlen, 1, remainder, lctx->f, NULL);
2339	if (result != ISC_R_SUCCESS) {
2340		UNEXPECTED_ERROR(__FILE__, __LINE__,
2341				 "isc_stdio_read failed: %s",
2342				 isc_result_totext(result));
2343		return (result);
2344	}
2345
2346	isc_buffer_add(&target, (unsigned int)remainder);
2347	header.dumptime = isc_buffer_getuint32(&target);
2348	if (header.version == DNS_RAWFORMAT_VERSION) {
2349		header.flags = isc_buffer_getuint32(&target);
2350		header.sourceserial = isc_buffer_getuint32(&target);
2351		header.lastxfrin = isc_buffer_getuint32(&target);
2352	}
2353
2354	lctx->first = false;
2355	lctx->header = header;
2356
2357	return (ISC_R_SUCCESS);
2358}
2359
2360static isc_result_t
2361openfile_map(dns_loadctx_t *lctx, const char *master_file) {
2362	isc_result_t result;
2363
2364	result = isc_stdio_open(master_file, "rb", &lctx->f);
2365	if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
2366		UNEXPECTED_ERROR(__FILE__, __LINE__,
2367				 "isc_stdio_open() failed: %s",
2368				 isc_result_totext(result));
2369	}
2370
2371	return (result);
2372}
2373
2374/*
2375 * Load a map format file, using mmap() to access RBT trees directly
2376 */
2377static isc_result_t
2378load_map(dns_loadctx_t *lctx) {
2379	isc_result_t result = ISC_R_SUCCESS;
2380	dns_rdatacallbacks_t *callbacks;
2381
2382	REQUIRE(DNS_LCTX_VALID(lctx));
2383
2384	callbacks = lctx->callbacks;
2385
2386	if (lctx->first) {
2387		result = load_header(lctx);
2388		if (result != ISC_R_SUCCESS) {
2389			return (result);
2390		}
2391
2392		result = (*callbacks->deserialize)(
2393			callbacks->deserialize_private, lctx->f,
2394			sizeof(dns_masterrawheader_t));
2395	}
2396
2397	return (result);
2398}
2399
2400static isc_result_t
2401openfile_raw(dns_loadctx_t *lctx, const char *master_file) {
2402	isc_result_t result;
2403
2404	result = isc_stdio_open(master_file, "rb", &lctx->f);
2405	if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
2406		UNEXPECTED_ERROR(__FILE__, __LINE__,
2407				 "isc_stdio_open() failed: %s",
2408				 isc_result_totext(result));
2409	}
2410
2411	return (result);
2412}
2413
2414static isc_result_t
2415load_raw(dns_loadctx_t *lctx) {
2416	isc_result_t result = ISC_R_SUCCESS;
2417	bool done = false;
2418	unsigned int loop_cnt = 0;
2419	dns_rdatacallbacks_t *callbacks;
2420	unsigned char namebuf[DNS_NAME_MAXWIRE];
2421	dns_fixedname_t fixed;
2422	dns_name_t *name;
2423	rdatalist_head_t head, dummy;
2424	dns_rdatalist_t rdatalist;
2425	isc_mem_t *mctx = lctx->mctx;
2426	dns_rdata_t *rdata = NULL;
2427	unsigned int rdata_size = 0;
2428	int target_size = TSIZ;
2429	isc_buffer_t target, buf;
2430	unsigned char *target_mem = NULL;
2431	dns_decompress_t dctx;
2432
2433	callbacks = lctx->callbacks;
2434	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
2435
2436	if (lctx->first) {
2437		result = load_header(lctx);
2438		if (result != ISC_R_SUCCESS) {
2439			return (result);
2440		}
2441	}
2442
2443	ISC_LIST_INIT(head);
2444	ISC_LIST_INIT(dummy);
2445
2446	/*
2447	 * Allocate target_size of buffer space.  This is greater than twice
2448	 * the maximum individual RR data size.
2449	 */
2450	target_mem = isc_mem_get(mctx, target_size);
2451	isc_buffer_init(&target, target_mem, target_size);
2452
2453	name = dns_fixedname_initname(&fixed);
2454
2455	/*
2456	 * In the following loop, we regard any error fatal regardless of
2457	 * whether "MANYERRORS" is set in the context option.  This is because
2458	 * normal errors should already have been checked at creation time.
2459	 * Besides, it is very unlikely that we can recover from an error
2460	 * in this format, and so trying to continue parsing erroneous data
2461	 * does not really make sense.
2462	 */
2463	for (loop_cnt = 0; (lctx->loop_cnt == 0 || loop_cnt < lctx->loop_cnt);
2464	     loop_cnt++)
2465	{
2466		unsigned int i, rdcount;
2467		uint16_t namelen;
2468		uint32_t totallen;
2469		size_t minlen, readlen;
2470		bool sequential_read = false;
2471
2472		/* Read the data length */
2473		isc_buffer_clear(&target);
2474		INSIST(isc_buffer_availablelength(&target) >= sizeof(totallen));
2475		result = isc_stdio_read(target.base, 1, sizeof(totallen),
2476					lctx->f, NULL);
2477		if (result == ISC_R_EOF) {
2478			result = ISC_R_SUCCESS;
2479			done = true;
2480			break;
2481		}
2482		if (result != ISC_R_SUCCESS) {
2483			goto cleanup;
2484		}
2485		isc_buffer_add(&target, sizeof(totallen));
2486		totallen = isc_buffer_getuint32(&target);
2487
2488		/*
2489		 * Validation: the input data must at least contain the common
2490		 * header.
2491		 */
2492		minlen = sizeof(totallen) + sizeof(uint16_t) +
2493			 sizeof(uint16_t) + sizeof(uint16_t) +
2494			 sizeof(uint32_t) + sizeof(uint32_t);
2495		if (totallen < minlen) {
2496			result = ISC_R_RANGE;
2497			goto cleanup;
2498		}
2499		totallen -= sizeof(totallen);
2500
2501		isc_buffer_clear(&target);
2502		if (totallen > isc_buffer_availablelength(&target)) {
2503			/*
2504			 * The default buffer size should typically be large
2505			 * enough to store the entire RRset.  We could try to
2506			 * allocate enough space if this is not the case, but
2507			 * it might cause a hazardous result when "totallen"
2508			 * is forged.  Thus, we'd rather take an inefficient
2509			 * but robust approach in this atypical case: read
2510			 * data step by step, and commit partial data when
2511			 * necessary.  Note that the buffer must be large
2512			 * enough to store the "header part", owner name, and
2513			 * at least one rdata (however large it is).
2514			 */
2515			sequential_read = true;
2516			readlen = minlen - sizeof(totallen);
2517		} else {
2518			/*
2519			 * Typical case.  We can read the whole RRset at once
2520			 * with the default buffer.
2521			 */
2522			readlen = totallen;
2523		}
2524		result = isc_stdio_read(target.base, 1, readlen, lctx->f, NULL);
2525		if (result != ISC_R_SUCCESS) {
2526			goto cleanup;
2527		}
2528		isc_buffer_add(&target, (unsigned int)readlen);
2529		totallen -= (uint32_t)readlen;
2530
2531		/* Construct RRset headers */
2532		dns_rdatalist_init(&rdatalist);
2533		rdatalist.rdclass = isc_buffer_getuint16(&target);
2534		if (lctx->zclass != rdatalist.rdclass) {
2535			result = DNS_R_BADCLASS;
2536			goto cleanup;
2537		}
2538		rdatalist.type = isc_buffer_getuint16(&target);
2539		rdatalist.covers = isc_buffer_getuint16(&target);
2540		rdatalist.ttl = isc_buffer_getuint32(&target);
2541		rdcount = isc_buffer_getuint32(&target);
2542		if (rdcount == 0 || rdcount > 0xffff) {
2543			result = ISC_R_RANGE;
2544			goto cleanup;
2545		}
2546		INSIST(isc_buffer_consumedlength(&target) <= readlen);
2547
2548		/* Owner name: length followed by name */
2549		result = read_and_check(sequential_read, &target,
2550					sizeof(namelen), lctx->f, &totallen);
2551		if (result != ISC_R_SUCCESS) {
2552			goto cleanup;
2553		}
2554		namelen = isc_buffer_getuint16(&target);
2555		if (namelen > sizeof(namebuf)) {
2556			result = ISC_R_RANGE;
2557			goto cleanup;
2558		}
2559
2560		result = read_and_check(sequential_read, &target, namelen,
2561					lctx->f, &totallen);
2562		if (result != ISC_R_SUCCESS) {
2563			goto cleanup;
2564		}
2565
2566		isc_buffer_setactive(&target, (unsigned int)namelen);
2567		result = dns_name_fromwire(name, &target, &dctx, 0, NULL);
2568		if (result != ISC_R_SUCCESS) {
2569			goto cleanup;
2570		}
2571
2572		if ((lctx->options & DNS_MASTER_CHECKTTL) != 0 &&
2573		    rdatalist.ttl > lctx->maxttl)
2574		{
2575			(callbacks->error)(callbacks,
2576					   "dns_master_load: "
2577					   "TTL %d exceeds configured "
2578					   "max-zone-ttl %d",
2579					   rdatalist.ttl, lctx->maxttl);
2580			result = ISC_R_RANGE;
2581			goto cleanup;
2582		}
2583
2584		/* Rdata contents. */
2585		if (rdcount > rdata_size) {
2586			dns_rdata_t *new_rdata = NULL;
2587
2588			new_rdata = grow_rdata(rdcount + RDSZ, rdata,
2589					       rdata_size, &head, &dummy, mctx);
2590			if (new_rdata == NULL) {
2591				result = ISC_R_NOMEMORY;
2592				goto cleanup;
2593			}
2594			rdata_size = rdcount + RDSZ;
2595			rdata = new_rdata;
2596		}
2597
2598	continue_read:
2599		for (i = 0; i < rdcount; i++) {
2600			uint16_t rdlen;
2601
2602			dns_rdata_init(&rdata[i]);
2603
2604			if (sequential_read &&
2605			    isc_buffer_availablelength(&target) < MINTSIZ)
2606			{
2607				unsigned int j;
2608
2609				INSIST(i > 0); /* detect an infinite loop */
2610
2611				/* Partial Commit. */
2612				ISC_LIST_APPEND(head, &rdatalist, link);
2613				result = commit(callbacks, lctx, &head, name,
2614						NULL, 0);
2615				for (j = 0; j < i; j++) {
2616					ISC_LIST_UNLINK(rdatalist.rdata,
2617							&rdata[j], link);
2618					dns_rdata_reset(&rdata[j]);
2619				}
2620				if (result != ISC_R_SUCCESS) {
2621					goto cleanup;
2622				}
2623
2624				/* Rewind the buffer and continue */
2625				isc_buffer_clear(&target);
2626
2627				rdcount -= i;
2628
2629				goto continue_read;
2630			}
2631
2632			/* rdata length */
2633			result = read_and_check(sequential_read, &target,
2634						sizeof(rdlen), lctx->f,
2635						&totallen);
2636			if (result != ISC_R_SUCCESS) {
2637				goto cleanup;
2638			}
2639			rdlen = isc_buffer_getuint16(&target);
2640
2641			/* rdata */
2642			result = read_and_check(sequential_read, &target, rdlen,
2643						lctx->f, &totallen);
2644			if (result != ISC_R_SUCCESS) {
2645				goto cleanup;
2646			}
2647			isc_buffer_setactive(&target, (unsigned int)rdlen);
2648			/*
2649			 * It is safe to have the source active region and
2650			 * the target available region be the same if
2651			 * decompression is disabled (see dctx above) and we
2652			 * are not downcasing names (options == 0).
2653			 */
2654			isc_buffer_init(&buf, isc_buffer_current(&target),
2655					(unsigned int)rdlen);
2656			result = dns_rdata_fromwire(
2657				&rdata[i], rdatalist.rdclass, rdatalist.type,
2658				&target, &dctx, 0, &buf);
2659			if (result != ISC_R_SUCCESS) {
2660				goto cleanup;
2661			}
2662			ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link);
2663		}
2664
2665		/*
2666		 * Sanity check.  Still having remaining space is not
2667		 * necessarily critical, but it very likely indicates broken
2668		 * or malformed data.
2669		 */
2670		if (isc_buffer_remaininglength(&target) != 0 || totallen != 0) {
2671			result = ISC_R_RANGE;
2672			goto cleanup;
2673		}
2674
2675		ISC_LIST_APPEND(head, &rdatalist, link);
2676
2677		/* Commit this RRset.  rdatalist will be unlinked. */
2678		result = commit(callbacks, lctx, &head, name, NULL, 0);
2679
2680		for (i = 0; i < rdcount; i++) {
2681			ISC_LIST_UNLINK(rdatalist.rdata, &rdata[i], link);
2682			dns_rdata_reset(&rdata[i]);
2683		}
2684
2685		if (result != ISC_R_SUCCESS) {
2686			goto cleanup;
2687		}
2688	}
2689
2690	if (!done) {
2691		INSIST(lctx->done != NULL && lctx->task != NULL);
2692		result = DNS_R_CONTINUE;
2693	} else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) {
2694		result = lctx->result;
2695	}
2696
2697	if (result == ISC_R_SUCCESS && callbacks->rawdata != NULL) {
2698		(*callbacks->rawdata)(callbacks->zone, &lctx->header);
2699	}
2700
2701cleanup:
2702	if (rdata != NULL) {
2703		isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
2704	}
2705	if (target_mem != NULL) {
2706		isc_mem_put(mctx, target_mem, target_size);
2707	}
2708	if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE) {
2709		(*callbacks->error)(callbacks, "dns_master_load: %s",
2710				    dns_result_totext(result));
2711	}
2712
2713	return (result);
2714}
2715
2716isc_result_t
2717dns_master_loadfile(const char *master_file, dns_name_t *top,
2718		    dns_name_t *origin, dns_rdataclass_t zclass,
2719		    unsigned int options, uint32_t resign,
2720		    dns_rdatacallbacks_t *callbacks,
2721		    dns_masterincludecb_t include_cb, void *include_arg,
2722		    isc_mem_t *mctx, dns_masterformat_t format,
2723		    dns_ttl_t maxttl) {
2724	dns_loadctx_t *lctx = NULL;
2725	isc_result_t result;
2726
2727	result = loadctx_create(format, mctx, options, resign, top, zclass,
2728				origin, callbacks, NULL, NULL, NULL, include_cb,
2729				include_arg, NULL, &lctx);
2730	if (result != ISC_R_SUCCESS) {
2731		return (result);
2732	}
2733
2734	lctx->maxttl = maxttl;
2735
2736	result = (lctx->openfile)(lctx, master_file);
2737	if (result != ISC_R_SUCCESS) {
2738		goto cleanup;
2739	}
2740
2741	result = (lctx->load)(lctx);
2742	INSIST(result != DNS_R_CONTINUE);
2743
2744cleanup:
2745	dns_loadctx_detach(&lctx);
2746	return (result);
2747}
2748
2749isc_result_t
2750dns_master_loadfileinc(const char *master_file, dns_name_t *top,
2751		       dns_name_t *origin, dns_rdataclass_t zclass,
2752		       unsigned int options, uint32_t resign,
2753		       dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2754		       dns_loaddonefunc_t done, void *done_arg,
2755		       dns_loadctx_t **lctxp, dns_masterincludecb_t include_cb,
2756		       void *include_arg, isc_mem_t *mctx,
2757		       dns_masterformat_t format, uint32_t maxttl) {
2758	dns_loadctx_t *lctx = NULL;
2759	isc_result_t result;
2760
2761	REQUIRE(task != NULL);
2762	REQUIRE(done != NULL);
2763
2764	result = loadctx_create(format, mctx, options, resign, top, zclass,
2765				origin, callbacks, task, done, done_arg,
2766				include_cb, include_arg, NULL, &lctx);
2767	if (result != ISC_R_SUCCESS) {
2768		return (result);
2769	}
2770
2771	lctx->maxttl = maxttl;
2772
2773	result = (lctx->openfile)(lctx, master_file);
2774	if (result != ISC_R_SUCCESS) {
2775		goto cleanup;
2776	}
2777
2778	result = task_send(lctx);
2779	if (result == ISC_R_SUCCESS) {
2780		dns_loadctx_attach(lctx, lctxp);
2781		return (DNS_R_CONTINUE);
2782	}
2783
2784cleanup:
2785	dns_loadctx_detach(&lctx);
2786	return (result);
2787}
2788
2789isc_result_t
2790dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
2791		      dns_rdataclass_t zclass, unsigned int options,
2792		      dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx) {
2793	isc_result_t result;
2794	dns_loadctx_t *lctx = NULL;
2795
2796	REQUIRE(stream != NULL);
2797
2798	result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2799				zclass, origin, callbacks, NULL, NULL, NULL,
2800				NULL, NULL, NULL, &lctx);
2801	if (result != ISC_R_SUCCESS) {
2802		goto cleanup;
2803	}
2804
2805	result = isc_lex_openstream(lctx->lex, stream);
2806	if (result != ISC_R_SUCCESS) {
2807		goto cleanup;
2808	}
2809
2810	result = (lctx->load)(lctx);
2811	INSIST(result != DNS_R_CONTINUE);
2812
2813cleanup:
2814	if (lctx != NULL) {
2815		dns_loadctx_detach(&lctx);
2816	}
2817	return (result);
2818}
2819
2820isc_result_t
2821dns_master_loadstreaminc(FILE *stream, dns_name_t *top, dns_name_t *origin,
2822			 dns_rdataclass_t zclass, unsigned int options,
2823			 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2824			 dns_loaddonefunc_t done, void *done_arg,
2825			 dns_loadctx_t **lctxp, isc_mem_t *mctx) {
2826	isc_result_t result;
2827	dns_loadctx_t *lctx = NULL;
2828
2829	REQUIRE(stream != NULL);
2830	REQUIRE(task != NULL);
2831	REQUIRE(done != NULL);
2832
2833	result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2834				zclass, origin, callbacks, task, done, done_arg,
2835				NULL, NULL, NULL, &lctx);
2836	if (result != ISC_R_SUCCESS) {
2837		goto cleanup;
2838	}
2839
2840	result = isc_lex_openstream(lctx->lex, stream);
2841	if (result != ISC_R_SUCCESS) {
2842		goto cleanup;
2843	}
2844
2845	result = task_send(lctx);
2846	if (result == ISC_R_SUCCESS) {
2847		dns_loadctx_attach(lctx, lctxp);
2848		return (DNS_R_CONTINUE);
2849	}
2850
2851cleanup:
2852	if (lctx != NULL) {
2853		dns_loadctx_detach(&lctx);
2854	}
2855	return (result);
2856}
2857
2858isc_result_t
2859dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top, dns_name_t *origin,
2860		      dns_rdataclass_t zclass, unsigned int options,
2861		      dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx) {
2862	isc_result_t result;
2863	dns_loadctx_t *lctx = NULL;
2864
2865	REQUIRE(buffer != NULL);
2866
2867	result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2868				zclass, origin, callbacks, NULL, NULL, NULL,
2869				NULL, NULL, NULL, &lctx);
2870	if (result != ISC_R_SUCCESS) {
2871		return (result);
2872	}
2873
2874	result = isc_lex_openbuffer(lctx->lex, buffer);
2875	if (result != ISC_R_SUCCESS) {
2876		goto cleanup;
2877	}
2878
2879	result = (lctx->load)(lctx);
2880	INSIST(result != DNS_R_CONTINUE);
2881
2882cleanup:
2883	dns_loadctx_detach(&lctx);
2884	return (result);
2885}
2886
2887isc_result_t
2888dns_master_loadbufferinc(isc_buffer_t *buffer, dns_name_t *top,
2889			 dns_name_t *origin, dns_rdataclass_t zclass,
2890			 unsigned int options, dns_rdatacallbacks_t *callbacks,
2891			 isc_task_t *task, dns_loaddonefunc_t done,
2892			 void *done_arg, dns_loadctx_t **lctxp,
2893			 isc_mem_t *mctx) {
2894	isc_result_t result;
2895	dns_loadctx_t *lctx = NULL;
2896
2897	REQUIRE(buffer != NULL);
2898	REQUIRE(task != NULL);
2899	REQUIRE(done != NULL);
2900
2901	result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2902				zclass, origin, callbacks, task, done, done_arg,
2903				NULL, NULL, NULL, &lctx);
2904	if (result != ISC_R_SUCCESS) {
2905		return (result);
2906	}
2907
2908	result = isc_lex_openbuffer(lctx->lex, buffer);
2909	if (result != ISC_R_SUCCESS) {
2910		goto cleanup;
2911	}
2912
2913	result = task_send(lctx);
2914	if (result == ISC_R_SUCCESS) {
2915		dns_loadctx_attach(lctx, lctxp);
2916		return (DNS_R_CONTINUE);
2917	}
2918
2919cleanup:
2920	dns_loadctx_detach(&lctx);
2921	return (result);
2922}
2923
2924isc_result_t
2925dns_master_loadlexer(isc_lex_t *lex, dns_name_t *top, dns_name_t *origin,
2926		     dns_rdataclass_t zclass, unsigned int options,
2927		     dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx) {
2928	isc_result_t result;
2929	dns_loadctx_t *lctx = NULL;
2930
2931	REQUIRE(lex != NULL);
2932
2933	result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2934				zclass, origin, callbacks, NULL, NULL, NULL,
2935				NULL, NULL, lex, &lctx);
2936	if (result != ISC_R_SUCCESS) {
2937		return (result);
2938	}
2939
2940	result = (lctx->load)(lctx);
2941	INSIST(result != DNS_R_CONTINUE);
2942
2943	dns_loadctx_detach(&lctx);
2944	return (result);
2945}
2946
2947isc_result_t
2948dns_master_loadlexerinc(isc_lex_t *lex, dns_name_t *top, dns_name_t *origin,
2949			dns_rdataclass_t zclass, unsigned int options,
2950			dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2951			dns_loaddonefunc_t done, void *done_arg,
2952			dns_loadctx_t **lctxp, isc_mem_t *mctx) {
2953	isc_result_t result;
2954	dns_loadctx_t *lctx = NULL;
2955
2956	REQUIRE(lex != NULL);
2957	REQUIRE(task != NULL);
2958	REQUIRE(done != NULL);
2959
2960	result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2961				zclass, origin, callbacks, task, done, done_arg,
2962				NULL, NULL, lex, &lctx);
2963	if (result != ISC_R_SUCCESS) {
2964		return (result);
2965	}
2966
2967	result = task_send(lctx);
2968	if (result == ISC_R_SUCCESS) {
2969		dns_loadctx_attach(lctx, lctxp);
2970		return (DNS_R_CONTINUE);
2971	}
2972
2973	dns_loadctx_detach(&lctx);
2974	return (result);
2975}
2976
2977/*
2978 * Grow the slab of dns_rdatalist_t structures.
2979 * Re-link glue and current list.
2980 */
2981static dns_rdatalist_t *
2982grow_rdatalist(int new_len, dns_rdatalist_t *oldlist, int old_len,
2983	       rdatalist_head_t *current, rdatalist_head_t *glue,
2984	       isc_mem_t *mctx) {
2985	dns_rdatalist_t *newlist;
2986	int rdlcount = 0;
2987	ISC_LIST(dns_rdatalist_t) save;
2988	dns_rdatalist_t *this;
2989
2990	newlist = isc_mem_get(mctx, new_len * sizeof(*newlist));
2991	if (newlist == NULL) {
2992		return (NULL);
2993	}
2994
2995	ISC_LIST_INIT(save);
2996	while ((this = ISC_LIST_HEAD(*current)) != NULL) {
2997		ISC_LIST_UNLINK(*current, this, link);
2998		ISC_LIST_APPEND(save, this, link);
2999	}
3000	while ((this = ISC_LIST_HEAD(save)) != NULL) {
3001		ISC_LIST_UNLINK(save, this, link);
3002		INSIST(rdlcount < new_len);
3003		newlist[rdlcount] = *this;
3004		ISC_LIST_APPEND(*current, &newlist[rdlcount], link);
3005		rdlcount++;
3006	}
3007
3008	ISC_LIST_INIT(save);
3009	while ((this = ISC_LIST_HEAD(*glue)) != NULL) {
3010		ISC_LIST_UNLINK(*glue, this, link);
3011		ISC_LIST_APPEND(save, this, link);
3012	}
3013	while ((this = ISC_LIST_HEAD(save)) != NULL) {
3014		ISC_LIST_UNLINK(save, this, link);
3015		INSIST(rdlcount < new_len);
3016		newlist[rdlcount] = *this;
3017		ISC_LIST_APPEND(*glue, &newlist[rdlcount], link);
3018		rdlcount++;
3019	}
3020
3021	INSIST(rdlcount == old_len);
3022	if (oldlist != NULL) {
3023		isc_mem_put(mctx, oldlist, old_len * sizeof(*oldlist));
3024	}
3025	return (newlist);
3026}
3027
3028/*
3029 * Grow the slab of rdata structs.
3030 * Re-link the current and glue chains.
3031 */
3032static dns_rdata_t *
3033grow_rdata(int new_len, dns_rdata_t *oldlist, int old_len,
3034	   rdatalist_head_t *current, rdatalist_head_t *glue, isc_mem_t *mctx) {
3035	dns_rdata_t *newlist;
3036	int rdcount = 0;
3037	ISC_LIST(dns_rdata_t) save;
3038	dns_rdatalist_t *this;
3039	dns_rdata_t *rdata;
3040
3041	newlist = isc_mem_get(mctx, new_len * sizeof(*newlist));
3042	if (newlist == NULL) {
3043		return (NULL);
3044	}
3045	memset(newlist, 0, new_len * sizeof(*newlist));
3046
3047	/*
3048	 * Copy current relinking.
3049	 */
3050	this = ISC_LIST_HEAD(*current);
3051	while (this != NULL) {
3052		ISC_LIST_INIT(save);
3053		while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
3054			ISC_LIST_UNLINK(this->rdata, rdata, link);
3055			ISC_LIST_APPEND(save, rdata, link);
3056		}
3057		while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
3058			ISC_LIST_UNLINK(save, rdata, link);
3059			INSIST(rdcount < new_len);
3060			newlist[rdcount] = *rdata;
3061			ISC_LIST_APPEND(this->rdata, &newlist[rdcount], link);
3062			rdcount++;
3063		}
3064		this = ISC_LIST_NEXT(this, link);
3065	}
3066
3067	/*
3068	 * Copy glue relinking.
3069	 */
3070	this = ISC_LIST_HEAD(*glue);
3071	while (this != NULL) {
3072		ISC_LIST_INIT(save);
3073		while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
3074			ISC_LIST_UNLINK(this->rdata, rdata, link);
3075			ISC_LIST_APPEND(save, rdata, link);
3076		}
3077		while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
3078			ISC_LIST_UNLINK(save, rdata, link);
3079			INSIST(rdcount < new_len);
3080			newlist[rdcount] = *rdata;
3081			ISC_LIST_APPEND(this->rdata, &newlist[rdcount], link);
3082			rdcount++;
3083		}
3084		this = ISC_LIST_NEXT(this, link);
3085	}
3086	INSIST(rdcount == old_len || rdcount == 0);
3087	if (oldlist != NULL) {
3088		isc_mem_put(mctx, oldlist, old_len * sizeof(*oldlist));
3089	}
3090	return (newlist);
3091}
3092
3093static uint32_t
3094resign_fromlist(dns_rdatalist_t *this, dns_loadctx_t *lctx) {
3095	dns_rdata_t *rdata;
3096	dns_rdata_rrsig_t sig;
3097	uint32_t when;
3098
3099	rdata = ISC_LIST_HEAD(this->rdata);
3100	INSIST(rdata != NULL);
3101	(void)dns_rdata_tostruct(rdata, &sig, NULL);
3102	if (isc_serial_gt(sig.timesigned, lctx->now)) {
3103		when = lctx->now;
3104	} else {
3105		when = sig.timeexpire - lctx->resign;
3106	}
3107
3108	rdata = ISC_LIST_NEXT(rdata, link);
3109	while (rdata != NULL) {
3110		(void)dns_rdata_tostruct(rdata, &sig, NULL);
3111		if (isc_serial_gt(sig.timesigned, lctx->now)) {
3112			when = lctx->now;
3113		} else if (sig.timeexpire - lctx->resign < when) {
3114			when = sig.timeexpire - lctx->resign;
3115		}
3116		rdata = ISC_LIST_NEXT(rdata, link);
3117	}
3118	return (when);
3119}
3120
3121/*
3122 * Convert each element from a rdatalist_t to rdataset then call commit.
3123 * Unlink each element as we go.
3124 */
3125
3126static isc_result_t
3127commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
3128       rdatalist_head_t *head, dns_name_t *owner, const char *source,
3129       unsigned int line) {
3130	dns_rdatalist_t *this;
3131	dns_rdataset_t dataset;
3132	isc_result_t result;
3133	char namebuf[DNS_NAME_FORMATSIZE];
3134	void (*error)(struct dns_rdatacallbacks *, const char *, ...);
3135
3136	this = ISC_LIST_HEAD(*head);
3137	error = callbacks->error;
3138
3139	if (this == NULL) {
3140		return (ISC_R_SUCCESS);
3141	}
3142	do {
3143		dns_rdataset_init(&dataset);
3144		RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset) ==
3145			      ISC_R_SUCCESS);
3146		dataset.trust = dns_trust_ultimate;
3147		/*
3148		 * If this is a secure dynamic zone set the re-signing time.
3149		 */
3150		if (dataset.type == dns_rdatatype_rrsig &&
3151		    (lctx->options & DNS_MASTER_RESIGN) != 0)
3152		{
3153			dataset.attributes |= DNS_RDATASETATTR_RESIGN;
3154			dataset.resign = resign_fromlist(this, lctx);
3155		}
3156		result = ((*callbacks->add)(callbacks->add_private, owner,
3157					    &dataset));
3158		if (result == ISC_R_NOMEMORY) {
3159			(*error)(callbacks, "dns_master_load: %s",
3160				 dns_result_totext(result));
3161		} else if (result != ISC_R_SUCCESS) {
3162			dns_name_format(owner, namebuf, sizeof(namebuf));
3163			if (source != NULL) {
3164				(*error)(callbacks, "%s: %s:%lu: %s: %s",
3165					 "dns_master_load", source, line,
3166					 namebuf, dns_result_totext(result));
3167			} else {
3168				(*error)(callbacks, "%s: %s: %s",
3169					 "dns_master_load", namebuf,
3170					 dns_result_totext(result));
3171			}
3172		}
3173		if (MANYERRS(lctx, result)) {
3174			SETRESULT(lctx, result);
3175		} else if (result != ISC_R_SUCCESS) {
3176			return (result);
3177		}
3178		ISC_LIST_UNLINK(*head, this, link);
3179		this = ISC_LIST_HEAD(*head);
3180	} while (this != NULL);
3181	return (ISC_R_SUCCESS);
3182}
3183
3184/*
3185 * Returns true if one of the NS rdata's contains 'owner'.
3186 */
3187
3188static bool
3189is_glue(rdatalist_head_t *head, dns_name_t *owner) {
3190	dns_rdatalist_t *this;
3191	dns_rdata_t *rdata;
3192	isc_region_t region;
3193	dns_name_t name;
3194
3195	/*
3196	 * Find NS rrset.
3197	 */
3198	this = ISC_LIST_HEAD(*head);
3199	while (this != NULL) {
3200		if (this->type == dns_rdatatype_ns) {
3201			break;
3202		}
3203		this = ISC_LIST_NEXT(this, link);
3204	}
3205	if (this == NULL) {
3206		return (false);
3207	}
3208
3209	rdata = ISC_LIST_HEAD(this->rdata);
3210	while (rdata != NULL) {
3211		dns_name_init(&name, NULL);
3212		dns_rdata_toregion(rdata, &region);
3213		dns_name_fromregion(&name, &region);
3214		if (dns_name_equal(&name, owner)) {
3215			return (true);
3216		}
3217		rdata = ISC_LIST_NEXT(rdata, link);
3218	}
3219	return (false);
3220}
3221
3222static void
3223load_quantum(isc_task_t *task, isc_event_t *event) {
3224	isc_result_t result;
3225	dns_loadctx_t *lctx;
3226
3227	REQUIRE(event != NULL);
3228	lctx = event->ev_arg;
3229	REQUIRE(DNS_LCTX_VALID(lctx));
3230
3231	if (atomic_load_acquire(&lctx->canceled)) {
3232		result = ISC_R_CANCELED;
3233	} else {
3234		result = (lctx->load)(lctx);
3235	}
3236	if (result == DNS_R_CONTINUE) {
3237		event->ev_arg = lctx;
3238		isc_task_send(task, &event);
3239	} else {
3240		(lctx->done)(lctx->done_arg, result);
3241		isc_event_free(&event);
3242		dns_loadctx_detach(&lctx);
3243	}
3244}
3245
3246static isc_result_t
3247task_send(dns_loadctx_t *lctx) {
3248	isc_event_t *event;
3249
3250	event = isc_event_allocate(lctx->mctx, NULL, DNS_EVENT_MASTERQUANTUM,
3251				   load_quantum, lctx, sizeof(*event));
3252	isc_task_send(lctx->task, &event);
3253	return (ISC_R_SUCCESS);
3254}
3255
3256void
3257dns_loadctx_cancel(dns_loadctx_t *lctx) {
3258	REQUIRE(DNS_LCTX_VALID(lctx));
3259
3260	atomic_store_release(&lctx->canceled, true);
3261}
3262
3263void
3264dns_master_initrawheader(dns_masterrawheader_t *header) {
3265	memset(header, 0, sizeof(dns_masterrawheader_t));
3266}
3267