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