1/* $NetBSD: master.c,v 1.12 2024/02/21 22:52:07 christos 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 95typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t; 96 97typedef struct dns_incctx dns_incctx_t; 98 99/*% 100 * Master file load state. 101 */ 102 103struct 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 159struct 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 180static isc_result_t 181openfile_text(dns_loadctx_t *lctx, const char *master_file); 182 183static isc_result_t 184load_text(dns_loadctx_t *lctx); 185 186static isc_result_t 187openfile_raw(dns_loadctx_t *lctx, const char *master_file); 188 189static isc_result_t 190load_raw(dns_loadctx_t *lctx); 191 192static isc_result_t 193pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx); 194 195static isc_result_t 196commit(dns_rdatacallbacks_t *, dns_loadctx_t *, rdatalist_head_t *, 197 dns_name_t *, const char *, unsigned int); 198 199static bool 200is_glue(rdatalist_head_t *, dns_name_t *); 201 202static dns_rdatalist_t * 203grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *, 204 rdatalist_head_t *, isc_mem_t *mctx); 205 206static dns_rdata_t * 207grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *, 208 isc_mem_t *); 209 210static void 211load_quantum(isc_task_t *task, isc_event_t *event); 212 213static isc_result_t 214task_send(dns_loadctx_t *lctx); 215 216static void 217loadctx_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 325static unsigned char in_addr_arpa_data[] = "\007IN-ADDR\004ARPA"; 326static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 }; 327static dns_name_t const in_addr_arpa = 328 DNS_NAME_INITABSOLUTE(in_addr_arpa_data, in_addr_arpa_offsets); 329 330static unsigned char ip6_int_data[] = "\003IP6\003INT"; 331static unsigned char ip6_int_offsets[] = { 0, 4, 8 }; 332static dns_name_t const ip6_int = DNS_NAME_INITABSOLUTE(ip6_int_data, 333 ip6_int_offsets); 334 335static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA"; 336static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 }; 337static dns_name_t const ip6_arpa = DNS_NAME_INITABSOLUTE(ip6_arpa_data, 338 ip6_arpa_offsets); 339 340static bool 341dns_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 347static isc_result_t 348gettoken(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 397void 398dns_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 407void 408dns_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 421static void 422incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) { 423 dns_incctx_t *parent; 424 425again: 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 437static void 438loadctx_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 468static isc_result_t 469incctx_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 501static isc_result_t 502loadctx_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 613cleanup_inc: 614 incctx_destroy(mctx, lctx->inc); 615cleanup_ctx: 616 isc_mem_put(mctx, lctx, sizeof(*lctx)); 617 return (result); 618} 619 620static 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 */ 630static unsigned int 631nibbles(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 673static isc_result_t 674genname(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 795static isc_result_t 796generate(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 937error_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 946insist_cleanup: 947 INSIST(result != ISC_R_SUCCESS); 948 949cleanup: 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 962static void 963limit_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 975static isc_result_t 976check_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 1017static void 1018check_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 1034static isc_result_t 1035openfile_text(dns_loadctx_t *lctx, const char *master_file) { 1036 return (isc_lex_openfile(lctx->lex, master_file)); 1037} 1038 1039static int 1040find_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 1052static isc_result_t 1053load_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 2139log_and_cleanup: 2140 LOGIT(result); 2141 2142insist_and_cleanup: 2143 INSIST(result != ISC_R_SUCCESS); 2144 2145cleanup: 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 2180static isc_result_t 2181pushfile(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 2227cleanup: 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 */ 2236static isc_result_t 2237read_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 2262static isc_result_t 2263load_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 2337static isc_result_t 2338openfile_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 2350static isc_result_t 2351load_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 2637cleanup: 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 2652isc_result_t 2653dns_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 2680cleanup: 2681 dns_loadctx_detach(&lctx); 2682 return (result); 2683} 2684 2685isc_result_t 2686dns_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 2720cleanup: 2721 dns_loadctx_detach(&lctx); 2722 return (result); 2723} 2724 2725isc_result_t 2726dns_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 2749cleanup: 2750 if (lctx != NULL) { 2751 dns_loadctx_detach(&lctx); 2752 } 2753 return (result); 2754} 2755 2756isc_result_t 2757dns_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 2787cleanup: 2788 if (lctx != NULL) { 2789 dns_loadctx_detach(&lctx); 2790 } 2791 return (result); 2792} 2793 2794isc_result_t 2795dns_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 2818cleanup: 2819 dns_loadctx_detach(&lctx); 2820 return (result); 2821} 2822 2823isc_result_t 2824dns_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 2855cleanup: 2856 dns_loadctx_detach(&lctx); 2857 return (result); 2858} 2859 2860isc_result_t 2861dns_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 2883isc_result_t 2884dns_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 */ 2917static dns_rdatalist_t * 2918grow_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 */ 2968static dns_rdata_t * 2969grow_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 3029static uint32_t 3030resign_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 3062static isc_result_t 3063commit(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 3124static bool 3125is_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 3158static void 3159load_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 3182static isc_result_t 3183task_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 3192void 3193dns_loadctx_cancel(dns_loadctx_t *lctx) { 3194 REQUIRE(DNS_LCTX_VALID(lctx)); 3195 3196 atomic_store_release(&lctx->canceled, true); 3197} 3198 3199void 3200dns_master_initrawheader(dns_masterrawheader_t *header) { 3201 memset(header, 0, sizeof(dns_masterrawheader_t)); 3202} 3203