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