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