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