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