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