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