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