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