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