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