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