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