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