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