PageRenderTime 148ms CodeModel.GetById 29ms app.highlight 104ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/bind9/lib/dns/master.c

https://bitbucket.org/freebsd/freebsd-head/
C | 2941 lines | 2804 code | 79 blank | 58 comment | 107 complexity | 27f06f2d7c402d2e65f77ae8419f13c0 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * Copyright (C) 2004-2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
   3 * Copyright (C) 1999-2003  Internet Software Consortium.
   4 *
   5 * Permission to use, copy, modify, and/or distribute this software for any
   6 * purpose with or without fee is hereby granted, provided that the above
   7 * copyright notice and this permission notice appear in all copies.
   8 *
   9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15 * PERFORMANCE OF THIS SOFTWARE.
  16 */
  17
  18/* $Id$ */
  19
  20/*! \file */
  21
  22#include <config.h>
  23
  24#include <isc/event.h>
  25#include <isc/lex.h>
  26#include <isc/magic.h>
  27#include <isc/mem.h>
  28#include <isc/print.h>
  29#include <isc/serial.h>
  30#include <isc/stdio.h>
  31#include <isc/stdtime.h>
  32#include <isc/string.h>
  33#include <isc/task.h>
  34#include <isc/util.h>
  35
  36#include <dns/callbacks.h>
  37#include <dns/events.h>
  38#include <dns/fixedname.h>
  39#include <dns/master.h>
  40#include <dns/name.h>
  41#include <dns/rdata.h>
  42#include <dns/rdataclass.h>
  43#include <dns/rdatalist.h>
  44#include <dns/rdataset.h>
  45#include <dns/rdatastruct.h>
  46#include <dns/rdatatype.h>
  47#include <dns/result.h>
  48#include <dns/soa.h>
  49#include <dns/time.h>
  50#include <dns/ttl.h>
  51
  52/*!
  53 * Grow the number of dns_rdatalist_t (#RDLSZ) and dns_rdata_t (#RDSZ) structures
  54 * by these sizes when we need to.
  55 *
  56 */
  57/*% RDLSZ reflects the number of different types with the same name expected. */
  58#define RDLSZ 32
  59/*%
  60 * RDSZ reflects the number of rdata expected at a give name that can fit into
  61 * 64k.
  62 */
  63#define RDSZ 512
  64
  65#define NBUFS 4
  66#define MAXWIRESZ 255
  67
  68/*%
  69 * Target buffer size and minimum target size.
  70 * MINTSIZ must be big enough to hold the largest rdata record.
  71 * \brief
  72 * TSIZ >= MINTSIZ
  73 */
  74#define TSIZ (128*1024)
  75/*%
  76 * max message size - header - root - type - class - ttl - rdlen
  77 */
  78#define MINTSIZ DNS_RDATA_MAXLENGTH
  79/*%
  80 * Size for tokens in the presentation format,
  81 * The largest tokens are the base64 blocks in KEY and CERT records,
  82 * Largest key allowed is about 1372 bytes but
  83 * there is no fixed upper bound on CERT records.
  84 * 2K is too small for some X.509s, 8K is overkill.
  85 */
  86#define TOKENSIZ (8*1024)
  87
  88/*%
  89 * Buffers sizes for $GENERATE.
  90 */
  91#define DNS_MASTER_LHS 2048
  92#define DNS_MASTER_RHS MINTSIZ
  93
  94typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
  95
  96typedef struct dns_incctx dns_incctx_t;
  97
  98/*%
  99 * Master file load state.
 100 */
 101
 102struct dns_loadctx {
 103	unsigned int		magic;
 104	isc_mem_t		*mctx;
 105	dns_masterformat_t	format;
 106
 107	dns_rdatacallbacks_t	*callbacks;
 108	isc_task_t		*task;
 109	dns_loaddonefunc_t	done;
 110	void			*done_arg;
 111
 112	/* Common methods */
 113	isc_result_t		(*openfile)(dns_loadctx_t *lctx,
 114					    const char *filename);
 115	isc_result_t		(*load)(dns_loadctx_t *lctx);
 116
 117	/* Members specific to the text format: */
 118	isc_lex_t		*lex;
 119	isc_boolean_t		keep_lex;
 120	unsigned int		options;
 121	isc_boolean_t		ttl_known;
 122	isc_boolean_t		default_ttl_known;
 123	isc_boolean_t		warn_1035;
 124	isc_boolean_t		warn_tcr;
 125	isc_boolean_t		warn_sigexpired;
 126	isc_boolean_t		seen_include;
 127	isc_uint32_t		ttl;
 128	isc_uint32_t		default_ttl;
 129	dns_rdataclass_t	zclass;
 130	dns_fixedname_t		fixed_top;
 131	dns_name_t		*top;			/*%< top of zone */
 132
 133	/* Members specific to the raw format: */
 134	FILE			*f;
 135	isc_boolean_t		first;
 136
 137	/* Which fixed buffers we are using? */
 138	unsigned int		loop_cnt;		/*% records per quantum,
 139							 * 0 => all. */
 140	isc_boolean_t		canceled;
 141	isc_mutex_t		lock;
 142	isc_result_t		result;
 143	/* locked by lock */
 144	isc_uint32_t		references;
 145	dns_incctx_t		*inc;
 146	isc_uint32_t		resign;
 147};
 148
 149struct dns_incctx {
 150	dns_incctx_t		*parent;
 151	dns_name_t		*origin;
 152	dns_name_t		*current;
 153	dns_name_t		*glue;
 154	dns_fixedname_t		fixed[NBUFS];		/* working buffers */
 155	unsigned int		in_use[NBUFS];		/* covert to bitmap? */
 156	int			glue_in_use;
 157	int			current_in_use;
 158	int			origin_in_use;
 159	isc_boolean_t		drop;
 160	unsigned int		glue_line;
 161	unsigned int		current_line;
 162};
 163
 164#define DNS_LCTX_MAGIC ISC_MAGIC('L','c','t','x')
 165#define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
 166
 167#define DNS_AS_STR(t) ((t).value.as_textregion.base)
 168
 169static isc_result_t
 170openfile_text(dns_loadctx_t *lctx, const char *master_file);
 171
 172static isc_result_t
 173openfile_raw(dns_loadctx_t *lctx, const char *master_file);
 174
 175static isc_result_t
 176load_text(dns_loadctx_t *lctx);
 177
 178static isc_result_t
 179load_raw(dns_loadctx_t *lctx);
 180
 181static isc_result_t
 182pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx);
 183
 184static isc_result_t
 185commit(dns_rdatacallbacks_t *, dns_loadctx_t *, rdatalist_head_t *,
 186       dns_name_t *, const char *, unsigned int);
 187
 188static isc_boolean_t
 189is_glue(rdatalist_head_t *, dns_name_t *);
 190
 191static dns_rdatalist_t *
 192grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *,
 193		rdatalist_head_t *, isc_mem_t *mctx);
 194
 195static dns_rdata_t *
 196grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *,
 197	   isc_mem_t *);
 198
 199static void
 200load_quantum(isc_task_t *task, isc_event_t *event);
 201
 202static isc_result_t
 203task_send(dns_loadctx_t *lctx);
 204
 205static void
 206loadctx_destroy(dns_loadctx_t *lctx);
 207
 208#define GETTOKEN(lexer, options, token, eol) \
 209	do { \
 210		result = gettoken(lexer, options, token, eol, callbacks); \
 211		switch (result) { \
 212		case ISC_R_SUCCESS: \
 213			break; \
 214		case ISC_R_UNEXPECTED: \
 215			goto insist_and_cleanup; \
 216		default: \
 217			if (MANYERRS(lctx, result)) { \
 218				SETRESULT(lctx, result); \
 219				LOGIT(result); \
 220				read_till_eol = ISC_TRUE; \
 221				goto next_line; \
 222			} else \
 223				goto log_and_cleanup; \
 224		} \
 225		if ((token)->type == isc_tokentype_special) { \
 226			result = DNS_R_SYNTAX; \
 227			if (MANYERRS(lctx, result)) { \
 228				SETRESULT(lctx, result); \
 229				LOGIT(result); \
 230				read_till_eol = ISC_TRUE; \
 231				goto next_line; \
 232			} else \
 233				goto log_and_cleanup; \
 234		} \
 235	} while (0)
 236
 237#define COMMITALL \
 238	do { \
 239		result = commit(callbacks, lctx, &current_list, \
 240				ictx->current, source, ictx->current_line); \
 241		if (MANYERRS(lctx, result)) { \
 242			SETRESULT(lctx, result); \
 243		} else if (result != ISC_R_SUCCESS) \
 244			goto insist_and_cleanup; \
 245		result = commit(callbacks, lctx, &glue_list, \
 246				ictx->glue, source, ictx->glue_line); \
 247		if (MANYERRS(lctx, result)) { \
 248			SETRESULT(lctx, result); \
 249		} else if (result != ISC_R_SUCCESS) \
 250			goto insist_and_cleanup; \
 251		rdcount = 0; \
 252		rdlcount = 0; \
 253		isc_buffer_init(&target, target_mem, target_size); \
 254		rdcount_save = rdcount; \
 255		rdlcount_save = rdlcount; \
 256	} while (0)
 257
 258#define WARNUNEXPECTEDEOF(lexer) \
 259	do { \
 260		if (isc_lex_isfile(lexer)) \
 261			(*callbacks->warn)(callbacks, \
 262				"%s: file does not end with newline", \
 263				source); \
 264	} while (0)
 265
 266#define EXPECTEOL \
 267	do { \
 268		GETTOKEN(lctx->lex, 0, &token, ISC_TRUE); \
 269		if (token.type != isc_tokentype_eol) { \
 270			isc_lex_ungettoken(lctx->lex, &token); \
 271			result = DNS_R_EXTRATOKEN; \
 272			if (MANYERRS(lctx, result)) { \
 273				SETRESULT(lctx, result); \
 274				LOGIT(result); \
 275				read_till_eol = ISC_TRUE; \
 276				continue; \
 277			} else if (result != ISC_R_SUCCESS) \
 278				goto log_and_cleanup; \
 279		} \
 280	} while (0)
 281
 282#define MANYERRS(lctx, result) \
 283		((result != ISC_R_SUCCESS) && \
 284		 (result != ISC_R_IOERROR) && \
 285		 ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
 286
 287#define SETRESULT(lctx, r) \
 288		do { \
 289			if ((lctx)->result == ISC_R_SUCCESS) \
 290				(lctx)->result = r; \
 291		} while (0)
 292
 293#define LOGITFILE(result, filename) \
 294	if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \
 295	    result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \
 296	    result == ISC_R_NOPERM) \
 297		(*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \
 298				    "dns_master_load", source, line, \
 299				    filename, dns_result_totext(result)); \
 300	else LOGIT(result)
 301
 302#define LOGIT(result) \
 303	if (result == ISC_R_NOMEMORY) \
 304		(*callbacks->error)(callbacks, "dns_master_load: %s", \
 305				    dns_result_totext(result)); \
 306	else \
 307		(*callbacks->error)(callbacks, "%s: %s:%lu: %s", \
 308				    "dns_master_load", \
 309				    source, line, dns_result_totext(result))
 310
 311
 312static unsigned char in_addr_arpa_data[]  = "\007IN-ADDR\004ARPA";
 313static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 };
 314static const dns_name_t in_addr_arpa =
 315{
 316	DNS_NAME_MAGIC,
 317	in_addr_arpa_data, 14, 3,
 318	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
 319	in_addr_arpa_offsets, NULL,
 320	{(void *)-1, (void *)-1},
 321	{NULL, NULL}
 322};
 323
 324static unsigned char ip6_int_data[]  = "\003IP6\003INT";
 325static unsigned char ip6_int_offsets[] = { 0, 4, 8 };
 326static const dns_name_t ip6_int =
 327{
 328	DNS_NAME_MAGIC,
 329	ip6_int_data, 9, 3,
 330	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
 331	ip6_int_offsets, NULL,
 332	{(void *)-1, (void *)-1},
 333	{NULL, NULL}
 334};
 335
 336static unsigned char ip6_arpa_data[]  = "\003IP6\004ARPA";
 337static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
 338static const dns_name_t ip6_arpa =
 339{
 340	DNS_NAME_MAGIC,
 341	ip6_arpa_data, 10, 3,
 342	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
 343	ip6_arpa_offsets, NULL,
 344	{(void *)-1, (void *)-1},
 345	{NULL, NULL}
 346};
 347
 348
 349static inline isc_result_t
 350gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token,
 351	 isc_boolean_t eol, dns_rdatacallbacks_t *callbacks)
 352{
 353	isc_result_t result;
 354
 355	options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE |
 356		ISC_LEXOPT_ESCAPE;
 357	result = isc_lex_gettoken(lex, options, token);
 358	if (result != ISC_R_SUCCESS) {
 359		switch (result) {
 360		case ISC_R_NOMEMORY:
 361			return (ISC_R_NOMEMORY);
 362		default:
 363			(*callbacks->error)(callbacks,
 364					    "dns_master_load: %s:%lu:"
 365					    " isc_lex_gettoken() failed: %s",
 366					    isc_lex_getsourcename(lex),
 367					    isc_lex_getsourceline(lex),
 368					    isc_result_totext(result));
 369			return (result);
 370		}
 371		/*NOTREACHED*/
 372	}
 373	if (eol != ISC_TRUE)
 374		if (token->type == isc_tokentype_eol ||
 375		    token->type == isc_tokentype_eof) {
 376			(*callbacks->error)(callbacks,
 377			    "dns_master_load: %s:%lu: unexpected end of %s",
 378					    isc_lex_getsourcename(lex),
 379					    isc_lex_getsourceline(lex),
 380					    (token->type ==
 381					     isc_tokentype_eol) ?
 382					    "line" : "file");
 383			return (ISC_R_UNEXPECTEDEND);
 384		}
 385	return (ISC_R_SUCCESS);
 386}
 387
 388
 389void
 390dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
 391
 392	REQUIRE(target != NULL && *target == NULL);
 393	REQUIRE(DNS_LCTX_VALID(source));
 394
 395	LOCK(&source->lock);
 396	INSIST(source->references > 0);
 397	source->references++;
 398	INSIST(source->references != 0);	/* Overflow? */
 399	UNLOCK(&source->lock);
 400
 401	*target = source;
 402}
 403
 404void
 405dns_loadctx_detach(dns_loadctx_t **lctxp) {
 406	dns_loadctx_t *lctx;
 407	isc_boolean_t need_destroy = ISC_FALSE;
 408
 409	REQUIRE(lctxp != NULL);
 410	lctx = *lctxp;
 411	REQUIRE(DNS_LCTX_VALID(lctx));
 412
 413	LOCK(&lctx->lock);
 414	INSIST(lctx->references > 0);
 415	lctx->references--;
 416	if (lctx->references == 0)
 417		need_destroy = ISC_TRUE;
 418	UNLOCK(&lctx->lock);
 419
 420	if (need_destroy)
 421		loadctx_destroy(lctx);
 422	*lctxp = NULL;
 423}
 424
 425static void
 426incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
 427	dns_incctx_t *parent;
 428
 429 again:
 430	parent = ictx->parent;
 431	ictx->parent = NULL;
 432
 433	isc_mem_put(mctx, ictx, sizeof(*ictx));
 434
 435	if (parent != NULL) {
 436		ictx = parent;
 437		goto again;
 438	}
 439}
 440
 441static void
 442loadctx_destroy(dns_loadctx_t *lctx) {
 443	isc_mem_t *mctx;
 444	isc_result_t result;
 445
 446	REQUIRE(DNS_LCTX_VALID(lctx));
 447
 448	lctx->magic = 0;
 449	if (lctx->inc != NULL)
 450		incctx_destroy(lctx->mctx, lctx->inc);
 451
 452	if (lctx->f != NULL) {
 453		result = isc_stdio_close(lctx->f);
 454		if (result != ISC_R_SUCCESS) {
 455			UNEXPECTED_ERROR(__FILE__, __LINE__,
 456					 "isc_stdio_close() failed: %s",
 457					 isc_result_totext(result));
 458		}
 459	}
 460
 461	/* isc_lex_destroy() will close all open streams */
 462	if (lctx->lex != NULL && !lctx->keep_lex)
 463		isc_lex_destroy(&lctx->lex);
 464
 465	if (lctx->task != NULL)
 466		isc_task_detach(&lctx->task);
 467	DESTROYLOCK(&lctx->lock);
 468	mctx = NULL;
 469	isc_mem_attach(lctx->mctx, &mctx);
 470	isc_mem_detach(&lctx->mctx);
 471	isc_mem_put(mctx, lctx, sizeof(*lctx));
 472	isc_mem_detach(&mctx);
 473}
 474
 475static isc_result_t
 476incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
 477	dns_incctx_t *ictx;
 478	isc_region_t r;
 479	int i;
 480
 481	ictx = isc_mem_get(mctx, sizeof(*ictx));
 482	if (ictx == NULL)
 483		return (ISC_R_NOMEMORY);
 484
 485	for (i = 0; i < NBUFS; i++) {
 486		dns_fixedname_init(&ictx->fixed[i]);
 487		ictx->in_use[i] = ISC_FALSE;
 488	}
 489
 490	ictx->origin_in_use = 0;
 491	ictx->origin = dns_fixedname_name(&ictx->fixed[ictx->origin_in_use]);
 492	ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
 493	dns_name_toregion(origin, &r);
 494	dns_name_fromregion(ictx->origin, &r);
 495
 496	ictx->glue = NULL;
 497	ictx->current = NULL;
 498	ictx->glue_in_use = -1;
 499	ictx->current_in_use = -1;
 500	ictx->parent = NULL;
 501	ictx->drop = ISC_FALSE;
 502	ictx->glue_line = 0;
 503	ictx->current_line = 0;
 504
 505	*ictxp = ictx;
 506	return (ISC_R_SUCCESS);
 507}
 508
 509static isc_result_t
 510loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
 511	       unsigned int options, isc_uint32_t resign, dns_name_t *top,
 512	       dns_rdataclass_t zclass, dns_name_t *origin,
 513	       dns_rdatacallbacks_t *callbacks, isc_task_t *task,
 514	       dns_loaddonefunc_t done, void *done_arg, isc_lex_t *lex,
 515	       dns_loadctx_t **lctxp)
 516{
 517	dns_loadctx_t *lctx;
 518	isc_result_t result;
 519	isc_region_t r;
 520	isc_lexspecials_t specials;
 521
 522	REQUIRE(lctxp != NULL && *lctxp == NULL);
 523	REQUIRE(callbacks != NULL);
 524	REQUIRE(callbacks->add != NULL);
 525	REQUIRE(callbacks->error != NULL);
 526	REQUIRE(callbacks->warn != NULL);
 527	REQUIRE(mctx != NULL);
 528	REQUIRE(dns_name_isabsolute(top));
 529	REQUIRE(dns_name_isabsolute(origin));
 530	REQUIRE((task == NULL && done == NULL) ||
 531		(task != NULL && done != NULL));
 532
 533	lctx = isc_mem_get(mctx, sizeof(*lctx));
 534	if (lctx == NULL)
 535		return (ISC_R_NOMEMORY);
 536	result = isc_mutex_init(&lctx->lock);
 537	if (result != ISC_R_SUCCESS) {
 538		isc_mem_put(mctx, lctx, sizeof(*lctx));
 539		return (result);
 540	}
 541
 542	lctx->inc = NULL;
 543	result = incctx_create(mctx, origin, &lctx->inc);
 544	if (result != ISC_R_SUCCESS)
 545		goto cleanup_ctx;
 546
 547	lctx->format = format;
 548	switch (format) {
 549	default:
 550		INSIST(0);
 551	case dns_masterformat_text:
 552		lctx->openfile = openfile_text;
 553		lctx->load = load_text;
 554		break;
 555	case dns_masterformat_raw:
 556		lctx->openfile = openfile_raw;
 557		lctx->load = load_raw;
 558		break;
 559	}
 560
 561	if (lex != NULL) {
 562		lctx->lex = lex;
 563		lctx->keep_lex = ISC_TRUE;
 564	} else {
 565		lctx->lex = NULL;
 566		result = isc_lex_create(mctx, TOKENSIZ, &lctx->lex);
 567		if (result != ISC_R_SUCCESS)
 568			goto cleanup_inc;
 569		lctx->keep_lex = ISC_FALSE;
 570		memset(specials, 0, sizeof(specials));
 571		specials['('] = 1;
 572		specials[')'] = 1;
 573		specials['"'] = 1;
 574		isc_lex_setspecials(lctx->lex, specials);
 575		isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE);
 576	}
 577
 578	lctx->ttl_known = ISC_FALSE;
 579	lctx->ttl = 0;
 580	lctx->default_ttl_known = ISC_FALSE;
 581	lctx->default_ttl = 0;
 582	lctx->warn_1035 = ISC_TRUE;	/* XXX Argument? */
 583	lctx->warn_tcr = ISC_TRUE;	/* XXX Argument? */
 584	lctx->warn_sigexpired = ISC_TRUE;	/* XXX Argument? */
 585	lctx->options = options;
 586	lctx->seen_include = ISC_FALSE;
 587	lctx->zclass = zclass;
 588	lctx->resign = resign;
 589	lctx->result = ISC_R_SUCCESS;
 590
 591	dns_fixedname_init(&lctx->fixed_top);
 592	lctx->top = dns_fixedname_name(&lctx->fixed_top);
 593	dns_name_toregion(top, &r);
 594	dns_name_fromregion(lctx->top, &r);
 595
 596	lctx->f = NULL;
 597	lctx->first = ISC_TRUE;
 598
 599	lctx->loop_cnt = (done != NULL) ? 100 : 0;
 600	lctx->callbacks = callbacks;
 601	lctx->task = NULL;
 602	if (task != NULL)
 603		isc_task_attach(task, &lctx->task);
 604	lctx->done = done;
 605	lctx->done_arg = done_arg;
 606	lctx->canceled = ISC_FALSE;
 607	lctx->mctx = NULL;
 608	isc_mem_attach(mctx, &lctx->mctx);
 609	lctx->references = 1;			/* Implicit attach. */
 610	lctx->magic = DNS_LCTX_MAGIC;
 611	*lctxp = lctx;
 612	return (ISC_R_SUCCESS);
 613
 614 cleanup_inc:
 615	incctx_destroy(mctx, lctx->inc);
 616 cleanup_ctx:
 617	isc_mem_put(mctx, lctx, sizeof(*lctx));
 618	return (result);
 619}
 620
 621static const char *hex = "0123456789abcdef0123456789ABCDEF";
 622
 623/*%
 624 * Convert value into a nibble sequence from least significant to most
 625 * significant nibble.  Zero fill upper most significant nibbles if
 626 * required to make the width.
 627 *
 628 * Returns the number of characters that should have been written without
 629 * counting the terminating NUL.
 630 */
 631static unsigned int
 632nibbles(char *numbuf, size_t length, unsigned int width, char mode, int value) {
 633	unsigned int count = 0;
 634
 635	/*
 636	 * This reserve space for the NUL string terminator.
 637	 */
 638	if (length > 0U) {
 639		*numbuf = '\0';
 640		length--;
 641	}
 642	do {
 643		char val = hex[(value & 0x0f) + ((mode == 'n') ? 0 : 16)];
 644		value >>= 4;
 645		if (length > 0U) {
 646			*numbuf++ = val;
 647			*numbuf = '\0';
 648			length--;
 649		}
 650		if (width > 0)
 651			width--;
 652		count++;
 653		/*
 654		 * If width is non zero then we need to add a label seperator.
 655		 * If value is non zero then we need to add another label and
 656		 * that requires a label seperator.
 657		 */
 658		if (width > 0 || value != 0) {
 659			if (length > 0U) {
 660				*numbuf++ = '.';
 661				*numbuf = '\0';
 662				length--;
 663			}
 664			if (width > 0)
 665				width--;
 666			count++;
 667		}
 668	} while (value != 0 || width > 0);
 669	return (count);
 670}
 671
 672static isc_result_t
 673genname(char *name, int it, char *buffer, size_t length) {
 674	char fmt[sizeof("%04000000000d")];
 675	char numbuf[128];
 676	char *cp;
 677	char mode[2];
 678	int delta = 0;
 679	isc_textregion_t r;
 680	unsigned int n;
 681	unsigned int width;
 682	isc_boolean_t nibblemode;
 683
 684	r.base = buffer;
 685	r.length = length;
 686
 687	while (*name != '\0') {
 688		if (*name == '$') {
 689			name++;
 690			if (*name == '$') {
 691				if (r.length == 0)
 692					return (ISC_R_NOSPACE);
 693				r.base[0] = *name++;
 694				isc_textregion_consume(&r, 1);
 695				continue;
 696			}
 697			nibblemode = ISC_FALSE;
 698			strcpy(fmt, "%d");
 699			/* Get format specifier. */
 700			if (*name == '{' ) {
 701				n = sscanf(name, "{%d,%u,%1[doxXnN]}",
 702					   &delta, &width, mode);
 703				switch (n) {
 704				case 1:
 705					break;
 706				case 2:
 707					n = snprintf(fmt, sizeof(fmt),
 708						     "%%0%ud", width);
 709					break;
 710				case 3:
 711					if (mode[0] == 'n' || mode[0] == 'N')
 712						nibblemode = ISC_TRUE;
 713					n = snprintf(fmt, sizeof(fmt),
 714						     "%%0%u%c", width, mode[0]);
 715					break;
 716				default:
 717					return (DNS_R_SYNTAX);
 718				}
 719				if (n >= sizeof(fmt))
 720					return (ISC_R_NOSPACE);
 721				/* Skip past closing brace. */
 722				while (*name != '\0' && *name++ != '}')
 723					continue;
 724			}
 725			if (nibblemode)
 726				n = nibbles(numbuf, sizeof(numbuf), width,
 727					    mode[0], it + delta);
 728			else
 729				n = snprintf(numbuf, sizeof(numbuf), fmt,
 730					     it + delta);
 731			if (n >= sizeof(numbuf))
 732				return (ISC_R_NOSPACE);
 733			cp = numbuf;
 734			while (*cp != '\0') {
 735				if (r.length == 0)
 736					return (ISC_R_NOSPACE);
 737				r.base[0] = *cp++;
 738				isc_textregion_consume(&r, 1);
 739			}
 740		} else if (*name == '\\') {
 741			if (r.length == 0)
 742				return (ISC_R_NOSPACE);
 743			r.base[0] = *name++;
 744			isc_textregion_consume(&r, 1);
 745			if (*name == '\0')
 746				continue;
 747			if (r.length == 0)
 748				return (ISC_R_NOSPACE);
 749			r.base[0] = *name++;
 750			isc_textregion_consume(&r, 1);
 751		} else {
 752			if (r.length == 0)
 753				return (ISC_R_NOSPACE);
 754			r.base[0] = *name++;
 755			isc_textregion_consume(&r, 1);
 756		}
 757	}
 758	if (r.length == 0)
 759		return (ISC_R_NOSPACE);
 760	r.base[0] = '\0';
 761	return (ISC_R_SUCCESS);
 762}
 763
 764static isc_result_t
 765openfile_text(dns_loadctx_t *lctx, const char *master_file) {
 766	return (isc_lex_openfile(lctx->lex, master_file));
 767}
 768
 769static isc_result_t
 770openfile_raw(dns_loadctx_t *lctx, const char *master_file) {
 771	isc_result_t result;
 772
 773	result = isc_stdio_open(master_file, "r", &lctx->f);
 774	if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
 775		UNEXPECTED_ERROR(__FILE__, __LINE__,
 776				 "isc_stdio_open() failed: %s",
 777				 isc_result_totext(result));
 778	}
 779
 780	return (result);
 781}
 782
 783static isc_result_t
 784generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
 785	 const char *source, unsigned int line)
 786{
 787	char *target_mem = NULL;
 788	char *lhsbuf = NULL;
 789	char *rhsbuf = NULL;
 790	dns_fixedname_t ownerfixed;
 791	dns_name_t *owner;
 792	dns_rdata_t rdata = DNS_RDATA_INIT;
 793	dns_rdatacallbacks_t *callbacks;
 794	dns_rdatalist_t rdatalist;
 795	dns_rdatatype_t type;
 796	rdatalist_head_t head;
 797	int n;
 798	int target_size = MINTSIZ;	/* only one rdata at a time */
 799	isc_buffer_t buffer;
 800	isc_buffer_t target;
 801	isc_result_t result;
 802	isc_textregion_t r;
 803	unsigned int start, stop, step, i;
 804	dns_incctx_t *ictx;
 805
 806	ictx = lctx->inc;
 807	callbacks = lctx->callbacks;
 808	dns_fixedname_init(&ownerfixed);
 809	owner = dns_fixedname_name(&ownerfixed);
 810	ISC_LIST_INIT(head);
 811
 812	target_mem = isc_mem_get(lctx->mctx, target_size);
 813	rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_RHS);
 814	lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_LHS);
 815	if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) {
 816		result = ISC_R_NOMEMORY;
 817		goto error_cleanup;
 818	}
 819	isc_buffer_init(&target, target_mem, target_size);
 820
 821	n = sscanf(range, "%u-%u/%u", &start, &stop, &step);
 822	if (n < 2 || stop < start) {
 823	       (*callbacks->error)(callbacks,
 824				  "%s: %s:%lu: invalid range '%s'",
 825				  "$GENERATE", source, line, range);
 826		result = DNS_R_SYNTAX;
 827		goto insist_cleanup;
 828	}
 829	if (n == 2)
 830		step = 1;
 831
 832	/*
 833	 * Get type.
 834	 */
 835	r.base = gtype;
 836	r.length = strlen(gtype);
 837	result = dns_rdatatype_fromtext(&type, &r);
 838	if (result != ISC_R_SUCCESS) {
 839		(*callbacks->error)(callbacks,
 840				   "%s: %s:%lu: unknown RR type '%s'",
 841				   "$GENERATE", source, line, gtype);
 842		goto insist_cleanup;
 843	}
 844
 845	ISC_LIST_INIT(rdatalist.rdata);
 846	ISC_LINK_INIT(&rdatalist, link);
 847	for (i = start; i <= stop; i += step) {
 848		result = genname(lhs, i, lhsbuf, DNS_MASTER_LHS);
 849		if (result != ISC_R_SUCCESS)
 850			goto error_cleanup;
 851		result = genname(rhs, i, rhsbuf, DNS_MASTER_RHS);
 852		if (result != ISC_R_SUCCESS)
 853			goto error_cleanup;
 854
 855		isc_buffer_init(&buffer, lhsbuf, strlen(lhsbuf));
 856		isc_buffer_add(&buffer, strlen(lhsbuf));
 857		isc_buffer_setactive(&buffer, strlen(lhsbuf));
 858		result = dns_name_fromtext(owner, &buffer, ictx->origin,
 859					   0, NULL);
 860		if (result != ISC_R_SUCCESS)
 861			goto error_cleanup;
 862
 863		if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
 864		    (lctx->options & DNS_MASTER_SLAVE) == 0 &&
 865		    (lctx->options & DNS_MASTER_KEY) == 0 &&
 866		    !dns_name_issubdomain(owner, lctx->top))
 867		{
 868			char namebuf[DNS_NAME_FORMATSIZE];
 869			dns_name_format(owner, namebuf, sizeof(namebuf));
 870			/*
 871			 * Ignore out-of-zone data.
 872			 */
 873			(*callbacks->warn)(callbacks,
 874					   "%s:%lu: "
 875					   "ignoring out-of-zone data (%s)",
 876					   source, line, namebuf);
 877			continue;
 878		}
 879
 880		isc_buffer_init(&buffer, rhsbuf, strlen(rhsbuf));
 881		isc_buffer_add(&buffer, strlen(rhsbuf));
 882		isc_buffer_setactive(&buffer, strlen(rhsbuf));
 883
 884		result = isc_lex_openbuffer(lctx->lex, &buffer);
 885		if (result != ISC_R_SUCCESS)
 886			goto error_cleanup;
 887
 888		isc_buffer_init(&target, target_mem, target_size);
 889		result = dns_rdata_fromtext(&rdata, lctx->zclass, type,
 890					    lctx->lex, ictx->origin, 0,
 891					    lctx->mctx, &target, callbacks);
 892		RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
 893		if (result != ISC_R_SUCCESS)
 894			goto error_cleanup;
 895
 896		rdatalist.type = type;
 897		rdatalist.covers = 0;
 898		rdatalist.rdclass = lctx->zclass;
 899		rdatalist.ttl = lctx->ttl;
 900		ISC_LIST_PREPEND(head, &rdatalist, link);
 901		ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
 902		result = commit(callbacks, lctx, &head, owner, source, line);
 903		ISC_LIST_UNLINK(rdatalist.rdata, &rdata, link);
 904		if (result != ISC_R_SUCCESS)
 905			goto error_cleanup;
 906		dns_rdata_reset(&rdata);
 907	}
 908	result = ISC_R_SUCCESS;
 909	goto cleanup;
 910
 911 error_cleanup:
 912	if (result == ISC_R_NOMEMORY)
 913		(*callbacks->error)(callbacks, "$GENERATE: %s",
 914				    dns_result_totext(result));
 915	else
 916		(*callbacks->error)(callbacks, "$GENERATE: %s:%lu: %s",
 917				    source, line, dns_result_totext(result));
 918
 919 insist_cleanup:
 920	INSIST(result != ISC_R_SUCCESS);
 921
 922 cleanup:
 923	if (target_mem != NULL)
 924		isc_mem_put(lctx->mctx, target_mem, target_size);
 925	if (lhsbuf != NULL)
 926		isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_LHS);
 927	if (rhsbuf != NULL)
 928		isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_RHS);
 929	return (result);
 930}
 931
 932static void
 933limit_ttl(dns_rdatacallbacks_t *callbacks, const char *source, unsigned int line,
 934	  isc_uint32_t *ttlp)
 935{
 936	if (*ttlp > 0x7fffffffUL) {
 937		(callbacks->warn)(callbacks,
 938				  "%s: %s:%lu: "
 939				  "$TTL %lu > MAXTTL, "
 940				  "setting $TTL to 0",
 941				  "dns_master_load",
 942				  source, line,
 943				  *ttlp);
 944		*ttlp = 0;
 945	}
 946}
 947
 948static isc_result_t
 949check_ns(dns_loadctx_t *lctx, isc_token_t *token, const char *source,
 950	 unsigned long line)
 951{
 952	char *tmp = NULL;
 953	isc_result_t result = ISC_R_SUCCESS;
 954	void (*callback)(struct dns_rdatacallbacks *, const char *, ...);
 955
 956	if ((lctx->options & DNS_MASTER_FATALNS) != 0)
 957		callback = lctx->callbacks->error;
 958	else
 959		callback = lctx->callbacks->warn;
 960
 961	if (token->type == isc_tokentype_string) {
 962		struct in_addr addr;
 963		struct in6_addr addr6;
 964
 965		tmp = isc_mem_strdup(lctx->mctx, DNS_AS_STR(*token));
 966		if (tmp == NULL)
 967			return (ISC_R_NOMEMORY);
 968		/*
 969		 * Catch both "1.2.3.4" and "1.2.3.4."
 970		 */
 971		if (tmp[strlen(tmp) - 1] == '.')
 972			tmp[strlen(tmp) - 1] = '\0';
 973		if (inet_aton(tmp, &addr) == 1 ||
 974		    inet_pton(AF_INET6, tmp, &addr6) == 1)
 975			result = DNS_R_NSISADDRESS;
 976	}
 977	if (result != ISC_R_SUCCESS)
 978		(*callback)(lctx->callbacks, "%s:%lu: NS record '%s' "
 979			    "appears to be an address",
 980			    source, line, DNS_AS_STR(*token));
 981	if (tmp != NULL)
 982		isc_mem_free(lctx->mctx, tmp);
 983	return (result);
 984}
 985
 986static void
 987check_wildcard(dns_incctx_t *ictx, const char *source, unsigned long line,
 988	       dns_rdatacallbacks_t *callbacks)
 989{
 990	dns_name_t *name;
 991
 992	name = (ictx->glue != NULL) ? ictx->glue : ictx->current;
 993	if (dns_name_internalwildcard(name)) {
 994		char namebuf[DNS_NAME_FORMATSIZE];
 995
 996		dns_name_format(name, namebuf, sizeof(namebuf));
 997		(*callbacks->warn)(callbacks, "%s:%lu: warning: ownername "
 998				   "'%s' contains an non-terminal wildcard",
 999				   source, line, namebuf);
1000	}
1001}
1002
1003static isc_result_t
1004load_text(dns_loadctx_t *lctx) {
1005	dns_rdataclass_t rdclass;
1006	dns_rdatatype_t type, covers;
1007	isc_uint32_t ttl_offset = 0;
1008	dns_name_t *new_name;
1009	isc_boolean_t current_has_delegation = ISC_FALSE;
1010	isc_boolean_t done = ISC_FALSE;
1011	isc_boolean_t finish_origin = ISC_FALSE;
1012	isc_boolean_t finish_include = ISC_FALSE;
1013	isc_boolean_t read_till_eol = ISC_FALSE;
1014	isc_boolean_t initialws;
1015	char *include_file = NULL;
1016	isc_token_t token;
1017	isc_result_t result = ISC_R_UNEXPECTED;
1018	rdatalist_head_t glue_list;
1019	rdatalist_head_t current_list;
1020	dns_rdatalist_t *this;
1021	dns_rdatalist_t *rdatalist = NULL;
1022	dns_rdatalist_t *new_rdatalist;
1023	int rdlcount = 0;
1024	int rdlcount_save = 0;
1025	int rdatalist_size = 0;
1026	isc_buffer_t buffer;
1027	isc_buffer_t target;
1028	isc_buffer_t target_ft;
1029	isc_buffer_t target_save;
1030	dns_rdata_t *rdata = NULL;
1031	dns_rdata_t *new_rdata;
1032	int rdcount = 0;
1033	int rdcount_save = 0;
1034	int rdata_size = 0;
1035	unsigned char *target_mem = NULL;
1036	int target_size = TSIZ;
1037	int new_in_use;
1038	unsigned int loop_cnt = 0;
1039	isc_mem_t *mctx;
1040	dns_rdatacallbacks_t *callbacks;
1041	dns_incctx_t *ictx;
1042	char *range = NULL;
1043	char *lhs = NULL;
1044	char *gtype = NULL;
1045	char *rhs = NULL;
1046	const char *source = "";
1047	unsigned long line = 0;
1048	isc_boolean_t explicit_ttl;
1049	isc_stdtime_t now;
1050	char classname1[DNS_RDATACLASS_FORMATSIZE];
1051	char classname2[DNS_RDATACLASS_FORMATSIZE];
1052	unsigned int options = 0;
1053
1054	REQUIRE(DNS_LCTX_VALID(lctx));
1055	callbacks = lctx->callbacks;
1056	mctx = lctx->mctx;
1057	ictx = lctx->inc;
1058
1059	ISC_LIST_INIT(glue_list);
1060	ISC_LIST_INIT(current_list);
1061
1062	isc_stdtime_get(&now);
1063
1064	/*
1065	 * Allocate target_size of buffer space.  This is greater than twice
1066	 * the maximum individual RR data size.
1067	 */
1068	target_mem = isc_mem_get(mctx, target_size);
1069	if (target_mem == NULL) {
1070		result = ISC_R_NOMEMORY;
1071		goto log_and_cleanup;
1072	}
1073	isc_buffer_init(&target, target_mem, target_size);
1074	target_save = target;
1075
1076	if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0)
1077		options |= DNS_RDATA_CHECKNAMES;
1078	if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0)
1079		options |= DNS_RDATA_CHECKNAMESFAIL;
1080	if ((lctx->options & DNS_MASTER_CHECKMX) != 0)
1081		options |= DNS_RDATA_CHECKMX;
1082	if ((lctx->options & DNS_MASTER_CHECKMXFAIL) != 0)
1083		options |= DNS_RDATA_CHECKMXFAIL;
1084	source = isc_lex_getsourcename(lctx->lex);
1085	do {
1086		initialws = ISC_FALSE;
1087		line = isc_lex_getsourceline(lctx->lex);
1088		GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS | ISC_LEXOPT_QSTRING,
1089			 &token, ISC_TRUE);
1090		line = isc_lex_getsourceline(lctx->lex);
1091
1092		if (token.type == isc_tokentype_eof) {
1093			if (read_till_eol)
1094				WARNUNEXPECTEDEOF(lctx->lex);
1095			/* Pop the include stack? */
1096			if (ictx->parent != NULL) {
1097				COMMITALL;
1098				lctx->inc = ictx->parent;
1099				ictx->parent = NULL;
1100				incctx_destroy(lctx->mctx, ictx);
1101				RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
1102				line = isc_lex_getsourceline(lctx->lex);
1103				source = isc_lex_getsourcename(lctx->lex);
1104				ictx = lctx->inc;
1105				EXPECTEOL;
1106				continue;
1107			}
1108			done = ISC_TRUE;
1109			continue;
1110		}
1111
1112		if (token.type == isc_tokentype_eol) {
1113			read_till_eol = ISC_FALSE;
1114			continue;		/* blank line */
1115		}
1116
1117		if (read_till_eol)
1118			continue;
1119
1120		if (token.type == isc_tokentype_initialws) {
1121			/*
1122			 * Still working on the same name.
1123			 */
1124			initialws = ISC_TRUE;
1125		} else if (token.type == isc_tokentype_string ||
1126			   token.type == isc_tokentype_qstring) {
1127
1128			/*
1129			 * "$" Support.
1130			 *
1131			 * "$ORIGIN" and "$INCLUDE" can both take domain names.
1132			 * The processing of "$ORIGIN" and "$INCLUDE" extends
1133			 * across the normal domain name processing.
1134			 */
1135
1136			if (strcasecmp(DNS_AS_STR(token), "$ORIGIN") == 0) {
1137				GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1138				finish_origin = ISC_TRUE;
1139			} else if (strcasecmp(DNS_AS_STR(token),
1140					      "$TTL") == 0) {
1141				GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1142				result =
1143				   dns_ttl_fromtext(&token.value.as_textregion,
1144						    &lctx->ttl);
1145				if (MANYERRS(lctx, result)) {
1146					SETRESULT(lctx, result);
1147					lctx->ttl = 0;
1148				} else if (result != ISC_R_SUCCESS)
1149					goto insist_and_cleanup;
1150				limit_ttl(callbacks, source, line, &lctx->ttl);
1151				lctx->default_ttl = lctx->ttl;
1152				lctx->default_ttl_known = ISC_TRUE;
1153				EXPECTEOL;
1154				continue;
1155			} else if (strcasecmp(DNS_AS_STR(token),
1156					      "$INCLUDE") == 0) {
1157				COMMITALL;
1158				if ((lctx->options & DNS_MASTER_NOINCLUDE)
1159				    != 0)
1160				{
1161					(callbacks->error)(callbacks,
1162					   "%s: %s:%lu: $INCLUDE not allowed",
1163					   "dns_master_load",
1164					   source, line);
1165					result = DNS_R_REFUSED;
1166					goto insist_and_cleanup;
1167				}
1168				if (ttl_offset != 0) {
1169					(callbacks->error)(callbacks,
1170					   "%s: %s:%lu: $INCLUDE "
1171					   "may not be used with $DATE",
1172					   "dns_master_load",
1173					   source, line);
1174					result = DNS_R_SYNTAX;
1175					goto insist_and_cleanup;
1176				}
1177				GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
1178					 ISC_FALSE);
1179				if (include_file != NULL)
1180					isc_mem_free(mctx, include_file);
1181				include_file = isc_mem_strdup(mctx,
1182							   DNS_AS_STR(token));
1183				if (include_file == NULL) {
1184					result = ISC_R_NOMEMORY;
1185					goto log_and_cleanup;
1186				}
1187				GETTOKEN(lctx->lex, 0, &token, ISC_TRUE);
1188
1189				if (token.type == isc_tokentype_eol ||
1190				    token.type == isc_tokentype_eof) {
1191					if (token.type == isc_tokentype_eof)
1192						WARNUNEXPECTEDEOF(lctx->lex);
1193					isc_lex_ungettoken(lctx->lex, &token);
1194					/*
1195					 * No origin field.
1196					 */
1197					result = pushfile(include_file,
1198							  ictx->origin, lctx);
1199					if (MANYERRS(lctx, result)) {
1200						SETRESULT(lctx, result);
1201						LOGITFILE(result, include_file);
1202						continue;
1203					} else if (result != ISC_R_SUCCESS) {
1204						LOGITFILE(result, include_file);
1205						goto insist_and_cleanup;
1206					}
1207					ictx = lctx->inc;
1208					source =
1209					       isc_lex_getsourcename(lctx->lex);
1210					line = isc_lex_getsourceline(lctx->lex);
1211					POST(line);
1212					continue;
1213				}
1214				/*
1215				 * There is an origin field.  Fall through
1216				 * to domain name processing code and do
1217				 * the actual inclusion later.
1218				 */
1219				finish_include = ISC_TRUE;
1220			} else if (strcasecmp(DNS_AS_STR(token),
1221					      "$DATE") == 0) {
1222				isc_int64_t dump_time64;
1223				isc_stdtime_t dump_time, current_time;
1224				GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1225				isc_stdtime_get(&current_time);
1226				result = dns_time64_fromtext(DNS_AS_STR(token),
1227							     &dump_time64);
1228				if (MANYERRS(lctx, result)) {
1229					SETRESULT(lctx, result);
1230					LOGIT(result);
1231					dump_time64 = 0;
1232				} else if (result != ISC_R_SUCCESS)
1233					goto log_and_cleanup;
1234				dump_time = (isc_stdtime_t)dump_time64;
1235				if (dump_time != dump_time64) {
1236					UNEXPECTED_ERROR(__FILE__, __LINE__,
1237					 "%s: %s:%lu: $DATE outside epoch",
1238					 "dns_master_load", source, line);
1239					result = ISC_R_UNEXPECTED;
1240					goto insist_and_cleanup;
1241				}
1242				if (dump_time > current_time) {
1243					UNEXPECTED_ERROR(__FILE__, __LINE__,
1244					"%s: %s:%lu: "
1245					"$DATE in future, using current date",
1246					"dns_master_load", source, line);
1247					dump_time = current_time;
1248				}
1249				ttl_offset = current_time - dump_time;
1250				EXPECTEOL;
1251				continue;
1252			} else if (strcasecmp(DNS_AS_STR(token),
1253					      "$GENERATE") == 0) {
1254				/*
1255				 * Lazy cleanup.
1256				 */
1257				if (range != NULL)
1258					isc_mem_free(mctx, range);
1259				if (lhs != NULL)
1260					isc_mem_free(mctx, lhs);
1261				if (gtype != NULL)
1262					isc_mem_free(mctx, gtype);
1263				if (rhs != NULL)
1264					isc_mem_free(mctx, rhs);
1265				range = lhs = gtype = rhs = NULL;
1266				/* RANGE */
1267				GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1268				range = isc_mem_strdup(mctx,
1269						     DNS_AS_STR(token));
1270				if (range == NULL) {
1271					result = ISC_R_NOMEMORY;
1272					goto log_and_cleanup;
1273				}
1274				/* LHS */
1275				GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1276				lhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1277				if (lhs == NULL) {
1278					result = ISC_R_NOMEMORY;
1279					goto log_and_cleanup;
1280				}
1281				rdclass = 0;
1282				explicit_ttl = ISC_FALSE;
1283				/* CLASS? */
1284				GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1285				if (dns_rdataclass_fromtext(&rdclass,
1286					    &token.value.as_textregion)
1287						== ISC_R_SUCCESS) {
1288					GETTOKEN(lctx->lex, 0, &token,
1289						 ISC_FALSE);
1290				}
1291				/* TTL? */
1292				if (dns_ttl_fromtext(&token.value.as_textregion,
1293						     &lctx->ttl)
1294						== ISC_R_SUCCESS) {
1295					limit_ttl(callbacks, source, line,
1296						  &lctx->ttl);
1297					lctx->ttl_known = ISC_TRUE;
1298					explicit_ttl = ISC_TRUE;
1299					GETTOKEN(lctx->lex, 0, &token,
1300						 ISC_FALSE);
1301				}
1302				/* CLASS? */
1303				if (rdclass == 0 &&
1304				    dns_rdataclass_fromtext(&rdclass,
1305						    &token.value.as_textregion)
1306						== ISC_R_SUCCESS)
1307					GETTOKEN(lctx->lex, 0, &token,
1308						 ISC_FALSE);
1309				/* TYPE */
1310				gtype = isc_mem_strdup(mctx,
1311						       DNS_AS_STR(token));
1312				if (gtype == NULL) {
1313					result = ISC_R_NOMEMORY;
1314					goto log_and_cleanup;
1315				}
1316				/* RHS */
1317				GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING,
1318					 &token, ISC_FALSE);
1319				rhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1320				if (rhs == NULL) {
1321					result = ISC_R_NOMEMORY;
1322					goto log_and_cleanup;
1323				}
1324				if (!lctx->ttl_known &&
1325				    !lctx->default_ttl_known) {
1326					(*callbacks->error)(callbacks,
1327					    "%s: %s:%lu: no TTL specified",
1328					    "dns_master_load", source, line);
1329					result = DNS_R_NOTTL;
1330					if (MANYERRS(lctx, result)) {
1331						SETRESULT(lctx, result);
1332						lctx->ttl = 0;
1333					} else if (result != ISC_R_SUCCESS)
1334						goto insist_and_cleanup;
1335				} else if (!explicit_ttl &&
1336					   lctx->default_ttl_known) {
1337					lctx->ttl = lctx->default_ttl;
1338				}
1339				/*
1340				 * If the class specified does not match the
1341				 * zone's class print out a error message and
1342				 * exit.
1343				 */
1344				if (rdclass != 0 && rdclass != lctx->zclass) {
1345					goto bad_class;
1346				}
1347				result = generate(lctx, range, lhs, gtype, rhs,
1348						  source, line);
1349				if (MANYERRS(lctx, result)) {
1350					SETRESULT(lctx, result);
1351				} else if (result != ISC_R_SUCCESS)
1352					goto insist_and_cleanup;
1353				EXPECTEOL;
1354				continue;
1355			} else if (strncasecmp(DNS_AS_STR(token),
1356					       "$", 1) == 0) {
1357				(callbacks->error)(callbacks,
1358					   "%s: %s:%lu: "
1359					   "unknown $ directive '%s'",
1360					   "dns_master_load", source, line,
1361					   DNS_AS_STR(token));
1362				result = DNS_R_SYNTAX;
1363				if (MANYERRS(lctx, result)) {
1364					SETRESULT(lctx, result);
1365				} else if (result != ISC_R_SUCCESS)
1366					goto insist_and_cleanup;
1367			}
1368
1369			/*
1370			 * Normal processing resumes.
1371			 *
1372			 * Find a free name buffer.
1373			 */
1374			for (new_in_use = 0; new_in_use < NBUFS; new_in_use++)
1375				if (!ictx->in_use[new_in_use])
1376					break;
1377			INSIST(new_in_use < NBUFS);
1378			dns_fixedname_init(&ictx->fixed[new_in_use]);
1379			new_name = dns_fixedname_name(&ictx->fixed[new_in_use]);
1380			isc_buffer_init(&buffer, token.value.as_region.base,
1381					token.value.as_region.length);
1382			isc_buffer_add(&buffer, token.value.as_region.length);
1383			isc_buffer_setactive(&buffer,
1384					     token.value.as_region.length);
1385			result = dns_name_fromtext(new_name, &buffer,
1386					  ictx->origin, 0, NULL);
1387			if (MANYERRS(lctx, result)) {
1388				SETRESULT(lctx, result);
1389				LOGIT(result);
1390				read_till_eol = ISC_TRUE;
1391				continue;
1392			} else if (result != ISC_R_SUCCESS)
1393				goto log_and_cleanup;
1394
1395			/*
1396			 * Finish $ORIGIN / $INCLUDE processing if required.
1397			 */
1398			if (finish_origin) {
1399				if (ictx->origin_in_use != -1)
1400					ictx->in_use[ictx->origin_in_use] =
1401						ISC_FALSE;
1402				ictx->origin_in_use = new_in_use;
1403				ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
1404				ictx->origin = new_name;
1405				finish_origin = ISC_FALSE;
1406				EXPECTEOL;
1407				continue;
1408			}
1409			if (finish_include) {
1410				finish_include = ISC_FALSE;
1411				result = pushfile(include_file, new_name, lctx);
1412				if (MANYERRS(lctx, result)) {
1413					SETRESULT(lctx, result);
1414					LOGITFILE(result, include_file);
1415					continue;
1416				} else if (result != ISC_R_SUCCESS) {
1417					LOGITFILE(result, include_file);
1418					goto insist_and_cleanup;
1419				}
1420				ictx = lctx->inc;
1421				source = isc_lex_getsourcename(lctx->lex);
1422				line = isc_lex_getsourceline(lctx->lex);
1423				POST(line);
1424				continue;
1425			}
1426
1427			/*
1428			 * "$" Processing Finished
1429			 */
1430
1431			/*
1432			 * If we are processing glue and the new name does
1433			 * not match the current glue name, commit the glue
1434			 * and pop stacks leaving us in 'normal' processing
1435			 * state.  Linked lists are undone by commit().
1436			 */
1437			if (ictx->glue != NULL &&
1438			    dns_name_compare(ictx->glue, new_name) != 0) {
1439				result = commit(callbacks, lctx, &glue_list,
1440						ictx->glue, source,
1441						ictx->glue_line);
1442				if (MANYERRS(lctx, result)) {
1443					SETRESULT(lctx, result);
1444				} else if (result != ISC_R_SUCCESS)
1445					goto insist_and_cleanup;
1446				if (ictx->glue_in_use != -1)
1447					ictx->in_use[ictx->glue_in_use] =
1448						ISC_FALSE;
1449				ictx->glue_in_use = -1;
1450				ictx->glue = NULL;
1451				rdcount = rdcount_save;
1452				rdlcount = rdlcount_save;
1453				target = target_save;
1454			}
1455
1456			/*
1457			 * If we are in 'normal' processing state and the new
1458			 * name does not match the current name, see if the
1459			 * new name is for glue and treat it as such,
1460			 * otherwise we have a new name so commit what we
1461			 * have.
1462			 */
1463			if ((ictx->glue == NULL) && (ictx->current == NULL ||
1464			    dns_name_compare(ictx->current, new_name) != 0)) {
1465				if (current_has_delegation &&
1466					is_glue(&current_list, new_name)) {
1467					rdcount_save = rdcount;
1468					rdlcount_save = rdlcount;
1469					target_save = target;
1470					ictx->glue = new_name;
1471					ictx->glue_in_use = new_in_use;
1472					ictx->in_use[ictx->glue_in_use] =
1473						ISC_TRUE;
1474				} else {
1475					result = commit(callbacks, lctx,
1476							&current_list,
1477							ictx->current,
1478							source,
1479							ictx->current_line);
1480					if (MANYERRS(lctx, result)) {
1481						SETRESULT(lctx, result);
1482					} else if (result != ISC_R_SUCCESS)
1483						goto insist_and_cleanup;
1484					rdcount = 0;
1485					rdlcount = 0;
1486					if (ictx->current_in_use != -1)
1487					    ictx->in_use[ictx->current_in_use] =
1488						ISC_FALSE;
1489					ictx->current_in_use = new_in_use;
1490					ictx->in_use[ictx->current_in_use] =
1491						ISC_TRUE;
1492					ictx->current = new_name;
1493					current_has_delegation = ISC_FALSE;
1494					isc_buffer_init(&target, target_mem,
1495							target_size);
1496				}
1497				/*
1498				 * Check for internal wildcards.
1499				 */
1500				if ((lctx->options & DNS_MASTER_CHECKWILDCARD)
1501						 != 0)
1502					check_wildcard(ictx, source, line,
1503						       callbacks);
1504
1505			}
1506			if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
1507			    (lctx->options & DNS_MASTER_SLAVE) == 0 &&
1508			    (lctx->options & DNS_MASTER_KEY) == 0 &&
1509			    !dns_name_issubdomain(new_name, lctx->top))
1510			{
1511				char namebuf[DNS_NAME_FORMATSIZE];
1512				dns_name_format(new_name, namebuf,
1513						sizeof(namebuf));
1514				/*
1515				 * Ignore out-of-zone data.
1516				 */
1517				(*callbacks->warn)(callbacks,
1518				       "%s:%lu: "
1519				       "ignoring out-of-zone data (%s)",
1520				       source, line, namebuf);
1521				ictx->drop = ISC_TRUE;
1522			} else
1523				ictx->drop = ISC_FALSE;
1524		} else {
1525			UNEXPECTED_ERROR(__FILE__, __LINE__,
1526					 "%s:%lu: isc_lex_gettoken() returned "
1527					 "unexpected token type (%d)",
1528					 source, line, token.type);
1529			result = ISC_R_UNEXPECTED;
1530			if (MANYERRS(lctx, result)) {
1531				SETRESULT(lctx, result);
1532				LOGIT(result);
1533				continue;
1534			} else if (result != ISC_R_SUCCESS)
1535				goto insist_and_cleanup;
1536		}
1537
1538		/*
1539		 * Find TTL, class and type.  Both TTL and class are optional
1540		 * and may occur in any order if they exist. TTL and class
1541		 * come before type which must exist.
1542		 *
1543		 * [<TTL>] [<class>] <type> <RDATA>
1544		 * [<class>] [<TTL>] <type> <RDATA>
1545		 */
1546
1547		type = 0;
1548		rdclass = 0;
1549
1550		GETTOKEN(lctx->lex, 0, &token, initialws);
1551
1552		if (initialws) {
1553			if (token.type == isc_tokentype_eol) {
1554				read_till_eol = ISC_FALSE;
1555				continue;		/* blank line */
1556			}
1557
1558			if (token.type == isc_tokentype_eof) {
1559				WARNUNEXPECTEDEOF(lctx->lex);
1560				read_till_eol = ISC_FALSE;
1561				isc_lex_ungettoken(lctx->lex, &token);
1562				continue;
1563			}
1564
1565			if (ictx->current == NULL) {
1566				(*callbacks->error)(callbacks,
1567					"%s:%lu: no current owner name",
1568					source, line);
1569				result = DNS_R_NOOWNER;
1570				if (MANYERRS(lctx, result)) {
1571					SETRESULT(lctx, result);
1572					read_till_eol = ISC_TRUE;
1573					continue;
1574				} else if (result != ISC_R_SUCCESS)
1575					goto insist_and_cleanup;
1576			}
1577		}
1578
1579		if (dns_rdataclass_fromtext(&rdclass,
1580					    &token.value.as_textregion)
1581				== ISC_R_SUCCESS)
1582			GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1583
1584		explicit_ttl = ISC_FALSE;
1585		if (dns_ttl_fromtext(&token.value.as_textregion, &lctx->ttl)
1586				== ISC_R_SUCCESS) {
1587			limit_ttl(callbacks, source, line, &lctx->ttl);
1588			explicit_ttl = ISC_TRUE;
1589			lctx->ttl_known = ISC_TRUE;
1590			GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1591		}
1592
1593		if (token.type != isc_tokentype_string) {
1594			UNEXPECTED_ERROR(__FILE__, __LINE__,
1595			"isc_lex_gettoken() returned unexpected token type");
1596			result = ISC_R_UNEXPECTED;
1597			if (MANYERRS(lctx, result)) {
1598				SETRESULT(lctx, result);
1599				read_till_eol = ISC_TRUE;
1600				continue;
1601			} else if (result != ISC_R_SUCCESS)
1602				goto insist_and_cleanup;
1603		}
1604
1605		if (rdclass == 0 &&
1606		    dns_rdataclass_fromtext(&rdclass,
1607					    &token.value.as_textregion)
1608				== ISC_R_SUCCESS)
1609			GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1610
1611		if (token.type != isc_tokentype_string) {
1612			UNEXPECTED_ERROR(__FILE__, __LINE__,
1613			"isc_lex_gettoken() returned unexpected token type");
1614			result = ISC_R_UNEXPECTED;
1615			if (MANYERRS(lctx, result)) {
1616				SETRESULT(lctx, result);
1617				read_till_eol = ISC_TRUE;
1618				continue;
1619			} else if (result != ISC_R_SUCCESS)
1620				goto insist_and_cleanup;
1621		}
1622
1623		result = dns_rdatatype_fromtext(&type,
1624						&token.value.as_textregion);
1625		if (result != ISC_R_SUCCESS) {
1626			(*callbacks->warn)(callbacks,
1627				   "%s:%lu: unknown RR type '%.*s'",
1628				   source, line,
1629				   token.value.as_textregion.length,
1630				   token.value.as_textregion.base);
1631			if (MANYERRS(lctx, result)) {
1632				SETRESULT(lctx, result);
1633				read_till_eol = ISC_TRUE;
1634				continue;
1635			} else if (result != ISC_R_SUCCESS)
1636				goto insist_and_cleanup;
1637		}
1638
1639		/*
1640		 * If the class specified does not match the zone's class
1641		 * print out a error message and exit.
1642		 */
1643		if (rdclass != 0 && rdclass != lctx->zclass) {
1644  bad_class:
1645
1646			dns_rdataclass_format(rdclass, classname1,
1647					      sizeof(classname1));
1648			dns_rdataclass_format(lctx->zclass, classname2,
1649					      sizeof(classname2));
1650			(*callbacks->error)(callbacks,
1651					    "%s:%lu: class '%s' != "
1652					    "zone class '%s'",
1653					    source, line,
1654					    classname1, classname2);
1655			result = DNS_R_BADCLASS;
1656			if (MANYERRS(lctx, result)) {
1657				SETRESULT(lctx, result);
1658				read_till_eol = ISC_TRUE;
1659				continue;
1660			} else if (result != ISC_R_SUCCESS)
1661				goto insist_and_cleanup;
1662		}
1663
1664		if (type == dns_rdatatype_ns && ictx->glue == NULL)
1665			current_has_delegation = ISC_TRUE;
1666
1667		/*
1668		 * RFC1123: MD and MF are not allowed to be loaded from
1669		 * master files.
1670		 */
1671		if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
1672		    (lctx->options & DNS_MASTER_SLAVE) == 0 &&
1673		    (type == dns_rdatatype_md || type == dns_rdatatype_mf)) {
1674			char typename[DNS_RDATATYPE_FORMATSIZE];
1675
1676			result = DNS_R_OBSOLETE;
1677
1678			dns_rdatatype_format(type, typename, sizeof(typename));
1679			(*callbacks->error)(callbacks,
1680					    "%s:%lu: %s '%s': %s",
1681					    source, line,
1682					    "type", typename,
1683					    dns_result_totext(result));
1684			if (MANYERRS(lctx, result)) {
1685				SETRESULT(lctx, result);
1686			} else
1687				goto insist_and_cleanup;
1688		}
1689
1690		/*
1691		 * Find a rdata structure.
1692		 */
1693		if (rdcount == rdata_size) {
1694			new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
1695					       rdata_size, &current_list,
1696					       &glue_list, mctx);
1697			if (new_rdata == NULL) {
1698				result = ISC_R_NOMEMORY;
1699				goto log_and_cleanup;
1700			}
1701			rdata_size += RDSZ;
1702			rdata = new_rdata;
1703		}
1704
1705		/*
1706		 * Peek at the NS record.
1707		 */
1708		if (type == dns_rdatatype_ns &&
1709		    lctx->zclass == dns_rdataclass_in &&
1710		    (lctx->options & DNS_MASTER_CHECKNS) != 0) {
1711
1712			GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1713			result = check_ns(lctx, &token, source, line);
1714			isc_lex_ungettoken(lctx->lex, &token);
1715			if ((lctx->options & DNS_MASTER_FATALNS) != 0) {
1716				if (MANYERRS(lctx, result)) {
1717					SETRESULT(lctx, result);
1718				} else if (result != ISC_R_SUCCESS)
1719					goto insist_and_cleanup;
1720			}
1721		}
1722
1723		/*
1724		 * Check owner name.
1725		 */
1726		options &= ~DNS_RDATA_CHECKREVERSE;
1727		if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0) {
1728			isc_boolean_t ok;
1729			dns_name_t *name;
1730
1731			name = (ictx->glue != NULL) ? ictx->glue :
1732						      ictx->current;
1733			ok = dns_rdata_checkowner(name, lctx->zclass, type,
1734						  ISC_TRUE);
1735			if (!ok) {
1736				char namebuf[DNS_NAME_FORMATSIZE];
1737				const char *desc;
1738				dns_name_format(name, namebuf, sizeof(namebuf));
1739				result = DNS_R_BADOWNERNAME;
1740				desc = dns_result_totext(result);
1741				if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0) {
1742					(*callbacks->error)(callbacks,
1743							    "%s:%lu: %s: %s",
1744							    source, line,
1745							    namebuf, desc);
1746					if (MANYERRS(lctx, result)) {
1747						SETRESULT(lctx, result);
1748					} else if (result != ISC_R_SUCCESS)
1749						goto cleanup;
1750				} else {
1751					(*callbacks->warn)(callbacks,
1752							   "%s:%lu: %s: %s",
1753							   source, line,
1754							   namebuf, desc);
1755				}
1756			}
1757			if (type == dns_rdatatype_ptr &&
1758			    (dns_name_issubdomain(name, &in_addr_arpa) ||
1759			     dns_name_issubdomain(name, &ip6_arpa) ||
1760			     dns_name_issubdomain(name, &ip6_int)))
1761				options |= DNS_RDATA_CHECKREVERSE;
1762		}
1763
1764		/*
1765		 * Read rdata contents.
1766		 */
1767		dns_rdata_init(&rdata[rdcount]);
1768		target_ft = target;
1769		result = dns_rdata_fromtext(&rdata[rdcount], lctx->zclass,
1770					    type, lctx->lex, ictx->origin,
1771					    options, lctx->mctx, &target,
1772					    callbacks);
1773		if (MANYERRS(lctx, result)) {
1774			SETRESULT(lctx, result);
1775			continue;
1776		} else if (result != ISC_R_SUCCESS)
1777			goto insist_and_cleanup;
1778
1779		if (ictx->drop) {
1780			target = target_ft;
1781			continue;
1782		}
1783
1784		if (type == dns_rdatatype_soa &&
1785		    (lctx->options & DNS_MASTER_ZONE) != 0 &&
1786		    dns_name_compare(ictx->current, lctx->top) != 0) {
1787			char namebuf[DNS_NAME_FORMATSIZE];
1788			dns_name_format(ictx->current, namebuf,
1789					sizeof(namebuf));
1790			(*callbacks->error)(callbacks, "%s:%lu: SOA "
1791					    "record not at top of zone (%s)",
1792					    source, line, namebuf);
1793			result = DNS_R_NOTZONETOP;
1794			if (MANYERRS(lctx, result)) {
1795				SETRESULT(lctx, result);
1796				read_till_eol = ISC_TRUE;
1797				target = target_ft;
1798				continue;
1799			} else if (result != ISC_R_SUCCESS)
1800				goto insist_and_cleanup;
1801		}
1802
1803
1804		if (type == dns_rdatatype_rrsig ||
1805		    type == dns_rdatatype_sig)
1806			covers = dns_rdata_covers(&rdata[rdcount]);
1807		else
1808			covers = 0;
1809
1810		if (!lctx->ttl_known && !lctx->default_ttl_known) {
1811			if (type == dns_rdatatype_soa) {
1812				(*callbacks->warn)(callbacks,
1813						   "%s:%lu: no TTL specified; "
1814						   "using SOA MINTTL instead",
1815						   source, line);
1816				lctx->ttl = dns_soa_getminimum(&rdata[rdcount]);
1817				limit_ttl(callbacks, source, line, &lctx->ttl);
1818				lctx->default_ttl = lctx->ttl;
1819				lctx->default_ttl_known = ISC_TRUE;
1820			} else if ((lctx->options & DNS_MASTER_HINT) != 0) {
1821				/*
1822				 * Zero TTL's are fine for hints.
1823				 */
1824				lctx->ttl = 0;
1825				lctx->default_ttl = lctx->ttl;
1826				lctx->default_ttl_known = ISC_TRUE;
1827			} else {
1828				(*callbacks->warn)(callbacks,
1829						   "%s:%lu: no TTL specified; "
1830						   "zone rejected",
1831						   source, line);
1832				result = DNS_R_NOTTL;
1833				if (MANYERRS(lctx, result)) {
1834					SETRESULT(lctx, result);
1835					lctx->ttl = 0;
1836				} else {
1837					goto insist_and_cleanup;
1838				}
1839			}
1840		} else if (!explicit_ttl && lctx->default_ttl_known) {
1841			lctx->ttl = lctx->default_ttl;
1842		} else if (!explicit_ttl && lctx->warn_1035) {
1843			(*callbacks->warn)(callbacks,
1844					   "%s:%lu: "
1845					   "using RFC1035 TTL semantics",
1846					   source, line);
1847			lctx->warn_1035 = ISC_FALSE;
1848		}
1849
1850		if (type == dns_rdatatype_rrsig && lctx->warn_sigexpired) {
1851			dns_rdata_rrsig_t sig;
1852			result = dns_rdata_tostruct(&rdata[rdcount], &sig,
1853						    NULL);
1854			RUNTIME_CHECK(result == ISC_R_SUCCESS);
1855			if (isc_serial_lt(sig.timeexpire, now)) {
1856				(*callbacks->warn)(callbacks,
1857						   "%s:%lu: "
1858						   "signature has expired",
1859						   source, line);
1860

Large files files are truncated, but you can click here to view the full file