Merge branch 'vendor/TCSH'
[dragonfly.git] / contrib / bind-9.3 / lib / dns / master.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and 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.122.2.8.2.14 2004/05/05 01:32:16 marka Exp $ */
19
20 #include <config.h>
21
22 #include <isc/event.h>
23 #include <isc/lex.h>
24 #include <isc/magic.h>
25 #include <isc/mem.h>
26 #include <isc/print.h>
27 #include <isc/serial.h>
28 #include <isc/stdtime.h>
29 #include <isc/string.h>
30 #include <isc/task.h>
31 #include <isc/util.h>
32
33 #include <dns/callbacks.h>
34 #include <dns/events.h>
35 #include <dns/fixedname.h>
36 #include <dns/master.h>
37 #include <dns/name.h>
38 #include <dns/rdata.h>
39 #include <dns/rdataclass.h>
40 #include <dns/rdatalist.h>
41 #include <dns/rdataset.h>
42 #include <dns/rdatastruct.h>
43 #include <dns/rdatatype.h>
44 #include <dns/result.h>
45 #include <dns/soa.h>
46 #include <dns/time.h>
47 #include <dns/ttl.h>
48
49 /*
50  * Grow the number of dns_rdatalist_t (RDLSZ) and dns_rdata_t (RDSZ) structures
51  * by these sizes when we need to.
52  *
53  * RDLSZ reflects the number of different types with the same name expected.
54  * RDSZ reflects the number of rdata expected at a give name that can fit into
55  * 64k.
56  */
57
58 #define RDLSZ 32
59 #define RDSZ 512
60
61 #define NBUFS 4
62 #define MAXWIRESZ 255
63
64 /*
65  * Target buffer size and minimum target size.
66  * MINTSIZ must be big enough to hold the largest rdata record.
67  *
68  * TSIZ >= MINTSIZ
69  */
70 #define TSIZ (128*1024)
71 /*
72  * max message size - header - root - type - class - ttl - rdlen
73  */
74 #define MINTSIZ (65535 - 12 - 1 - 2 - 2 - 4 - 2)
75 /*
76  * Size for tokens in the presentation format,
77  * The largest tokens are the base64 blocks in KEY and CERT records,
78  * Largest key allowed is about 1372 bytes but
79  * there is no fixed upper bound on CERT records.
80  * 2K is too small for some X.509s, 8K is overkill.
81  */
82 #define TOKENSIZ (8*1024)
83
84 #define DNS_MASTER_BUFSZ 2048
85
86 typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
87
88 typedef struct dns_incctx dns_incctx_t;
89
90 /*
91  * Master file load state.
92  */
93
94 struct dns_loadctx {
95         unsigned int            magic;
96         isc_mem_t               *mctx;
97         isc_lex_t               *lex;
98         isc_boolean_t           keep_lex;
99         dns_rdatacallbacks_t    *callbacks;
100         isc_task_t              *task;
101         dns_loaddonefunc_t      done;
102         void                    *done_arg;
103         unsigned int            options;
104         isc_boolean_t           ttl_known;
105         isc_boolean_t           default_ttl_known;
106         isc_boolean_t           warn_1035;
107         isc_boolean_t           warn_tcr;
108         isc_boolean_t           warn_sigexpired;
109         isc_boolean_t           seen_include;
110         isc_uint32_t            ttl;
111         isc_uint32_t            default_ttl;
112         dns_rdataclass_t        zclass;
113         dns_fixedname_t         fixed_top;
114         dns_name_t              *top;                   /* top of zone */
115         /* Which fixed buffers we are using? */
116         unsigned int            loop_cnt;               /* records per quantum,
117                                                          * 0 => all. */
118         isc_boolean_t           canceled;
119         isc_mutex_t             lock;
120         isc_result_t            result;
121         /* locked by lock */
122         isc_uint32_t            references;
123         dns_incctx_t            *inc;
124 };
125
126 struct dns_incctx {
127         dns_incctx_t            *parent;
128         dns_name_t              *origin;
129         dns_name_t              *current;
130         dns_name_t              *glue;
131         dns_fixedname_t         fixed[NBUFS];           /* working buffers */
132         unsigned int            in_use[NBUFS];          /* covert to bitmap? */
133         int                     glue_in_use;
134         int                     current_in_use;
135         int                     origin_in_use;
136         isc_boolean_t           drop;
137         unsigned int            glue_line;
138         unsigned int            current_line;
139 };
140
141 #define DNS_LCTX_MAGIC ISC_MAGIC('L','c','t','x')
142 #define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
143
144 #define DNS_AS_STR(t) ((t).value.as_textregion.base)
145
146 static isc_result_t
147 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx);
148
149 static isc_result_t
150 commit(dns_rdatacallbacks_t *, dns_loadctx_t *, rdatalist_head_t *,
151        dns_name_t *, const char *, unsigned int);
152
153 static isc_boolean_t
154 is_glue(rdatalist_head_t *, dns_name_t *);
155
156 static dns_rdatalist_t *
157 grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *,
158                 rdatalist_head_t *, isc_mem_t *mctx);
159
160 static dns_rdata_t *
161 grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *,
162            isc_mem_t *);
163
164 static void
165 load_quantum(isc_task_t *task, isc_event_t *event);
166
167 static isc_result_t
168 task_send(dns_loadctx_t *lctx);
169
170 static void
171 loadctx_destroy(dns_loadctx_t *lctx);
172
173 #define GETTOKEN(lexer, options, token, eol) \
174         do { \
175                 result = gettoken(lexer, options, token, eol, callbacks); \
176                 switch (result) { \
177                 case ISC_R_SUCCESS: \
178                         break; \
179                 case ISC_R_UNEXPECTED: \
180                         goto insist_and_cleanup; \
181                 default: \
182                         if (MANYERRS(lctx, result)) { \
183                                 SETRESULT(lctx, result); \
184                                 LOGIT(result); \
185                                 read_till_eol = ISC_TRUE; \
186                                 goto next_line; \
187                         } else \
188                                 goto log_and_cleanup; \
189                 } \
190                 if ((token)->type == isc_tokentype_special) { \
191                         result = DNS_R_SYNTAX; \
192                         if (MANYERRS(lctx, result)) { \
193                                 SETRESULT(lctx, result); \
194                                 LOGIT(result); \
195                                 read_till_eol = ISC_TRUE; \
196                                 goto next_line; \
197                         } else \
198                                 goto log_and_cleanup; \
199                 } \
200         } while (0)
201
202 #define COMMITALL \
203         do { \
204                 result = commit(callbacks, lctx, &current_list, \
205                                 ictx->current, source, ictx->current_line); \
206                 if (MANYERRS(lctx, result)) { \
207                         SETRESULT(lctx, result); \
208                 } else if (result != ISC_R_SUCCESS) \
209                         goto insist_and_cleanup; \
210                 result = commit(callbacks, lctx, &glue_list, \
211                                 ictx->glue, source, ictx->glue_line); \
212                 if (MANYERRS(lctx, result)) { \
213                         SETRESULT(lctx, result); \
214                 } else if (result != ISC_R_SUCCESS) \
215                         goto insist_and_cleanup; \
216                 rdcount = 0; \
217                 rdlcount = 0; \
218                 isc_buffer_init(&target, target_mem, target_size); \
219                 rdcount_save = rdcount; \
220                 rdlcount_save = rdlcount; \
221         } while (0)
222
223 #define WARNUNEXPECTEDEOF(lexer) \
224         do { \
225                 if (isc_lex_isfile(lexer)) \
226                         (*callbacks->warn)(callbacks, \
227                                 "%s: file does not end with newline", \
228                                 source); \
229         } while (0)
230
231 #define EXPECTEOL \
232         do { \
233                 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE); \
234                 if (token.type != isc_tokentype_eol) { \
235                         isc_lex_ungettoken(lctx->lex, &token); \
236                         result = DNS_R_EXTRATOKEN; \
237                         if (MANYERRS(lctx, result)) { \
238                                 SETRESULT(lctx, result); \
239                                 LOGIT(result); \
240                                 read_till_eol = ISC_TRUE; \
241                                 continue; \
242                         } else if (result != ISC_R_SUCCESS) \
243                                 goto log_and_cleanup; \
244                 } \
245         } while (0)
246
247 #define MANYERRS(lctx, result) \
248                 ((result != ISC_R_SUCCESS) && \
249                 ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
250
251 #define SETRESULT(lctx, r) \
252                 do { \
253                         if ((lctx)->result == ISC_R_SUCCESS) \
254                                 (lctx)->result = r; \
255                 } while (0)
256
257 #define LOGITFILE(result, filename) \
258         if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \
259             result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \
260             result == ISC_R_NOPERM) \
261                 (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \
262                                     "dns_master_load", source, line, \
263                                     filename, dns_result_totext(result)); \
264         else LOGIT(result)
265
266 #define LOGIT(result) \
267         if (result == ISC_R_NOMEMORY) \
268                 (*callbacks->error)(callbacks, "dns_master_load: %s", \
269                                     dns_result_totext(result)); \
270         else \
271                 (*callbacks->error)(callbacks, "%s: %s:%lu: %s", \
272                                     "dns_master_load", \
273                                     source, line, dns_result_totext(result))
274
275
276 static unsigned char in_addr_arpa_data[]  = "\007IN-ADDR\004ARPA";
277 static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 };
278 static const dns_name_t in_addr_arpa =
279 {
280         DNS_NAME_MAGIC,
281         in_addr_arpa_data, 14, 3,
282         DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
283         in_addr_arpa_offsets, NULL,
284         {(void *)-1, (void *)-1},
285         {NULL, NULL}
286 };
287
288 static unsigned char ip6_int_data[]  = "\003IP6\003INT";
289 static unsigned char ip6_int_offsets[] = { 0, 4, 8 };
290 static const dns_name_t ip6_int =
291 {
292         DNS_NAME_MAGIC,
293         ip6_int_data, 9, 3,
294         DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
295         ip6_int_offsets, NULL,
296         {(void *)-1, (void *)-1},
297         {NULL, NULL}
298 };
299
300 static unsigned char ip6_arpa_data[]  = "\003IP6\004ARPA";
301 static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
302 static const dns_name_t ip6_arpa =
303 {
304         DNS_NAME_MAGIC,
305         ip6_arpa_data, 10, 3,
306         DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
307         ip6_arpa_offsets, NULL,
308         {(void *)-1, (void *)-1},
309         {NULL, NULL}
310 };
311
312
313 static inline isc_result_t
314 gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token,
315          isc_boolean_t eol, dns_rdatacallbacks_t *callbacks)
316 {
317         isc_result_t result;
318
319         options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE |
320                 ISC_LEXOPT_ESCAPE;
321         result = isc_lex_gettoken(lex, options, token);
322         if (result != ISC_R_SUCCESS) {
323                 switch (result) {
324                 case ISC_R_NOMEMORY:
325                         return (ISC_R_NOMEMORY);
326                 default:
327                         (*callbacks->error)(callbacks,
328                                             "dns_master_load: %s:%lu:"
329                                             " isc_lex_gettoken() failed: %s",
330                                             isc_lex_getsourcename(lex),
331                                             isc_lex_getsourceline(lex),
332                                             isc_result_totext(result));
333                         return (result);
334                 }
335                 /*NOTREACHED*/
336         }
337         if (eol != ISC_TRUE)
338                 if (token->type == isc_tokentype_eol ||
339                     token->type == isc_tokentype_eof) {
340                         (*callbacks->error)(callbacks,
341                             "dns_master_load: %s:%lu: unexpected end of %s",
342                                             isc_lex_getsourcename(lex),
343                                             isc_lex_getsourceline(lex),
344                                             (token->type ==
345                                              isc_tokentype_eol) ?
346                                             "line" : "file");
347                         return (ISC_R_UNEXPECTEDEND);
348                 }
349         return (ISC_R_SUCCESS);
350 }
351
352
353 void
354 dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
355
356         REQUIRE(target != NULL && *target == NULL);
357         REQUIRE(DNS_LCTX_VALID(source));
358
359         LOCK(&source->lock);
360         INSIST(source->references > 0);
361         source->references++;
362         INSIST(source->references != 0);        /* Overflow? */
363         UNLOCK(&source->lock);
364
365         *target = source;
366 }
367
368 void
369 dns_loadctx_detach(dns_loadctx_t **lctxp) {
370         dns_loadctx_t *lctx;
371         isc_boolean_t need_destroy = ISC_FALSE;
372
373         REQUIRE(lctxp != NULL);
374         lctx = *lctxp;
375         REQUIRE(DNS_LCTX_VALID(lctx));
376
377         LOCK(&lctx->lock);
378         INSIST(lctx->references > 0);
379         lctx->references--;
380         if (lctx->references == 0)
381                 need_destroy = ISC_TRUE;
382         UNLOCK(&lctx->lock);
383
384         if (need_destroy)
385                 loadctx_destroy(lctx);
386         *lctxp = NULL;
387 }
388
389 static void
390 incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
391         dns_incctx_t *parent;
392
393  again:
394         parent = ictx->parent;
395         ictx->parent = NULL;
396
397         isc_mem_put(mctx, ictx, sizeof(*ictx));
398
399         if (parent != NULL) {
400                 ictx = parent;
401                 goto again;
402         }
403 }
404
405 static void
406 loadctx_destroy(dns_loadctx_t *lctx) {
407         isc_mem_t *mctx;
408
409         REQUIRE(DNS_LCTX_VALID(lctx));
410
411         lctx->magic = 0;
412         if (lctx->inc != NULL)
413                 incctx_destroy(lctx->mctx, lctx->inc);
414
415         /* isc_lex_destroy() will close all open streams */
416         if (lctx->lex != NULL && !lctx->keep_lex)
417                 isc_lex_destroy(&lctx->lex);
418
419         if (lctx->task != NULL)
420                 isc_task_detach(&lctx->task);
421         DESTROYLOCK(&lctx->lock);
422         mctx = NULL;
423         isc_mem_attach(lctx->mctx, &mctx);
424         isc_mem_detach(&lctx->mctx);
425         isc_mem_put(mctx, lctx, sizeof(*lctx));
426         isc_mem_detach(&mctx);
427 }
428
429 static isc_result_t
430 incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
431         dns_incctx_t *ictx;
432         isc_region_t r;
433         int i;
434
435         ictx = isc_mem_get(mctx, sizeof(*ictx));
436         if (ictx == NULL)
437                 return (ISC_R_NOMEMORY);
438
439         for (i = 0; i < NBUFS; i++) {
440                 dns_fixedname_init(&ictx->fixed[i]);
441                 ictx->in_use[i] = ISC_FALSE;
442         }
443
444         ictx->origin_in_use = 0;
445         ictx->origin = dns_fixedname_name(&ictx->fixed[ictx->origin_in_use]);
446         ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
447         dns_name_toregion(origin, &r);
448         dns_name_fromregion(ictx->origin, &r);
449
450         ictx->glue = NULL;
451         ictx->current = NULL;
452         ictx->glue_in_use = -1;
453         ictx->current_in_use = -1;
454         ictx->parent = NULL;
455         ictx->drop = ISC_FALSE;
456         ictx->glue_line = 0;
457         ictx->current_line = 0;
458
459         *ictxp = ictx;
460         return (ISC_R_SUCCESS);
461 }
462
463 static isc_result_t
464 loadctx_create(isc_mem_t *mctx, unsigned int options, dns_name_t *top,
465                dns_rdataclass_t zclass, dns_name_t *origin,
466                dns_rdatacallbacks_t *callbacks, isc_task_t *task,
467                dns_loaddonefunc_t done, void *done_arg, isc_lex_t *lex,
468                dns_loadctx_t **lctxp)
469 {
470         dns_loadctx_t *lctx;
471         isc_result_t result;
472         isc_region_t r;
473         isc_lexspecials_t specials;
474
475         REQUIRE(lctxp != NULL && *lctxp == NULL);
476         REQUIRE(callbacks != NULL);
477         REQUIRE(callbacks->add != NULL);
478         REQUIRE(callbacks->error != NULL);
479         REQUIRE(callbacks->warn != NULL);
480         REQUIRE(mctx != NULL);
481         REQUIRE(dns_name_isabsolute(top));
482         REQUIRE(dns_name_isabsolute(origin));
483         REQUIRE((task == NULL && done == NULL) ||
484                 (task != NULL && done != NULL));
485
486         lctx = isc_mem_get(mctx, sizeof(*lctx));
487         if (lctx == NULL)
488                 return (ISC_R_NOMEMORY);
489         result = isc_mutex_init(&lctx->lock);
490         if (result != ISC_R_SUCCESS) {
491                 isc_mem_put(mctx, lctx, sizeof(*lctx));
492                 UNEXPECTED_ERROR(__FILE__, __LINE__,
493                                  "isc_mutex_init() failed: %s",
494                                  isc_result_totext(result));
495                 return (ISC_R_UNEXPECTED);
496         }
497
498         lctx->inc = NULL;
499         result = incctx_create(mctx, origin, &lctx->inc);
500         if (result != ISC_R_SUCCESS) 
501                 goto cleanup_ctx;
502
503         if (lex != NULL) {
504                 lctx->lex = lex;
505                 lctx->keep_lex = ISC_TRUE;
506         } else {
507                 lctx->lex = NULL;
508                 result = isc_lex_create(mctx, TOKENSIZ, &lctx->lex);
509                 if (result != ISC_R_SUCCESS)
510                         goto cleanup_inc;
511                 lctx->keep_lex = ISC_FALSE;
512                 memset(specials, 0, sizeof(specials));
513                 specials['('] = 1;
514                 specials[')'] = 1;
515                 specials['"'] = 1;
516                 isc_lex_setspecials(lctx->lex, specials);
517                 isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE);
518         }
519
520         lctx->ttl_known = ISC_FALSE;
521         lctx->ttl = 0;
522         lctx->default_ttl_known = ISC_FALSE;
523         lctx->default_ttl = 0;
524         lctx->warn_1035 = ISC_TRUE;     /* XXX Argument? */
525         lctx->warn_tcr = ISC_TRUE;      /* XXX Argument? */
526         lctx->warn_sigexpired = ISC_TRUE;       /* XXX Argument? */
527         lctx->options = options;
528         lctx->seen_include = ISC_FALSE;
529         lctx->zclass = zclass;
530         lctx->result = ISC_R_SUCCESS;
531
532         dns_fixedname_init(&lctx->fixed_top);
533         lctx->top = dns_fixedname_name(&lctx->fixed_top);
534         dns_name_toregion(top, &r);
535         dns_name_fromregion(lctx->top, &r);
536
537         lctx->loop_cnt = (done != NULL) ? 100 : 0;
538         lctx->callbacks = callbacks;
539         lctx->task = NULL;
540         if (task != NULL)
541                 isc_task_attach(task, &lctx->task);
542         lctx->done = done;
543         lctx->done_arg = done_arg;
544         lctx->canceled = ISC_FALSE;
545         lctx->mctx = NULL;
546         isc_mem_attach(mctx, &lctx->mctx);
547         lctx->references = 1;                   /* Implicit attach. */
548         lctx->magic = DNS_LCTX_MAGIC;
549         *lctxp = lctx;
550         return (ISC_R_SUCCESS);
551
552  cleanup_inc:
553         incctx_destroy(mctx, lctx->inc);
554  cleanup_ctx:
555         isc_mem_put(mctx, lctx, sizeof(*lctx));
556         return (result);
557 }
558
559 static isc_result_t
560 genname(char *name, int it, char *buffer, size_t length) {
561         char fmt[sizeof("%04000000000d")];
562         char numbuf[128];
563         char *cp;
564         char mode[2];
565         int delta = 0;
566         isc_textregion_t r;
567         unsigned int n;
568         unsigned int width;
569
570         r.base = buffer;
571         r.length = length;
572
573         while (*name != '\0') {
574                 if (*name == '$') {
575                         name++;
576                         if (*name == '$') {
577                                 if (r.length == 0)
578                                         return (ISC_R_NOSPACE);
579                                 r.base[0] = *name++;
580                                 isc_textregion_consume(&r, 1);
581                                 continue;
582                         }
583                         strcpy(fmt, "%d");
584                         /* Get format specifier. */
585                         if (*name == '{' ) {
586                                 n = sscanf(name, "{%d,%u,%1[doxX]}",
587                                            &delta, &width, mode);
588                                 switch (n) {
589                                 case 1:
590                                         break;
591                                 case 2:
592                                         n = snprintf(fmt, sizeof(fmt),
593                                                      "%%0%ud", width);
594                                         break;
595                                 case 3:
596                                         n = snprintf(fmt, sizeof(fmt),
597                                                      "%%0%u%c", width, mode[0]);
598                                         break;
599                                 default:
600                                         return (DNS_R_SYNTAX);
601                                 }
602                                 if (n >= sizeof(fmt))
603                                         return (ISC_R_NOSPACE);
604                                 /* Skip past closing brace. */
605                                 while (*name != '\0' && *name++ != '}')
606                                         continue;
607                         }
608                         n = snprintf(numbuf, sizeof(numbuf), fmt, it + delta);
609                         if (n >= sizeof(numbuf))
610                                 return (ISC_R_NOSPACE);
611                         cp = numbuf;
612                         while (*cp != '\0') {
613                                 if (r.length == 0)
614                                         return (ISC_R_NOSPACE);
615                                 r.base[0] = *cp++;
616                                 isc_textregion_consume(&r, 1);
617                         }
618                 } else if (*name == '\\') {
619                         if (r.length == 0)
620                                 return (ISC_R_NOSPACE);
621                         r.base[0] = *name++;
622                         isc_textregion_consume(&r, 1);
623                         if (*name == '\0')
624                                 continue;
625                         if (r.length == 0)
626                                 return (ISC_R_NOSPACE);
627                         r.base[0] = *name++;
628                         isc_textregion_consume(&r, 1);
629                 } else {
630                         if (r.length == 0)
631                                 return (ISC_R_NOSPACE);
632                         r.base[0] = *name++;
633                         isc_textregion_consume(&r, 1);
634                 }
635         }
636         if (r.length == 0)
637                 return (ISC_R_NOSPACE);
638         r.base[0] = '\0';
639         return (ISC_R_SUCCESS);
640 }
641
642 static isc_result_t
643 generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
644          const char *source, unsigned int line)
645 {
646         char *target_mem = NULL;
647         char *lhsbuf = NULL;
648         char *rhsbuf = NULL;
649         dns_fixedname_t ownerfixed;
650         dns_name_t *owner;
651         dns_rdata_t rdata = DNS_RDATA_INIT;
652         dns_rdatacallbacks_t *callbacks;
653         dns_rdatalist_t rdatalist;
654         dns_rdatatype_t type;
655         rdatalist_head_t head;
656         int n;
657         int target_size = MINTSIZ;      /* only one rdata at a time */
658         isc_buffer_t buffer;
659         isc_buffer_t target;
660         isc_result_t result;
661         isc_textregion_t r;
662         unsigned int start, stop, step, i;
663         dns_incctx_t *ictx;
664
665         ictx = lctx->inc;
666         callbacks = lctx->callbacks;
667         dns_fixedname_init(&ownerfixed);
668         owner = dns_fixedname_name(&ownerfixed);
669         ISC_LIST_INIT(head);
670
671         target_mem = isc_mem_get(lctx->mctx, target_size);
672         rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_BUFSZ);
673         lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_BUFSZ);
674         if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) {
675                 result = ISC_R_NOMEMORY;
676                 goto error_cleanup;
677         }
678         isc_buffer_init(&target, target_mem, target_size);
679
680         n = sscanf(range, "%u-%u/%u", &start, &stop, &step);
681         if (n < 2 || stop < start) {
682                (*callbacks->error)(callbacks,
683                                   "%s: %s:%lu: invalid range '%s'",
684                                   "$GENERATE", source, line, range);
685                 result = DNS_R_SYNTAX;
686                 goto insist_cleanup;
687         }
688         if (n == 2)
689                 step = 1;
690
691         /*
692          * Get type.
693          */
694         r.base = gtype;
695         r.length = strlen(gtype);
696         result = dns_rdatatype_fromtext(&type, &r);
697         if (result != ISC_R_SUCCESS) {
698                 (*callbacks->error)(callbacks,
699                                    "%s: %s:%lu: unknown RR type '%s'",
700                                    "$GENERATE", source, line, gtype);
701                 goto insist_cleanup;
702         }
703
704         switch (type) {
705         case dns_rdatatype_ns:
706         case dns_rdatatype_ptr:
707         case dns_rdatatype_cname:
708         case dns_rdatatype_dname:
709                 break;
710
711         case dns_rdatatype_a:
712         case dns_rdatatype_aaaa:
713                 if (lctx->zclass == dns_rdataclass_in ||
714                     lctx->zclass == dns_rdataclass_hs)
715                         break;
716                 /* FALLTHROUGH */
717         default:
718                (*callbacks->error)(callbacks,
719                                   "%s: %s:%lu: unsupported type '%s'",
720                                   "$GENERATE", source, line, gtype);
721                 result = ISC_R_NOTIMPLEMENTED;
722                 goto error_cleanup;
723         }
724
725         ISC_LIST_INIT(rdatalist.rdata);
726         ISC_LINK_INIT(&rdatalist, link);
727         for (i = start; i <= stop; i += step) {
728                 result = genname(lhs, i, lhsbuf, DNS_MASTER_BUFSZ);
729                 if (result != ISC_R_SUCCESS)
730                         goto error_cleanup;
731                 result = genname(rhs, i, rhsbuf, DNS_MASTER_BUFSZ);
732                 if (result != ISC_R_SUCCESS)
733                         goto error_cleanup;
734
735                 isc_buffer_init(&buffer, lhsbuf, strlen(lhsbuf));
736                 isc_buffer_add(&buffer, strlen(lhsbuf));
737                 isc_buffer_setactive(&buffer, strlen(lhsbuf));
738                 result = dns_name_fromtext(owner, &buffer, ictx->origin,
739                                            0, NULL);
740                 if (result != ISC_R_SUCCESS)
741                         goto error_cleanup;
742
743                 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
744                     (lctx->options & DNS_MASTER_SLAVE) == 0 &&
745                     !dns_name_issubdomain(owner, lctx->top))
746                 {
747                         char namebuf[DNS_NAME_FORMATSIZE];
748                         dns_name_format(owner, namebuf, sizeof(namebuf));
749                         /*
750                          * Ignore out-of-zone data.
751                          */
752                         (*callbacks->warn)(callbacks,
753                                            "%s:%lu: "
754                                            "ignoring out-of-zone data (%s)",
755                                            source, line, namebuf);
756                         continue;
757                 }
758
759                 isc_buffer_init(&buffer, rhsbuf, strlen(rhsbuf));
760                 isc_buffer_add(&buffer, strlen(rhsbuf));
761                 isc_buffer_setactive(&buffer, strlen(rhsbuf));
762
763                 result = isc_lex_openbuffer(lctx->lex, &buffer);
764                 if (result != ISC_R_SUCCESS)
765                         goto error_cleanup;
766
767                 isc_buffer_init(&target, target_mem, target_size);
768                 result = dns_rdata_fromtext(&rdata, lctx->zclass, type,
769                                             lctx->lex, ictx->origin, 0,
770                                             lctx->mctx, &target, callbacks);
771                 RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
772                 if (result != ISC_R_SUCCESS)
773                         goto error_cleanup;
774
775                 rdatalist.type = type;
776                 rdatalist.covers = 0;
777                 rdatalist.rdclass = lctx->zclass;
778                 rdatalist.ttl = lctx->ttl;
779                 ISC_LIST_PREPEND(head, &rdatalist, link);
780                 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
781                 result = commit(callbacks, lctx, &head, owner, source, line);
782                 ISC_LIST_UNLINK(rdatalist.rdata, &rdata, link);
783                 if (result != ISC_R_SUCCESS)
784                         goto error_cleanup;
785                 dns_rdata_reset(&rdata);
786         }
787         result = ISC_R_SUCCESS;
788         goto cleanup;
789
790  error_cleanup:
791         if (result == ISC_R_NOMEMORY)
792                 (*callbacks->error)(callbacks, "$GENERATE: %s",
793                                     dns_result_totext(result));
794         else
795                 (*callbacks->error)(callbacks, "$GENERATE: %s:%lu: %s",
796                                     source, line, dns_result_totext(result));
797
798  insist_cleanup:
799         INSIST(result != ISC_R_SUCCESS);
800
801  cleanup:
802         if (target_mem != NULL)
803                 isc_mem_put(lctx->mctx, target_mem, target_size);
804         if (lhsbuf != NULL)
805                 isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_BUFSZ);
806         if (rhsbuf != NULL)
807                 isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_BUFSZ);
808         return (result);
809 }
810
811 static void
812 limit_ttl(dns_rdatacallbacks_t *callbacks, const char *source, unsigned int line,
813           isc_uint32_t *ttlp)
814 {
815         if (*ttlp > 0x7fffffffUL) {
816                 (callbacks->warn)(callbacks,
817                                   "%s: %s:%lu: "
818                                   "$TTL %lu > MAXTTL, "
819                                   "setting $TTL to 0",
820                                   "dns_master_load",
821                                   source, line,
822                                   *ttlp);
823                 *ttlp = 0;
824         }
825 }
826
827 static isc_result_t
828 check_ns(dns_loadctx_t *lctx, isc_token_t *token, const char *source,
829          unsigned long line)
830 {
831         char *tmp = NULL;
832         isc_result_t result = ISC_R_SUCCESS;
833         void (*callback)(struct dns_rdatacallbacks *, const char *, ...);
834
835         if ((lctx->options & DNS_MASTER_FATALNS) != 0)
836                 callback = lctx->callbacks->error;
837         else
838                 callback = lctx->callbacks->warn;
839                 
840         if (token->type == isc_tokentype_string) {
841                 struct in_addr addr;
842                 struct in6_addr addr6;
843
844                 tmp = isc_mem_strdup(lctx->mctx, DNS_AS_STR(*token));
845                 if (tmp == NULL)
846                         return (ISC_R_NOMEMORY);
847                 /*
848                  * Catch both "1.2.3.4" and "1.2.3.4."
849                  */
850                 if (tmp[strlen(tmp) - 1] == '.')
851                         tmp[strlen(tmp) - 1] = '\0';
852                 if (inet_aton(tmp, &addr) == 1 ||
853                     inet_pton(AF_INET6, tmp, &addr6) == 1)
854                         result = DNS_R_NSISADDRESS;
855         }
856         if (result != ISC_R_SUCCESS)
857                 (*callback)(lctx->callbacks, "%s:%lu: NS record '%s' "
858                             "appears to be an address",
859                             source, line, DNS_AS_STR(*token));
860         if (tmp != NULL)
861                 isc_mem_free(lctx->mctx, tmp);
862         return (result);
863 }
864
865 static isc_result_t
866 load(dns_loadctx_t *lctx) {
867         dns_rdataclass_t rdclass;
868         dns_rdatatype_t type, covers;
869         isc_uint32_t ttl_offset = 0;
870         dns_name_t *new_name;
871         isc_boolean_t current_has_delegation = ISC_FALSE;
872         isc_boolean_t done = ISC_FALSE;
873         isc_boolean_t finish_origin = ISC_FALSE;
874         isc_boolean_t finish_include = ISC_FALSE;
875         isc_boolean_t read_till_eol = ISC_FALSE;
876         isc_boolean_t initialws;
877         char *include_file = NULL;
878         isc_token_t token;
879         isc_result_t result = ISC_R_UNEXPECTED;
880         rdatalist_head_t glue_list;
881         rdatalist_head_t current_list;
882         dns_rdatalist_t *this;
883         dns_rdatalist_t *rdatalist = NULL;
884         dns_rdatalist_t *new_rdatalist;
885         int rdlcount = 0;
886         int rdlcount_save = 0;
887         int rdatalist_size = 0;
888         isc_buffer_t buffer;
889         isc_buffer_t target;
890         isc_buffer_t target_ft;
891         isc_buffer_t target_save;
892         dns_rdata_t *rdata = NULL;
893         dns_rdata_t *new_rdata;
894         int rdcount = 0;
895         int rdcount_save = 0;
896         int rdata_size = 0;
897         unsigned char *target_mem = NULL;
898         int target_size = TSIZ;
899         int new_in_use;
900         unsigned int loop_cnt = 0;
901         isc_mem_t *mctx;
902         dns_rdatacallbacks_t *callbacks;
903         dns_incctx_t *ictx;
904         char *range = NULL;
905         char *lhs = NULL;
906         char *gtype = NULL;
907         char *rhs = NULL;
908         const char *source = "";
909         unsigned long line = 0;
910         isc_boolean_t explicit_ttl;
911         isc_stdtime_t now;
912         char classname1[DNS_RDATACLASS_FORMATSIZE];
913         char classname2[DNS_RDATACLASS_FORMATSIZE];
914         unsigned int options = 0;
915
916         REQUIRE(DNS_LCTX_VALID(lctx));
917         callbacks = lctx->callbacks;
918         mctx = lctx->mctx;
919         ictx = lctx->inc;
920
921         ISC_LIST_INIT(glue_list);
922         ISC_LIST_INIT(current_list);
923
924         isc_stdtime_get(&now);
925
926         /*
927          * Allocate target_size of buffer space.  This is greater than twice
928          * the maximum individual RR data size.
929          */
930         target_mem = isc_mem_get(mctx, target_size);
931         if (target_mem == NULL) {
932                 result = ISC_R_NOMEMORY;
933                 goto log_and_cleanup;
934         }
935         isc_buffer_init(&target, target_mem, target_size);
936         target_save = target;
937
938         if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0)
939                 options |= DNS_RDATA_CHECKNAMES;
940         if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0)
941                 options |= DNS_RDATA_CHECKNAMESFAIL;
942         source = isc_lex_getsourcename(lctx->lex);
943         do {
944                 initialws = ISC_FALSE;
945                 line = isc_lex_getsourceline(lctx->lex);
946                 GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS, &token, ISC_TRUE);
947                 line = isc_lex_getsourceline(lctx->lex);
948
949                 if (token.type == isc_tokentype_eof) {
950                         if (read_till_eol)
951                                 WARNUNEXPECTEDEOF(lctx->lex);
952                         /* Pop the include stack? */
953                         if (ictx->parent != NULL) {
954                                 COMMITALL;
955                                 lctx->inc = ictx->parent;
956                                 ictx->parent = NULL;
957                                 incctx_destroy(lctx->mctx, ictx);
958                                 RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
959                                 line = isc_lex_getsourceline(lctx->lex);
960                                 source = isc_lex_getsourcename(lctx->lex);
961                                 ictx = lctx->inc;
962                                 EXPECTEOL;
963                                 continue;
964                         }
965                         done = ISC_TRUE;
966                         continue;
967                 }
968
969                 if (token.type == isc_tokentype_eol) {
970                         read_till_eol = ISC_FALSE;
971                         continue;               /* blank line */
972                 }
973
974                 if (read_till_eol)
975                         continue;
976
977                 if (token.type == isc_tokentype_initialws) {
978                         /*
979                          * Still working on the same name.
980                          */
981                         initialws = ISC_TRUE;
982                 } else if (token.type == isc_tokentype_string) {
983
984                         /*
985                          * "$" Support.
986                          *
987                          * "$ORIGIN" and "$INCLUDE" can both take domain names.
988                          * The processing of "$ORIGIN" and "$INCLUDE" extends
989                          * across the normal domain name processing.
990                          */
991
992                         if (strcasecmp(DNS_AS_STR(token), "$ORIGIN") == 0) {
993                                 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
994                                 finish_origin = ISC_TRUE;
995                         } else if (strcasecmp(DNS_AS_STR(token),
996                                               "$TTL") == 0) {
997                                 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
998                                 result =
999                                    dns_ttl_fromtext(&token.value.as_textregion,
1000                                                     &lctx->ttl);
1001                                 if (MANYERRS(lctx, result)) {
1002                                         SETRESULT(lctx, result);
1003                                         lctx->ttl = 0;
1004                                 } else if (result != ISC_R_SUCCESS)
1005                                         goto insist_and_cleanup;
1006                                 limit_ttl(callbacks, source, line, &lctx->ttl);
1007                                 lctx->default_ttl = lctx->ttl;
1008                                 lctx->default_ttl_known = ISC_TRUE;
1009                                 EXPECTEOL;
1010                                 continue;
1011                         } else if (strcasecmp(DNS_AS_STR(token),
1012                                               "$INCLUDE") == 0) {
1013                                 COMMITALL;
1014                                 if ((lctx->options & DNS_MASTER_NOINCLUDE)
1015                                     != 0)
1016                                 {
1017                                         (callbacks->error)(callbacks,
1018                                            "%s: %s:%lu: $INCLUDE not allowed",
1019                                            "dns_master_load",
1020                                            source, line);
1021                                         result = DNS_R_REFUSED;
1022                                         goto insist_and_cleanup;
1023                                 }
1024                                 if (ttl_offset != 0) {
1025                                         (callbacks->error)(callbacks,
1026                                            "%s: %s:%lu: $INCLUDE "
1027                                            "may not be used with $DATE",
1028                                            "dns_master_load",
1029                                            source, line);
1030                                         result = DNS_R_SYNTAX;
1031                                         goto insist_and_cleanup;
1032                                 }
1033                                 GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
1034                                          ISC_FALSE);
1035                                 if (include_file != NULL)
1036                                         isc_mem_free(mctx, include_file);
1037                                 include_file = isc_mem_strdup(mctx,
1038                                                            DNS_AS_STR(token));
1039                                 if (include_file == NULL) {
1040                                         result = ISC_R_NOMEMORY;
1041                                         goto log_and_cleanup;
1042                                 }
1043                                 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE);
1044
1045                                 if (token.type == isc_tokentype_eol ||
1046                                     token.type == isc_tokentype_eof) {
1047                                         if (token.type == isc_tokentype_eof)
1048                                                 WARNUNEXPECTEDEOF(lctx->lex);
1049                                         isc_lex_ungettoken(lctx->lex, &token);
1050                                         /*
1051                                          * No origin field.
1052                                          */
1053                                         result = pushfile(include_file,
1054                                                           ictx->origin, lctx);
1055                                         if (MANYERRS(lctx, result)) {
1056                                                 SETRESULT(lctx, result);
1057                                                 LOGITFILE(result, include_file);
1058                                                 continue;
1059                                         } else if (result != ISC_R_SUCCESS) {
1060                                                 LOGITFILE(result, include_file);
1061                                                 goto insist_and_cleanup;
1062                                         }
1063                                         ictx = lctx->inc;
1064                                         line = isc_lex_getsourceline(lctx->lex);
1065                                         source =
1066                                                isc_lex_getsourcename(lctx->lex);
1067                                         continue;
1068                                 }
1069                                 /*
1070                                  * There is an origin field.  Fall through
1071                                  * to domain name processing code and do
1072                                  * the actual inclusion later.
1073                                  */
1074                                 finish_include = ISC_TRUE;
1075                         } else if (strcasecmp(DNS_AS_STR(token),
1076                                               "$DATE") == 0) {
1077                                 isc_int64_t dump_time64;
1078                                 isc_stdtime_t dump_time, current_time;
1079                                 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1080                                 isc_stdtime_get(&current_time);
1081                                 result = dns_time64_fromtext(DNS_AS_STR(token),
1082                                                              &dump_time64);
1083                                 if (MANYERRS(lctx, result)) {
1084                                         SETRESULT(lctx, result);
1085                                         LOGIT(result);
1086                                         dump_time64 = 0;
1087                                 } else if (result != ISC_R_SUCCESS)
1088                                         goto log_and_cleanup;
1089                                 dump_time = (isc_stdtime_t)dump_time64;
1090                                 if (dump_time != dump_time64) {
1091                                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1092                                          "%s: %s:%lu: $DATE outside epoch",
1093                                          "dns_master_load", source, line);
1094                                         result = ISC_R_UNEXPECTED;
1095                                         goto insist_and_cleanup;
1096                                 }
1097                                 if (dump_time > current_time) {
1098                                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1099                                         "%s: %s:%lu: "
1100                                         "$DATE in future, using current date",
1101                                         "dns_master_load", source, line);
1102                                         dump_time = current_time;
1103                                 }
1104                                 ttl_offset = current_time - dump_time;
1105                                 EXPECTEOL;
1106                                 continue;
1107                         } else if (strcasecmp(DNS_AS_STR(token),
1108                                               "$GENERATE") == 0) {
1109                                 /*
1110                                  * Lazy cleanup.
1111                                  */
1112                                 if (range != NULL)
1113                                         isc_mem_free(mctx, range);
1114                                 if (lhs != NULL)
1115                                         isc_mem_free(mctx, lhs);
1116                                 if (gtype != NULL)
1117                                         isc_mem_free(mctx, gtype);
1118                                 if (rhs != NULL)
1119                                         isc_mem_free(mctx, rhs);
1120                                 /* RANGE */
1121                                 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1122                                 range = isc_mem_strdup(mctx,
1123                                                      DNS_AS_STR(token));
1124                                 if (range == NULL) {
1125                                         result = ISC_R_NOMEMORY;
1126                                         goto log_and_cleanup;
1127                                 }
1128                                 /* LHS */
1129                                 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1130                                 lhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1131                                 if (lhs == NULL) {
1132                                         result = ISC_R_NOMEMORY;
1133                                         goto log_and_cleanup;
1134                                 }
1135                                 rdclass = 0;
1136                                 explicit_ttl = ISC_FALSE;
1137                                 /* CLASS? */
1138                                 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1139                                 if (dns_rdataclass_fromtext(&rdclass,
1140                                             &token.value.as_textregion)
1141                                                 == ISC_R_SUCCESS) {
1142                                         GETTOKEN(lctx->lex, 0, &token,
1143                                                  ISC_FALSE);
1144                                 }
1145                                 /* TTL? */
1146                                 if (dns_ttl_fromtext(&token.value.as_textregion,
1147                                                      &lctx->ttl)
1148                                                 == ISC_R_SUCCESS) {
1149                                         limit_ttl(callbacks, source, line,
1150                                                   &lctx->ttl);
1151                                         lctx->ttl_known = ISC_TRUE;
1152                                         explicit_ttl = ISC_TRUE;
1153                                         GETTOKEN(lctx->lex, 0, &token,
1154                                                  ISC_FALSE);
1155                                 }
1156                                 /* CLASS? */
1157                                 if (rdclass == 0 &&
1158                                     dns_rdataclass_fromtext(&rdclass,
1159                                                     &token.value.as_textregion)
1160                                                 == ISC_R_SUCCESS)
1161                                         GETTOKEN(lctx->lex, 0, &token,
1162                                                  ISC_FALSE);
1163                                 /* TYPE */
1164                                 gtype = isc_mem_strdup(mctx,
1165                                                        DNS_AS_STR(token));
1166                                 if (gtype == NULL) {
1167                                         result = ISC_R_NOMEMORY;
1168                                         goto log_and_cleanup;
1169                                 }
1170                                 /* RHS */
1171                                 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1172                                 rhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1173                                 if (rhs == NULL) {
1174                                         result = ISC_R_NOMEMORY;
1175                                         goto log_and_cleanup;
1176                                 }
1177                                 if (!lctx->ttl_known &&
1178                                     !lctx->default_ttl_known) {
1179                                         (*callbacks->error)(callbacks,
1180                                             "%s: %s:%lu: no TTL specified",
1181                                             "dns_master_load", source, line);
1182                                         result = DNS_R_NOTTL;
1183                                         if (MANYERRS(lctx, result)) {
1184                                                 SETRESULT(lctx, result);
1185                                                 lctx->ttl = 0;
1186                                         } else if (result != ISC_R_SUCCESS)
1187                                                 goto insist_and_cleanup;
1188                                 } else if (!explicit_ttl &&
1189                                            lctx->default_ttl_known) {
1190                                         lctx->ttl = lctx->default_ttl;
1191                                 }
1192                                 /*
1193                                  * If the class specified does not match the
1194                                  * zone's class print out a error message and
1195                                  * exit.
1196                                  */
1197                                 if (rdclass != 0 && rdclass != lctx->zclass) {
1198                                         goto bad_class;
1199                                 }
1200                                 result = generate(lctx, range, lhs, gtype, rhs,
1201                                                   source, line);
1202                                 if (MANYERRS(lctx, result)) {
1203                                         SETRESULT(lctx, result);
1204                                 } else if (result != ISC_R_SUCCESS)
1205                                         goto insist_and_cleanup;
1206                                 EXPECTEOL;
1207                                 continue;
1208                         } else if (strncasecmp(DNS_AS_STR(token),
1209                                                "$", 1) == 0) {
1210                                 (callbacks->error)(callbacks,
1211                                            "%s: %s:%lu: "
1212                                            "unknown $ directive '%s'",
1213                                            "dns_master_load", source, line,
1214                                            DNS_AS_STR(token));
1215                                 result = DNS_R_SYNTAX;
1216                                 if (MANYERRS(lctx, result)) {
1217                                         SETRESULT(lctx, result);
1218                                 } else if (result != ISC_R_SUCCESS)
1219                                         goto insist_and_cleanup;
1220                         }
1221
1222                         /*
1223                          * Normal processing resumes.
1224                          *
1225                          * Find a free name buffer.
1226                          */
1227                         for (new_in_use = 0; new_in_use < NBUFS; new_in_use++)
1228                                 if (!ictx->in_use[new_in_use])
1229                                         break;
1230                         INSIST(new_in_use < NBUFS);
1231                         dns_fixedname_init(&ictx->fixed[new_in_use]);
1232                         new_name = dns_fixedname_name(&ictx->fixed[new_in_use]);
1233                         isc_buffer_init(&buffer, token.value.as_region.base,
1234                                         token.value.as_region.length);
1235                         isc_buffer_add(&buffer, token.value.as_region.length);
1236                         isc_buffer_setactive(&buffer,
1237                                              token.value.as_region.length);
1238                         result = dns_name_fromtext(new_name, &buffer,
1239                                           ictx->origin, ISC_FALSE, NULL);
1240                         if (MANYERRS(lctx, result)) {
1241                                 SETRESULT(lctx, result);
1242                                 LOGIT(result);
1243                                 read_till_eol = ISC_TRUE;
1244                                 continue;
1245                         } else if (result != ISC_R_SUCCESS)
1246                                 goto log_and_cleanup;
1247
1248                         /*
1249                          * Finish $ORIGIN / $INCLUDE processing if required.
1250                          */
1251                         if (finish_origin) {
1252                                 if (ictx->origin_in_use != -1)
1253                                         ictx->in_use[ictx->origin_in_use] =
1254                                                 ISC_FALSE;
1255                                 ictx->origin_in_use = new_in_use;
1256                                 ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
1257                                 ictx->origin = new_name;
1258                                 finish_origin = ISC_FALSE;
1259                                 EXPECTEOL;
1260                                 continue;
1261                         }
1262                         if (finish_include) {
1263                                 finish_include = ISC_FALSE;
1264                                 result = pushfile(include_file, new_name, lctx);
1265                                 if (MANYERRS(lctx, result)) {
1266                                         SETRESULT(lctx, result);
1267                                         LOGITFILE(result, include_file);
1268                                         continue;
1269                                 } else if (result != ISC_R_SUCCESS) {
1270                                         LOGITFILE(result, include_file);
1271                                         goto insist_and_cleanup;
1272                                 }
1273                                 ictx = lctx->inc;
1274                                 line = isc_lex_getsourceline(lctx->lex);
1275                                 source = isc_lex_getsourcename(lctx->lex);
1276                                 continue;
1277                         }
1278
1279                         /*
1280                          * "$" Processing Finished
1281                          */
1282
1283                         /*
1284                          * If we are processing glue and the new name does
1285                          * not match the current glue name, commit the glue
1286                          * and pop stacks leaving us in 'normal' processing
1287                          * state.  Linked lists are undone by commit().
1288                          */
1289                         if (ictx->glue != NULL &&
1290                             dns_name_compare(ictx->glue, new_name) != 0) {
1291                                 result = commit(callbacks, lctx, &glue_list,
1292                                                 ictx->glue, source,
1293                                                 ictx->glue_line);
1294                                 if (MANYERRS(lctx, result)) {
1295                                         SETRESULT(lctx, result);
1296                                 } else if (result != ISC_R_SUCCESS)
1297                                         goto insist_and_cleanup;
1298                                 if (ictx->glue_in_use != -1)
1299                                         ictx->in_use[ictx->glue_in_use] =
1300                                                 ISC_FALSE;
1301                                 ictx->glue_in_use = -1;
1302                                 ictx->glue = NULL;
1303                                 rdcount = rdcount_save;
1304                                 rdlcount = rdlcount_save;
1305                                 target = target_save;
1306                         }
1307
1308                         /*
1309                          * If we are in 'normal' processing state and the new
1310                          * name does not match the current name, see if the
1311                          * new name is for glue and treat it as such,
1312                          * otherwise we have a new name so commit what we
1313                          * have.
1314                          */
1315                         if ((ictx->glue == NULL) && (ictx->current == NULL ||
1316                             dns_name_compare(ictx->current, new_name) != 0)) {
1317                                 if (current_has_delegation &&
1318                                         is_glue(&current_list, new_name)) {
1319                                         rdcount_save = rdcount;
1320                                         rdlcount_save = rdlcount;
1321                                         target_save = target;
1322                                         ictx->glue = new_name;
1323                                         ictx->glue_in_use = new_in_use;
1324                                         ictx->in_use[ictx->glue_in_use] = 
1325                                                 ISC_TRUE;
1326                                 } else {
1327                                         result = commit(callbacks, lctx,
1328                                                         &current_list,
1329                                                         ictx->current,
1330                                                         source,
1331                                                         ictx->current_line);
1332                                         if (MANYERRS(lctx, result)) {
1333                                                 SETRESULT(lctx, result);
1334                                         } else if (result != ISC_R_SUCCESS)
1335                                                 goto insist_and_cleanup;
1336                                         rdcount = 0;
1337                                         rdlcount = 0;
1338                                         if (ictx->current_in_use != -1)
1339                                             ictx->in_use[ictx->current_in_use] =
1340                                                 ISC_FALSE;
1341                                         ictx->current_in_use = new_in_use;
1342                                         ictx->in_use[ictx->current_in_use] =
1343                                                 ISC_TRUE;
1344                                         ictx->current = new_name;
1345                                         current_has_delegation = ISC_FALSE;
1346                                         isc_buffer_init(&target, target_mem,
1347                                                         target_size);
1348                                 }
1349                         }
1350                         if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
1351                             (lctx->options & DNS_MASTER_SLAVE) == 0 &&
1352                             !dns_name_issubdomain(new_name, lctx->top))
1353                         {
1354                                 char namebuf[DNS_NAME_FORMATSIZE];
1355                                 dns_name_format(new_name, namebuf,
1356                                                 sizeof(namebuf));
1357                                 /*
1358                                  * Ignore out-of-zone data.
1359                                  */
1360                                 (*callbacks->warn)(callbacks,
1361                                        "%s:%lu: "
1362                                        "ignoring out-of-zone data (%s)",
1363                                        source, line, namebuf);
1364                                 ictx->drop = ISC_TRUE;
1365                         } else
1366                                 ictx->drop = ISC_FALSE;
1367                 } else {
1368                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1369                                          "%s:%lu: isc_lex_gettoken() returned "
1370                                          "unexpeced token type (%d)",
1371                                          source, line, token.type);
1372                         result = ISC_R_UNEXPECTED;
1373                         if (MANYERRS(lctx, result)) {
1374                                 SETRESULT(lctx, result);
1375                                 LOGIT(result);
1376                                 continue;
1377                         } else if (result != ISC_R_SUCCESS)
1378                                 goto insist_and_cleanup;
1379                 }
1380
1381                 /*
1382                  * Find TTL, class and type.  Both TTL and class are optional
1383                  * and may occur in any order if they exist. TTL and class
1384                  * come before type which must exist.
1385                  *
1386                  * [<TTL>] [<class>] <type> <RDATA>
1387                  * [<class>] [<TTL>] <type> <RDATA>
1388                  */
1389
1390                 type = 0;
1391                 rdclass = 0;
1392
1393                 GETTOKEN(lctx->lex, 0, &token, initialws);
1394
1395                 if (initialws) {
1396                         if (token.type == isc_tokentype_eol) {
1397                                 read_till_eol = ISC_FALSE;
1398                                 continue;               /* blank line */
1399                         }
1400
1401                         if (token.type == isc_tokentype_eof) {
1402                                 WARNUNEXPECTEDEOF(lctx->lex);
1403                                 read_till_eol = ISC_FALSE;
1404                                 isc_lex_ungettoken(lctx->lex, &token);
1405                                 continue;
1406                         }
1407
1408                         if (ictx->current == NULL) {
1409                                 (*callbacks->error)(callbacks,
1410                                         "%s:%lu: no current owner name",
1411                                         source, line);
1412                                 result = DNS_R_NOOWNER;
1413                                 if (MANYERRS(lctx, result)) {
1414                                         SETRESULT(lctx, result);
1415                                         read_till_eol = ISC_TRUE;
1416                                         continue;
1417                                 } else if (result != ISC_R_SUCCESS)
1418                                         goto insist_and_cleanup;
1419                         }
1420                 }
1421
1422                 if (dns_rdataclass_fromtext(&rdclass,
1423                                             &token.value.as_textregion)
1424                                 == ISC_R_SUCCESS)
1425                         GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1426
1427                 explicit_ttl = ISC_FALSE;
1428                 if (dns_ttl_fromtext(&token.value.as_textregion, &lctx->ttl)
1429                                 == ISC_R_SUCCESS) {
1430                         limit_ttl(callbacks, source, line, &lctx->ttl);
1431                         explicit_ttl = ISC_TRUE;
1432                         lctx->ttl_known = ISC_TRUE;
1433                         GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1434                 }
1435
1436                 if (token.type != isc_tokentype_string) {
1437                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1438                         "isc_lex_gettoken() returned unexpected token type");
1439                         result = ISC_R_UNEXPECTED;
1440                         if (MANYERRS(lctx, result)) {
1441                                 SETRESULT(lctx, result);
1442                                 read_till_eol = ISC_TRUE;
1443                                 continue;
1444                         } else if (result != ISC_R_SUCCESS)
1445                                 goto insist_and_cleanup;
1446                 }
1447
1448                 if (rdclass == 0 &&
1449                     dns_rdataclass_fromtext(&rdclass,
1450                                             &token.value.as_textregion)
1451                                 == ISC_R_SUCCESS)
1452                         GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1453
1454                 if (token.type != isc_tokentype_string) {
1455                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1456                         "isc_lex_gettoken() returned unexpected token type");
1457                         result = ISC_R_UNEXPECTED;
1458                         if (MANYERRS(lctx, result)) {
1459                                 SETRESULT(lctx, result);
1460                                 read_till_eol = ISC_TRUE;
1461                                 continue;
1462                         } else if (result != ISC_R_SUCCESS)
1463                                 goto insist_and_cleanup;
1464                 }
1465
1466                 result = dns_rdatatype_fromtext(&type,
1467                                                 &token.value.as_textregion);
1468                 if (result != ISC_R_SUCCESS) {
1469                         (*callbacks->warn)(callbacks,
1470                                    "%s:%lu: unknown RR type '%.*s'",
1471                                    source, line,
1472                                    token.value.as_textregion.length,
1473                                    token.value.as_textregion.base);
1474                         if (MANYERRS(lctx, result)) {
1475                                 SETRESULT(lctx, result);
1476                                 read_till_eol = ISC_TRUE;
1477                                 continue;
1478                         } else if (result != ISC_R_SUCCESS)
1479                                 goto insist_and_cleanup;
1480                 }
1481
1482                 /*
1483                  * If the class specified does not match the zone's class
1484                  * print out a error message and exit.
1485                  */
1486                 if (rdclass != 0 && rdclass != lctx->zclass) {
1487   bad_class:
1488
1489                         dns_rdataclass_format(rdclass, classname1,
1490                                               sizeof(classname1));
1491                         dns_rdataclass_format(lctx->zclass, classname2,
1492                                               sizeof(classname2));
1493                         (*callbacks->error)(callbacks,
1494                                             "%s:%lu: class '%s' != "
1495                                             "zone class '%s'",
1496                                             source, line,
1497                                             classname1, classname2);
1498                         result = DNS_R_BADCLASS;
1499                         if (MANYERRS(lctx, result)) {
1500                                 SETRESULT(lctx, result);
1501                                 read_till_eol = ISC_TRUE;
1502                                 continue;
1503                         } else if (result != ISC_R_SUCCESS)
1504                                 goto insist_and_cleanup;
1505                 }
1506
1507                 if (type == dns_rdatatype_ns && ictx->glue == NULL)
1508                         current_has_delegation = ISC_TRUE;
1509
1510                 /*
1511                  * RFC 1123: MD and MF are not allowed to be loaded from
1512                  * master files.
1513                  */
1514                 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
1515                     (lctx->options & DNS_MASTER_SLAVE) == 0 &&
1516                     (type == dns_rdatatype_md || type == dns_rdatatype_mf)) {
1517                         char typename[DNS_RDATATYPE_FORMATSIZE];
1518
1519                         result = DNS_R_OBSOLETE;
1520
1521                         dns_rdatatype_format(type, typename, sizeof(typename));
1522                         (*callbacks->error)(callbacks,
1523                                             "%s:%lu: %s '%s': %s",
1524                                             source, line,
1525                                             "type", typename,
1526                                             dns_result_totext(result));
1527                         if (MANYERRS(lctx, result)) {
1528                                 SETRESULT(lctx, result);
1529                         } else
1530                                 goto insist_and_cleanup;
1531                 }
1532
1533                 /*
1534                  * Find a rdata structure.
1535                  */
1536                 if (rdcount == rdata_size) {
1537                         new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
1538                                                rdata_size, &current_list,
1539                                                &glue_list, mctx);
1540                         if (new_rdata == NULL) {
1541                                 result = ISC_R_NOMEMORY;
1542                                 goto log_and_cleanup;
1543                         }
1544                         rdata_size += RDSZ;
1545                         rdata = new_rdata;
1546                 }
1547
1548                 /*
1549                  * Peek at the NS record.
1550                  */
1551                 if (type == dns_rdatatype_ns &&
1552                     lctx->zclass == dns_rdataclass_in &&
1553                     (lctx->options & DNS_MASTER_CHECKNS) != 0) {
1554
1555                         GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
1556                         result = check_ns(lctx, &token, source, line);
1557                         isc_lex_ungettoken(lctx->lex, &token);
1558                         if ((lctx->options & DNS_MASTER_FATALNS) != 0) {
1559                                 if (MANYERRS(lctx, result)) {
1560                                         SETRESULT(lctx, result);
1561                                 } else if (result != ISC_R_SUCCESS)
1562                                         goto insist_and_cleanup;
1563                         }
1564                 }
1565
1566                 /*
1567                  * Check owner name.
1568                  */
1569                 options &= ~DNS_RDATA_CHECKREVERSE;
1570                 if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0) {
1571                         isc_boolean_t ok;
1572                         dns_name_t *name;
1573
1574                         name = (ictx->glue != NULL) ? ictx-> glue :
1575                                                       ictx->current;
1576                         ok = dns_rdata_checkowner(name, lctx->zclass, type,
1577                                                   ISC_TRUE);
1578                         if (!ok) {
1579                                 char namebuf[DNS_NAME_FORMATSIZE];
1580                                 const char *desc;
1581                                 dns_name_format(name, namebuf, sizeof(namebuf));
1582                                 result = DNS_R_BADOWNERNAME;
1583                                 desc = dns_result_totext(result);
1584                                 if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0) {
1585                                         (*callbacks->error)(callbacks,
1586                                                             "%s:%lu: %s: %s",
1587                                                             source, line,
1588                                                             namebuf, desc);
1589                                         if (MANYERRS(lctx, result)) {
1590                                                 SETRESULT(lctx, result);
1591                                         } else if (result != ISC_R_SUCCESS)
1592                                                 goto cleanup;
1593                                 } else {
1594                                         (*callbacks->warn)(callbacks,
1595                                                            "%s:%lu: %s: %s",
1596                                                            source, line,
1597                                                            namebuf, desc);
1598                                 }
1599                         }
1600                         if (type == dns_rdatatype_ptr &&
1601                             (dns_name_issubdomain(name, &in_addr_arpa) ||
1602                              dns_name_issubdomain(name, &ip6_arpa) ||
1603                              dns_name_issubdomain(name, &ip6_int)))
1604                                 options |= DNS_RDATA_CHECKREVERSE;
1605                 }
1606
1607                 /*
1608                  * Read rdata contents.
1609                  */
1610                 dns_rdata_init(&rdata[rdcount]);
1611                 target_ft = target;
1612                 result = dns_rdata_fromtext(&rdata[rdcount], lctx->zclass,
1613                                             type, lctx->lex, ictx->origin,
1614                                             options, lctx->mctx, &target,
1615                                             callbacks);
1616                 if (MANYERRS(lctx, result)) {
1617                         SETRESULT(lctx, result);
1618                         continue;
1619                 } else if (result != ISC_R_SUCCESS)
1620                         goto insist_and_cleanup;
1621
1622                 if (ictx->drop) {
1623                         target = target_ft;
1624                         continue;
1625                 }
1626
1627                 if (type == dns_rdatatype_soa &&
1628                     (lctx->options & DNS_MASTER_ZONE) != 0 &&
1629                     dns_name_compare(ictx->current, lctx->top) != 0) {
1630                         char namebuf[DNS_NAME_FORMATSIZE];
1631                         dns_name_format(ictx->current, namebuf,
1632                                         sizeof(namebuf));
1633                         (*callbacks->error)(callbacks,
1634                                             "%s:%lu: SOA "
1635                                             "record not at top of zone (%s)",
1636                                             source, line, namebuf);
1637                         result = DNS_R_NOTZONETOP;
1638                         if (MANYERRS(lctx, result)) {
1639                                 SETRESULT(lctx, result);
1640                                 read_till_eol = ISC_TRUE;
1641                                 target = target_ft;
1642                                 continue;
1643                         } else if (result != ISC_R_SUCCESS)
1644                                 goto insist_and_cleanup;
1645                 }
1646
1647
1648                 if (type == dns_rdatatype_rrsig ||
1649                     type == dns_rdatatype_sig)
1650                         covers = dns_rdata_covers(&rdata[rdcount]);
1651                 else
1652                         covers = 0;
1653
1654                 if (!lctx->ttl_known && !lctx->default_ttl_known) {
1655                         if (type == dns_rdatatype_soa) {
1656                                 (*callbacks->warn)(callbacks,
1657                                                    "%s:%lu: no TTL specified; "
1658                                                    "using SOA MINTTL instead",
1659                                                    source, line);
1660                                 lctx->ttl = dns_soa_getminimum(&rdata[rdcount]);
1661                                 limit_ttl(callbacks, source, line, &lctx->ttl);
1662                                 lctx->default_ttl = lctx->ttl;
1663                                 lctx->default_ttl_known = ISC_TRUE;
1664                         } else if ((lctx->options & DNS_MASTER_HINT) != 0) {
1665                                 /*
1666                                  * Zero TTL's are fine for hints.
1667                                  */
1668                                 lctx->ttl = 0;
1669                                 lctx->default_ttl = lctx->ttl;
1670                                 lctx->default_ttl_known = ISC_TRUE;
1671                         } else {
1672                                 (*callbacks->warn)(callbacks,
1673                                                    "%s:%lu: no TTL specified; "
1674                                                    "zone rejected",
1675                                                    source, line);
1676                                 result = DNS_R_NOTTL;
1677                                 if (MANYERRS(lctx, result)) {
1678                                         SETRESULT(lctx, result);
1679                                         lctx->ttl = 0;
1680                                 } else {
1681                                         goto insist_and_cleanup;
1682                                 }
1683                         }
1684                 } else if (!explicit_ttl && lctx->default_ttl_known) {
1685                         lctx->ttl = lctx->default_ttl;
1686                 } else if (!explicit_ttl && lctx->warn_1035) {
1687                         (*callbacks->warn)(callbacks,
1688                                            "%s:%lu: "
1689                                            "using RFC 1035 TTL semantics",
1690                                            source, line);
1691                         lctx->warn_1035 = ISC_FALSE;
1692                 }
1693
1694                 if (type == dns_rdatatype_rrsig && lctx->warn_sigexpired) {
1695                         dns_rdata_rrsig_t sig;
1696                         (void)dns_rdata_tostruct(&rdata[rdcount], &sig, NULL);
1697                         if (isc_serial_lt(sig.timeexpire, now)) {
1698                                 (*callbacks->warn)(callbacks,
1699                                                    "%s:%lu: "
1700                                                    "signature has expired",
1701                                                    source, line);
1702                                 lctx->warn_sigexpired = ISC_FALSE;
1703                         }
1704                 }
1705
1706                 if ((type == dns_rdatatype_sig || type == dns_rdatatype_nxt) &&
1707                     lctx->warn_tcr && (lctx->options & DNS_MASTER_ZONE) != 0 &&
1708                     (lctx->options & DNS_MASTER_SLAVE) == 0) {
1709                         (*callbacks->warn)(callbacks, "%s:%lu: old style DNSSEC "
1710                                            " zone detected", source, line);
1711                         lctx->warn_tcr = ISC_FALSE;
1712                 }
1713
1714                 if ((lctx->options & DNS_MASTER_AGETTL) != 0) {
1715                         /*
1716                          * Adjust the TTL for $DATE.  If the RR has already
1717                          * expired, ignore it.
1718                          */
1719                         if (lctx->ttl < ttl_offset)
1720                                 continue;
1721                         lctx->ttl -= ttl_offset;
1722                 }
1723
1724                 /*
1725                  * Find type in rdatalist.
1726                  * If it does not exist create new one and prepend to list
1727                  * as this will mimimise list traversal.
1728                  */
1729                 if (ictx->glue != NULL)
1730                         this = ISC_LIST_HEAD(glue_list);
1731                 else
1732                         this = ISC_LIST_HEAD(current_list);
1733
1734                 while (this != NULL) {
1735                         if (this->type == type && this->covers == covers)
1736                                 break;
1737                         this = ISC_LIST_NEXT(this, link);
1738                 }
1739
1740                 if (this == NULL) {
1741                         if (rdlcount == rdatalist_size) {
1742                                 new_rdatalist =
1743                                         grow_rdatalist(rdatalist_size + RDLSZ,
1744                                                        rdatalist,
1745                                                        rdatalist_size,
1746                                                        &current_list,
1747                                                        &glue_list,
1748                                                        mctx);
1749                                 if (new_rdatalist == NULL) {
1750                                         result = ISC_R_NOMEMORY;
1751                                         goto log_and_cleanup;
1752                                 }
1753                                 rdatalist = new_rdatalist;
1754                                 rdatalist_size += RDLSZ;
1755                         }
1756                         this = &rdatalist[rdlcount++];
1757                         this->type = type;
1758                         this->covers = covers;
1759                         this->rdclass = lctx->zclass;
1760                         this->ttl = lctx->ttl;
1761                         ISC_LIST_INIT(this->rdata);
1762                         if (ictx->glue != NULL)
1763                                 ISC_LIST_INITANDPREPEND(glue_list, this, link);
1764                         else
1765                                 ISC_LIST_INITANDPREPEND(current_list, this,
1766                                                         link);
1767                 } else if (this->ttl != lctx->ttl) {
1768                         (*callbacks->warn)(callbacks,
1769                                            "%s:%lu: "
1770                                            "TTL set to prior TTL (%lu)",
1771                                            source, line, this->ttl);
1772                         lctx->ttl = this->ttl;
1773                 }
1774
1775                 ISC_LIST_APPEND(this->rdata, &rdata[rdcount], link);
1776                 if (ictx->glue != NULL) 
1777                         ictx->glue_line = line;
1778                 else
1779                         ictx->current_line = line;
1780                 rdcount++;
1781
1782                 /*
1783                  * We must have at least 64k as rdlen is 16 bits.
1784                  * If we don't commit everything we have so far.
1785                  */
1786                 if ((target.length - target.used) < MINTSIZ)
1787                         COMMITALL;
1788  next_line:
1789                 ;
1790         } while (!done && (lctx->loop_cnt == 0 || loop_cnt++ < lctx->loop_cnt));
1791
1792         /*
1793          * Commit what has not yet been committed.
1794          */
1795         result = commit(callbacks, lctx, &current_list, ictx->current,
1796                         source, ictx->current_line);
1797         if (MANYERRS(lctx, result)) {
1798                 SETRESULT(lctx, result);
1799         } else if (result != ISC_R_SUCCESS)
1800                 goto insist_and_cleanup;
1801         result = commit(callbacks, lctx, &glue_list, ictx->glue,
1802                         source, ictx->glue_line);
1803         if (MANYERRS(lctx, result)) {
1804                 SETRESULT(lctx, result);
1805         } else if (result != ISC_R_SUCCESS)
1806                 goto insist_and_cleanup;
1807
1808         if (!done) {
1809                 INSIST(lctx->done != NULL && lctx->task != NULL);
1810                 result = DNS_R_CONTINUE;
1811         } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) {
1812                 result = lctx->result;
1813         } else if (result == ISC_R_SUCCESS && lctx->seen_include)
1814                 result = DNS_R_SEENINCLUDE;
1815         goto cleanup;
1816
1817  log_and_cleanup:
1818         LOGIT(result);
1819
1820  insist_and_cleanup:
1821         INSIST(result != ISC_R_SUCCESS);
1822
1823  cleanup:
1824         while ((this = ISC_LIST_HEAD(current_list)) != NULL)
1825                 ISC_LIST_UNLINK(current_list, this, link);
1826         while ((this = ISC_LIST_HEAD(glue_list)) != NULL)
1827                 ISC_LIST_UNLINK(glue_list, this, link);
1828         if (rdatalist != NULL)
1829                 isc_mem_put(mctx, rdatalist,
1830                             rdatalist_size * sizeof(*rdatalist));
1831         if (rdata != NULL)
1832                 isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
1833         if (target_mem != NULL)
1834                 isc_mem_put(mctx, target_mem, target_size);
1835         if (include_file != NULL)
1836                 isc_mem_free(mctx, include_file);
1837         if (range != NULL)
1838                 isc_mem_free(mctx, range);
1839         if (lhs != NULL)
1840                 isc_mem_free(mctx, lhs);
1841         if (gtype != NULL)
1842                 isc_mem_free(mctx, gtype);
1843         if (rhs != NULL)
1844                 isc_mem_free(mctx, rhs);
1845         return (result);
1846 }
1847
1848 static isc_result_t
1849 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) {
1850         isc_result_t result;
1851         dns_incctx_t *ictx;
1852         dns_incctx_t *new = NULL;
1853         isc_region_t r;
1854         int new_in_use;
1855
1856         REQUIRE(master_file != NULL);
1857         REQUIRE(DNS_LCTX_VALID(lctx));
1858
1859         ictx = lctx->inc;
1860         lctx->seen_include = ISC_TRUE;
1861
1862         result = incctx_create(lctx->mctx, origin, &new);
1863         if (result != ISC_R_SUCCESS)
1864                 return (result);
1865
1866         /* Set current domain. */
1867         if (ictx->glue != NULL || ictx->current != NULL) {
1868                 for (new_in_use = 0; new_in_use < NBUFS; new_in_use++)
1869                         if (!new->in_use[new_in_use])
1870                                 break;
1871                 INSIST(new_in_use < NBUFS);
1872                 new->current_in_use = new_in_use;
1873                 new->current =
1874                         dns_fixedname_name(&new->fixed[new->current_in_use]);
1875                 new->in_use[new->current_in_use] = ISC_TRUE;
1876                 dns_name_toregion((ictx->glue != NULL) ?
1877                                    ictx->glue : ictx->current, &r);
1878                 dns_name_fromregion(new->current, &r);
1879                 new->drop = ictx->drop;
1880         }
1881
1882         result = isc_lex_openfile(lctx->lex, master_file);
1883         if (result != ISC_R_SUCCESS)
1884                 goto cleanup;
1885         new->parent = ictx;
1886         lctx->inc = new;
1887         return (ISC_R_SUCCESS);
1888
1889  cleanup:
1890         if (new != NULL)
1891                 incctx_destroy(lctx->mctx, new);
1892         return (result);
1893 }
1894
1895 isc_result_t
1896 dns_master_loadfile(const char *master_file, dns_name_t *top,
1897                     dns_name_t *origin,
1898                     dns_rdataclass_t zclass, unsigned int options,
1899                     dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
1900 {
1901         dns_loadctx_t *lctx = NULL;
1902         isc_result_t result;
1903
1904         result = loadctx_create(mctx, options, top, zclass, origin,
1905                                 callbacks, NULL, NULL, NULL, NULL, &lctx);
1906         if (result != ISC_R_SUCCESS)
1907                 return (result);
1908
1909         result = isc_lex_openfile(lctx->lex, master_file);
1910         if (result != ISC_R_SUCCESS)
1911                 goto cleanup;
1912
1913         result = load(lctx);
1914         INSIST(result != DNS_R_CONTINUE);
1915
1916  cleanup:
1917         if (lctx != NULL)
1918                 dns_loadctx_detach(&lctx);
1919         return (result);
1920 }
1921
1922 isc_result_t
1923 dns_master_loadfileinc(const char *master_file, dns_name_t *top,
1924                        dns_name_t *origin, dns_rdataclass_t zclass,
1925                        unsigned int options, dns_rdatacallbacks_t *callbacks,
1926                        isc_task_t *task, dns_loaddonefunc_t done,
1927                        void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx)
1928 {
1929         dns_loadctx_t *lctx = NULL;
1930         isc_result_t result;
1931         
1932         REQUIRE(task != NULL);
1933         REQUIRE(done != NULL);
1934
1935         result = loadctx_create(mctx, options, top, zclass, origin,
1936                                 callbacks, task, done, done_arg, NULL, &lctx);
1937         if (result != ISC_R_SUCCESS)
1938                 return (result);
1939
1940         result = isc_lex_openfile(lctx->lex, master_file);
1941         if (result != ISC_R_SUCCESS)
1942                 goto cleanup;
1943
1944         result = task_send(lctx);
1945         if (result == ISC_R_SUCCESS) {
1946                 dns_loadctx_attach(lctx, lctxp);
1947                 return (DNS_R_CONTINUE);
1948         }
1949
1950  cleanup:
1951         if (lctx != NULL)
1952                 dns_loadctx_detach(&lctx);
1953         return (result);
1954 }
1955
1956 isc_result_t
1957 dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
1958                       dns_rdataclass_t zclass, unsigned int options,
1959                       dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
1960 {
1961         isc_result_t result;
1962         dns_loadctx_t *lctx = NULL;
1963
1964         REQUIRE(stream != NULL);
1965
1966         result = loadctx_create(mctx, options, top, zclass, origin,
1967                                 callbacks, NULL, NULL, NULL, NULL, &lctx);
1968         if (result != ISC_R_SUCCESS)
1969                 goto cleanup;
1970
1971         result = isc_lex_openstream(lctx->lex, stream);
1972         if (result != ISC_R_SUCCESS)
1973                 goto cleanup;
1974
1975         result = load(lctx);
1976         INSIST(result != DNS_R_CONTINUE);
1977
1978  cleanup:
1979         if (lctx != NULL)
1980                 dns_loadctx_detach(&lctx);
1981         return (result);
1982 }
1983
1984 isc_result_t
1985 dns_master_loadstreaminc(FILE *stream, dns_name_t *top, dns_name_t *origin,
1986                          dns_rdataclass_t zclass, unsigned int options,
1987                          dns_rdatacallbacks_t *callbacks, isc_task_t *task,
1988                          dns_loaddonefunc_t done, void *done_arg,
1989                          dns_loadctx_t **lctxp, isc_mem_t *mctx)
1990 {
1991         isc_result_t result;
1992         dns_loadctx_t *lctx = NULL;
1993
1994         REQUIRE(stream != NULL);
1995         REQUIRE(task != NULL);
1996         REQUIRE(done != NULL);
1997
1998         result = loadctx_create(mctx, options, top, zclass, origin,
1999                                 callbacks, task, done, done_arg, NULL, &lctx);
2000         if (result != ISC_R_SUCCESS)
2001                 goto cleanup;
2002
2003         result = isc_lex_openstream(lctx->lex, stream);
2004         if (result != ISC_R_SUCCESS)
2005                 goto cleanup;
2006
2007         result = task_send(lctx);
2008         if (result == ISC_R_SUCCESS) {
2009                 dns_loadctx_attach(lctx, lctxp);
2010                 return (DNS_R_CONTINUE);
2011         }
2012
2013  cleanup:
2014         if (lctx != NULL)
2015                 dns_loadctx_detach(&lctx);
2016         return (result);
2017 }
2018
2019 isc_result_t
2020 dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top,
2021                       dns_name_t *origin, dns_rdataclass_t zclass,
2022                       unsigned int options,
2023                       dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2024 {
2025         isc_result_t result;
2026         dns_loadctx_t *lctx = NULL;
2027
2028         REQUIRE(buffer != NULL);
2029
2030         result = loadctx_create(mctx, options, top, zclass, origin,
2031                                 callbacks, NULL, NULL, NULL, NULL, &lctx);
2032         if (result != ISC_R_SUCCESS)
2033                 return (result);
2034
2035         result = isc_lex_openbuffer(lctx->lex, buffer);
2036         if (result != ISC_R_SUCCESS)
2037                 goto cleanup;
2038
2039         result = load(lctx);
2040         INSIST(result != DNS_R_CONTINUE);
2041
2042  cleanup:
2043         if (lctx != NULL)
2044                 dns_loadctx_detach(&lctx);
2045         return (result);
2046 }
2047
2048 isc_result_t
2049 dns_master_loadbufferinc(isc_buffer_t *buffer, dns_name_t *top,
2050                          dns_name_t *origin, dns_rdataclass_t zclass,
2051                          unsigned int options,
2052                          dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2053                          dns_loaddonefunc_t done, void *done_arg,
2054                          dns_loadctx_t **lctxp, isc_mem_t *mctx)
2055 {
2056         isc_result_t result;
2057         dns_loadctx_t *lctx = NULL;
2058
2059         REQUIRE(buffer != NULL);
2060         REQUIRE(task != NULL);
2061         REQUIRE(done != NULL);
2062
2063         result = loadctx_create(mctx, options, top, zclass, origin,
2064                                 callbacks, task, done, done_arg, NULL, &lctx);
2065         if (result != ISC_R_SUCCESS)
2066                 return (result);
2067
2068         result = isc_lex_openbuffer(lctx->lex, buffer);
2069         if (result != ISC_R_SUCCESS)
2070                 goto cleanup;
2071
2072         result = task_send(lctx);
2073         if (result == ISC_R_SUCCESS) {
2074                 dns_loadctx_attach(lctx, lctxp);
2075                 return (DNS_R_CONTINUE);
2076         }
2077
2078  cleanup:
2079         if (lctx != NULL)
2080                 dns_loadctx_detach(&lctx);
2081         return (result);
2082 }
2083
2084 isc_result_t
2085 dns_master_loadlexer(isc_lex_t *lex, dns_name_t *top,
2086                      dns_name_t *origin, dns_rdataclass_t zclass,
2087                      unsigned int options,
2088                      dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
2089 {
2090         isc_result_t result;
2091         dns_loadctx_t *lctx = NULL;
2092
2093         REQUIRE(lex != NULL);
2094
2095         result = loadctx_create(mctx, options, top, zclass, origin,
2096                                 callbacks, NULL, NULL, NULL, lex, &lctx);
2097         if (result != ISC_R_SUCCESS)
2098                 return (result);
2099
2100         result = load(lctx);
2101         INSIST(result != DNS_R_CONTINUE);
2102
2103         dns_loadctx_detach(&lctx);
2104         return (result);
2105 }
2106
2107 isc_result_t
2108 dns_master_loadlexerinc(isc_lex_t *lex, dns_name_t *top,
2109                         dns_name_t *origin, dns_rdataclass_t zclass,
2110                         unsigned int options,
2111                         dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2112                         dns_loaddonefunc_t done, void *done_arg,
2113                         dns_loadctx_t **lctxp, isc_mem_t *mctx)
2114 {
2115         isc_result_t result;
2116         dns_loadctx_t *lctx = NULL;
2117
2118         REQUIRE(lex != NULL);
2119         REQUIRE(task != NULL);
2120         REQUIRE(done != NULL);
2121
2122         result = loadctx_create(mctx, options, top, zclass, origin,
2123                                 callbacks, task, done, done_arg, lex, &lctx);
2124         if (result != ISC_R_SUCCESS)
2125                 return (result);
2126
2127         result = task_send(lctx);
2128         if (result == ISC_R_SUCCESS) {
2129                 dns_loadctx_attach(lctx, lctxp);
2130                 return (DNS_R_CONTINUE);
2131         }
2132
2133         dns_loadctx_detach(&lctx);
2134         return (result);
2135 }
2136
2137 /*
2138  * Grow the slab of dns_rdatalist_t structures.
2139  * Re-link glue and current list.
2140  */
2141 static dns_rdatalist_t *
2142 grow_rdatalist(int new_len, dns_rdatalist_t *old, int old_len,
2143                rdatalist_head_t *current, rdatalist_head_t *glue,
2144                isc_mem_t *mctx)
2145 {
2146         dns_rdatalist_t *new;
2147         int rdlcount = 0;
2148         ISC_LIST(dns_rdatalist_t) save;
2149         dns_rdatalist_t *this;
2150
2151         new = isc_mem_get(mctx, new_len * sizeof(*new));
2152         if (new == NULL)
2153                 return (NULL);
2154
2155         ISC_LIST_INIT(save);
2156         this = ISC_LIST_HEAD(*current);
2157         while ((this = ISC_LIST_HEAD(*current)) != NULL) {
2158                 ISC_LIST_UNLINK(*current, this, link);
2159                 ISC_LIST_APPEND(save, this, link);
2160         }
2161         while ((this = ISC_LIST_HEAD(save)) != NULL) {
2162                 ISC_LIST_UNLINK(save, this, link);
2163                 new[rdlcount] = *this;
2164                 ISC_LIST_APPEND(*current, &new[rdlcount], link);
2165                 rdlcount++;
2166         }
2167
2168         ISC_LIST_INIT(save);
2169         this = ISC_LIST_HEAD(*glue);
2170         while ((this = ISC_LIST_HEAD(*glue)) != NULL) {
2171                 ISC_LIST_UNLINK(*glue, this, link);
2172                 ISC_LIST_APPEND(save, this, link);
2173         }
2174         while ((this = ISC_LIST_HEAD(save)) != NULL) {
2175                 ISC_LIST_UNLINK(save, this, link);
2176                 new[rdlcount] = *this;
2177                 ISC_LIST_APPEND(*glue, &new[rdlcount], link);
2178                 rdlcount++;
2179         }
2180
2181         INSIST(rdlcount == old_len);
2182         if (old != NULL)
2183                 isc_mem_put(mctx, old, old_len * sizeof(*old));
2184         return (new);
2185 }
2186
2187 /*
2188  * Grow the slab of rdata structs.
2189  * Re-link the current and glue chains.
2190  */
2191 static dns_rdata_t *
2192 grow_rdata(int new_len, dns_rdata_t *old, int old_len,
2193            rdatalist_head_t *current, rdatalist_head_t *glue,
2194            isc_mem_t *mctx)
2195 {
2196         dns_rdata_t *new;
2197         int rdcount = 0;
2198         ISC_LIST(dns_rdata_t) save;
2199         dns_rdatalist_t *this;
2200         dns_rdata_t *rdata;
2201
2202         new = isc_mem_get(mctx, new_len * sizeof(*new));
2203         if (new == NULL)
2204                 return (NULL);
2205         memset(new, 0, new_len * sizeof(*new));
2206
2207         /*
2208          * Copy current relinking.
2209          */
2210         this = ISC_LIST_HEAD(*current);
2211         while (this != NULL) {
2212                 ISC_LIST_INIT(save);
2213                 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
2214                         ISC_LIST_UNLINK(this->rdata, rdata, link);
2215                         ISC_LIST_APPEND(save, rdata, link);
2216                 }
2217                 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
2218                         ISC_LIST_UNLINK(save, rdata, link);
2219                         new[rdcount] = *rdata;
2220                         ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
2221                         rdcount++;
2222                 }
2223                 this = ISC_LIST_NEXT(this, link);
2224         }
2225
2226         /*
2227          * Copy glue relinking.
2228          */
2229         this = ISC_LIST_HEAD(*glue);
2230         while (this != NULL) {
2231                 ISC_LIST_INIT(save);
2232                 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
2233                         ISC_LIST_UNLINK(this->rdata, rdata, link);
2234                         ISC_LIST_APPEND(save, rdata, link);
2235                 }
2236                 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
2237                         ISC_LIST_UNLINK(save, rdata, link);
2238                         new[rdcount] = *rdata;
2239                         ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
2240                         rdcount++;
2241                 }
2242                 this = ISC_LIST_NEXT(this, link);
2243         }
2244         INSIST(rdcount == old_len);
2245         if (old != NULL)
2246                 isc_mem_put(mctx, old, old_len * sizeof(*old));
2247         return (new);
2248 }
2249
2250 /*
2251  * Convert each element from a rdatalist_t to rdataset then call commit.
2252  * Unlink each element as we go.
2253  */
2254
2255 static isc_result_t
2256 commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
2257        rdatalist_head_t *head, dns_name_t *owner,
2258        const char *source, unsigned int line)
2259 {
2260         dns_rdatalist_t *this;
2261         dns_rdataset_t dataset;
2262         isc_result_t result;
2263         char namebuf[DNS_NAME_FORMATSIZE];
2264         void    (*error)(struct dns_rdatacallbacks *, const char *, ...);
2265
2266         this = ISC_LIST_HEAD(*head);
2267         error = callbacks->error;
2268
2269         if (this == NULL)
2270                 return (ISC_R_SUCCESS);
2271         do {
2272                 dns_rdataset_init(&dataset);
2273                 RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset)
2274                               == ISC_R_SUCCESS);
2275                 dataset.trust = dns_trust_ultimate;
2276                 result = ((*callbacks->add)(callbacks->add_private, owner,
2277                                             &dataset));
2278                 if (result == ISC_R_NOMEMORY) {
2279                         (*error)(callbacks, "dns_master_load: %s",
2280                                  dns_result_totext(result));
2281                 } else if (result != ISC_R_SUCCESS) {
2282                         dns_name_format(owner, namebuf,
2283                                         sizeof(namebuf));
2284                         (*error)(callbacks, "%s: %s:%lu: %s: %s",
2285                                  "dns_master_load", source, line,
2286                                  namebuf, dns_result_totext(result));
2287                 }
2288                 if (MANYERRS(lctx, result))
2289                         SETRESULT(lctx, result);
2290                 else if (result != ISC_R_SUCCESS)
2291                         return (result);
2292                 ISC_LIST_UNLINK(*head, this, link);
2293                 this = ISC_LIST_HEAD(*head);
2294         } while (this != NULL);
2295         return (ISC_R_SUCCESS);
2296 }
2297
2298 /*
2299  * Returns ISC_TRUE if one of the NS rdata's contains 'owner'.
2300  */
2301
2302 static isc_boolean_t
2303 is_glue(rdatalist_head_t *head, dns_name_t *owner) {
2304         dns_rdatalist_t *this;
2305         dns_rdata_t *rdata;
2306         isc_region_t region;
2307         dns_name_t name;
2308
2309         /*
2310          * Find NS rrset.
2311          */
2312         this = ISC_LIST_HEAD(*head);
2313         while (this != NULL) {
2314                 if (this->type == dns_rdatatype_ns)
2315                         break;
2316                 this = ISC_LIST_NEXT(this, link);
2317         }
2318         if (this == NULL)
2319                 return (ISC_FALSE);
2320
2321         rdata = ISC_LIST_HEAD(this->rdata);
2322         while (rdata != NULL) {
2323                 dns_name_init(&name, NULL);
2324                 dns_rdata_toregion(rdata, &region);
2325                 dns_name_fromregion(&name, &region);
2326                 if (dns_name_compare(&name, owner) == 0)
2327                         return (ISC_TRUE);
2328                 rdata = ISC_LIST_NEXT(rdata, link);
2329         }
2330         return (ISC_FALSE);
2331 }
2332
2333 static void
2334 load_quantum(isc_task_t *task, isc_event_t *event) {
2335         isc_result_t result;
2336         dns_loadctx_t *lctx;
2337
2338         REQUIRE(event != NULL);
2339         lctx = event->ev_arg;
2340         REQUIRE(DNS_LCTX_VALID(lctx));
2341
2342         if (lctx->canceled)
2343                 result = ISC_R_CANCELED;
2344         else
2345                 result = load(lctx);
2346         if (result == DNS_R_CONTINUE) {
2347                 event->ev_arg = lctx;
2348                 isc_task_send(task, &event);
2349         } else {
2350                 (lctx->done)(lctx->done_arg, result);
2351                 isc_event_free(&event);
2352                 dns_loadctx_detach(&lctx);
2353         }
2354 }
2355
2356 static isc_result_t
2357 task_send(dns_loadctx_t *lctx) {
2358         isc_event_t *event;
2359
2360         event = isc_event_allocate(lctx->mctx, NULL,
2361                                    DNS_EVENT_MASTERQUANTUM,
2362                                    load_quantum, lctx, sizeof(*event));
2363         if (event == NULL)
2364                 return (ISC_R_NOMEMORY);
2365         isc_task_send(lctx->task, &event);
2366         return (ISC_R_SUCCESS);
2367 }
2368
2369 void
2370 dns_loadctx_cancel(dns_loadctx_t *lctx) {
2371         REQUIRE(DNS_LCTX_VALID(lctx));
2372
2373         LOCK(&lctx->lock);
2374         lctx->canceled = ISC_TRUE;
2375         UNLOCK(&lctx->lock);
2376 }