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