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