00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <isc/event.h>
00025 #include <isc/lex.h>
00026 #include <isc/magic.h>
00027 #include <isc/mem.h>
00028 #include <isc/print.h>
00029 #include <isc/serial.h>
00030 #include <isc/stdio.h>
00031 #include <isc/stdtime.h>
00032 #include <isc/string.h>
00033 #include <isc/task.h>
00034 #include <isc/util.h>
00035
00036 #include <dns/callbacks.h>
00037 #include <dns/events.h>
00038 #include <dns/fixedname.h>
00039 #include <dns/master.h>
00040 #include <dns/name.h>
00041 #include <dns/rdata.h>
00042 #include <dns/rdataclass.h>
00043 #include <dns/rdatalist.h>
00044 #include <dns/rdataset.h>
00045 #include <dns/rdatastruct.h>
00046 #include <dns/rdatatype.h>
00047 #include <dns/result.h>
00048 #include <dns/soa.h>
00049 #include <dns/time.h>
00050 #include <dns/ttl.h>
00051
00052
00053
00054
00055
00056
00057
00058 #define RDLSZ 32
00059
00060
00061
00062
00063 #define RDSZ 512
00064
00065 #define NBUFS 4
00066 #define MAXWIRESZ 255
00067
00068
00069
00070
00071
00072
00073
00074 #define TSIZ (128*1024)
00075
00076
00077
00078 #define MINTSIZ DNS_RDATA_MAXLENGTH
00079
00080
00081
00082
00083
00084
00085
00086 #define TOKENSIZ (8*1024)
00087
00088
00089
00090
00091 #define DNS_MASTER_LHS 2048
00092 #define DNS_MASTER_RHS MINTSIZ
00093
00094 #define CHECKNAMESFAIL(x) (((x) & DNS_MASTER_CHECKNAMESFAIL) != 0)
00095
00096 typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
00097
00098 typedef struct dns_incctx dns_incctx_t;
00099
00100
00101
00102
00103
00104 struct dns_loadctx {
00105 unsigned int magic;
00106 isc_mem_t *mctx;
00107 dns_masterformat_t format;
00108
00109 dns_rdatacallbacks_t *callbacks;
00110 isc_task_t *task;
00111 dns_loaddonefunc_t done;
00112 void *done_arg;
00113
00114
00115 isc_result_t (*openfile)(dns_loadctx_t *lctx,
00116 const char *filename);
00117 isc_result_t (*load)(dns_loadctx_t *lctx);
00118
00119
00120 isc_uint32_t maxttl;
00121
00122
00123 isc_lex_t *lex;
00124 isc_boolean_t keep_lex;
00125 unsigned int options;
00126 isc_boolean_t ttl_known;
00127 isc_boolean_t default_ttl_known;
00128 isc_boolean_t warn_1035;
00129 isc_boolean_t warn_tcr;
00130 isc_boolean_t warn_sigexpired;
00131 isc_boolean_t seen_include;
00132 isc_uint32_t ttl;
00133 isc_uint32_t default_ttl;
00134 dns_rdataclass_t zclass;
00135 dns_fixedname_t fixed_top;
00136 dns_name_t *top;
00137
00138
00139 FILE *f;
00140 isc_boolean_t first;
00141 dns_masterrawheader_t header;
00142
00143
00144 unsigned int loop_cnt;
00145
00146 isc_boolean_t canceled;
00147 isc_mutex_t lock;
00148 isc_result_t result;
00149
00150 isc_uint32_t references;
00151 dns_incctx_t *inc;
00152 isc_uint32_t resign;
00153
00154 dns_masterincludecb_t include_cb;
00155 void *include_arg;
00156 };
00157
00158 struct dns_incctx {
00159 dns_incctx_t *parent;
00160 dns_name_t *origin;
00161 dns_name_t *current;
00162 dns_name_t *glue;
00163 dns_fixedname_t fixed[NBUFS];
00164 unsigned int in_use[NBUFS];
00165 int glue_in_use;
00166 int current_in_use;
00167 int origin_in_use;
00168 isc_boolean_t origin_changed;
00169 isc_boolean_t drop;
00170 unsigned int glue_line;
00171 unsigned int current_line;
00172 };
00173
00174 #define DNS_LCTX_MAGIC ISC_MAGIC('L','c','t','x')
00175 #define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
00176
00177 #define DNS_AS_STR(t) ((t).value.as_textregion.base)
00178
00179 static isc_result_t
00180 openfile_text(dns_loadctx_t *lctx, const char *master_file);
00181
00182 static isc_result_t
00183 load_text(dns_loadctx_t *lctx);
00184
00185 static isc_result_t
00186 openfile_raw(dns_loadctx_t *lctx, const char *master_file);
00187
00188 static isc_result_t
00189 load_raw(dns_loadctx_t *lctx);
00190
00191 static isc_result_t
00192 openfile_map(dns_loadctx_t *lctx, const char *master_file);
00193
00194 static isc_result_t
00195 load_map(dns_loadctx_t *lctx);
00196
00197 static isc_result_t
00198 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx);
00199
00200 static isc_result_t
00201 commit(dns_rdatacallbacks_t *, dns_loadctx_t *, rdatalist_head_t *,
00202 dns_name_t *, const char *, unsigned int);
00203
00204 static isc_boolean_t
00205 is_glue(rdatalist_head_t *, dns_name_t *);
00206
00207 static dns_rdatalist_t *
00208 grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *,
00209 rdatalist_head_t *, isc_mem_t *mctx);
00210
00211 static dns_rdata_t *
00212 grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *,
00213 isc_mem_t *);
00214
00215 static void
00216 load_quantum(isc_task_t *task, isc_event_t *event);
00217
00218 static isc_result_t
00219 task_send(dns_loadctx_t *lctx);
00220
00221 static void
00222 loadctx_destroy(dns_loadctx_t *lctx);
00223
00224 #define GETTOKENERR(lexer, options, token, eol, err) \
00225 do { \
00226 result = gettoken(lexer, options, token, eol, callbacks); \
00227 switch (result) { \
00228 case ISC_R_SUCCESS: \
00229 break; \
00230 case ISC_R_UNEXPECTED: \
00231 goto insist_and_cleanup; \
00232 default: \
00233 if (MANYERRS(lctx, result)) { \
00234 SETRESULT(lctx, result); \
00235 LOGIT(result); \
00236 read_till_eol = ISC_TRUE; \
00237 err \
00238 goto next_line; \
00239 } else \
00240 goto log_and_cleanup; \
00241 } \
00242 if ((token)->type == isc_tokentype_special) { \
00243 result = DNS_R_SYNTAX; \
00244 if (MANYERRS(lctx, result)) { \
00245 SETRESULT(lctx, result); \
00246 LOGIT(result); \
00247 read_till_eol = ISC_TRUE; \
00248 goto next_line; \
00249 } else \
00250 goto log_and_cleanup; \
00251 } \
00252 } while (0)
00253 #define GETTOKEN(lexer, options, token, eol) \
00254 GETTOKENERR(lexer, options, token, eol, {} )
00255
00256 #define COMMITALL \
00257 do { \
00258 result = commit(callbacks, lctx, ¤t_list, \
00259 ictx->current, source, ictx->current_line); \
00260 if (MANYERRS(lctx, result)) { \
00261 SETRESULT(lctx, result); \
00262 } else if (result != ISC_R_SUCCESS) \
00263 goto insist_and_cleanup; \
00264 result = commit(callbacks, lctx, &glue_list, \
00265 ictx->glue, source, ictx->glue_line); \
00266 if (MANYERRS(lctx, result)) { \
00267 SETRESULT(lctx, result); \
00268 } else if (result != ISC_R_SUCCESS) \
00269 goto insist_and_cleanup; \
00270 rdcount = 0; \
00271 rdlcount = 0; \
00272 isc_buffer_init(&target, target_mem, target_size); \
00273 rdcount_save = rdcount; \
00274 rdlcount_save = rdlcount; \
00275 } while (0)
00276
00277 #define WARNUNEXPECTEDEOF(lexer) \
00278 do { \
00279 if (isc_lex_isfile(lexer)) \
00280 (*callbacks->warn)(callbacks, \
00281 "%s: file does not end with newline", \
00282 source); \
00283 } while (0)
00284
00285 #define EXPECTEOL \
00286 do { \
00287 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE); \
00288 if (token.type != isc_tokentype_eol) { \
00289 isc_lex_ungettoken(lctx->lex, &token); \
00290 result = DNS_R_EXTRATOKEN; \
00291 if (MANYERRS(lctx, result)) { \
00292 SETRESULT(lctx, result); \
00293 LOGIT(result); \
00294 read_till_eol = ISC_TRUE; \
00295 continue; \
00296 } else if (result != ISC_R_SUCCESS) \
00297 goto log_and_cleanup; \
00298 } \
00299 } while (0)
00300
00301 #define MANYERRS(lctx, result) \
00302 ((result != ISC_R_SUCCESS) && \
00303 (result != ISC_R_IOERROR) && \
00304 ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
00305
00306 #define SETRESULT(lctx, r) \
00307 do { \
00308 if ((lctx)->result == ISC_R_SUCCESS) \
00309 (lctx)->result = r; \
00310 } while (0)
00311
00312 #define LOGITFILE(result, filename) \
00313 if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \
00314 result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \
00315 result == ISC_R_NOPERM) \
00316 (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \
00317 "dns_master_load", source, line, \
00318 filename, dns_result_totext(result)); \
00319 else LOGIT(result)
00320
00321 #define LOGIT(result) \
00322 if (result == ISC_R_NOMEMORY) \
00323 (*callbacks->error)(callbacks, "dns_master_load: %s", \
00324 dns_result_totext(result)); \
00325 else \
00326 (*callbacks->error)(callbacks, "%s: %s:%lu: %s", \
00327 "dns_master_load", \
00328 source, line, dns_result_totext(result))
00329
00330
00331 static unsigned char in_addr_arpa_data[] = "\007IN-ADDR\004ARPA";
00332 static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 };
00333 static const dns_name_t in_addr_arpa =
00334 {
00335 DNS_NAME_MAGIC,
00336 in_addr_arpa_data, 14, 3,
00337 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
00338 in_addr_arpa_offsets, NULL,
00339 {(void *)-1, (void *)-1},
00340 {NULL, NULL}
00341 };
00342
00343 static unsigned char ip6_int_data[] = "\003IP6\003INT";
00344 static unsigned char ip6_int_offsets[] = { 0, 4, 8 };
00345 static const dns_name_t ip6_int =
00346 {
00347 DNS_NAME_MAGIC,
00348 ip6_int_data, 9, 3,
00349 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
00350 ip6_int_offsets, NULL,
00351 {(void *)-1, (void *)-1},
00352 {NULL, NULL}
00353 };
00354
00355 static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA";
00356 static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
00357 static const dns_name_t ip6_arpa =
00358 {
00359 DNS_NAME_MAGIC,
00360 ip6_arpa_data, 10, 3,
00361 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
00362 ip6_arpa_offsets, NULL,
00363 {(void *)-1, (void *)-1},
00364 {NULL, NULL}
00365 };
00366
00367
00368 static inline isc_result_t
00369 gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token,
00370 isc_boolean_t eol, dns_rdatacallbacks_t *callbacks)
00371 {
00372 isc_result_t result;
00373
00374 options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE |
00375 ISC_LEXOPT_ESCAPE;
00376 result = isc_lex_gettoken(lex, options, token);
00377 if (result != ISC_R_SUCCESS) {
00378 switch (result) {
00379 case ISC_R_NOMEMORY:
00380 return (ISC_R_NOMEMORY);
00381 default:
00382 (*callbacks->error)(callbacks,
00383 "dns_master_load: %s:%lu:"
00384 " isc_lex_gettoken() failed: %s",
00385 isc_lex_getsourcename(lex),
00386 isc_lex_getsourceline(lex),
00387 isc_result_totext(result));
00388 return (result);
00389 }
00390
00391 }
00392 if (eol != ISC_TRUE)
00393 if (token->type == isc_tokentype_eol ||
00394 token->type == isc_tokentype_eof) {
00395 unsigned long int line;
00396 const char *what;
00397 const char *file;
00398 file = isc_lex_getsourcename(lex);
00399 line = isc_lex_getsourceline(lex);
00400 if (token->type == isc_tokentype_eol) {
00401 line--;
00402 what = "line";
00403 } else
00404 what = "file";
00405 (*callbacks->error)(callbacks,
00406 "dns_master_load: %s:%lu: unexpected end of %s",
00407 file, line, what);
00408 return (ISC_R_UNEXPECTEDEND);
00409 }
00410 return (ISC_R_SUCCESS);
00411 }
00412
00413
00414 void
00415 dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
00416
00417 REQUIRE(target != NULL && *target == NULL);
00418 REQUIRE(DNS_LCTX_VALID(source));
00419
00420 LOCK(&source->lock);
00421 INSIST(source->references > 0);
00422 source->references++;
00423 INSIST(source->references != 0);
00424 UNLOCK(&source->lock);
00425
00426 *target = source;
00427 }
00428
00429 void
00430 dns_loadctx_detach(dns_loadctx_t **lctxp) {
00431 dns_loadctx_t *lctx;
00432 isc_boolean_t need_destroy = ISC_FALSE;
00433
00434 REQUIRE(lctxp != NULL);
00435 lctx = *lctxp;
00436 REQUIRE(DNS_LCTX_VALID(lctx));
00437
00438 LOCK(&lctx->lock);
00439 INSIST(lctx->references > 0);
00440 lctx->references--;
00441 if (lctx->references == 0)
00442 need_destroy = ISC_TRUE;
00443 UNLOCK(&lctx->lock);
00444
00445 if (need_destroy)
00446 loadctx_destroy(lctx);
00447 *lctxp = NULL;
00448 }
00449
00450 static void
00451 incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
00452 dns_incctx_t *parent;
00453
00454 again:
00455 parent = ictx->parent;
00456 ictx->parent = NULL;
00457
00458 isc_mem_put(mctx, ictx, sizeof(*ictx));
00459
00460 if (parent != NULL) {
00461 ictx = parent;
00462 goto again;
00463 }
00464 }
00465
00466 static void
00467 loadctx_destroy(dns_loadctx_t *lctx) {
00468 isc_mem_t *mctx;
00469 isc_result_t result;
00470
00471 REQUIRE(DNS_LCTX_VALID(lctx));
00472
00473 lctx->magic = 0;
00474 if (lctx->inc != NULL)
00475 incctx_destroy(lctx->mctx, lctx->inc);
00476
00477 if (lctx->f != NULL) {
00478 result = isc_stdio_close(lctx->f);
00479 if (result != ISC_R_SUCCESS) {
00480 UNEXPECTED_ERROR(__FILE__, __LINE__,
00481 "isc_stdio_close() failed: %s",
00482 isc_result_totext(result));
00483 }
00484 }
00485
00486
00487 if (lctx->lex != NULL && !lctx->keep_lex)
00488 isc_lex_destroy(&lctx->lex);
00489
00490 if (lctx->task != NULL)
00491 isc_task_detach(&lctx->task);
00492 DESTROYLOCK(&lctx->lock);
00493 mctx = NULL;
00494 isc_mem_attach(lctx->mctx, &mctx);
00495 isc_mem_detach(&lctx->mctx);
00496 isc_mem_put(mctx, lctx, sizeof(*lctx));
00497 isc_mem_detach(&mctx);
00498 }
00499
00500 static isc_result_t
00501 incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
00502 dns_incctx_t *ictx;
00503 isc_region_t r;
00504 int i;
00505
00506 ictx = isc_mem_get(mctx, sizeof(*ictx));
00507 if (ictx == NULL)
00508 return (ISC_R_NOMEMORY);
00509
00510 for (i = 0; i < NBUFS; i++) {
00511 dns_fixedname_init(&ictx->fixed[i]);
00512 ictx->in_use[i] = ISC_FALSE;
00513 }
00514
00515 ictx->origin_in_use = 0;
00516 ictx->origin = dns_fixedname_name(&ictx->fixed[ictx->origin_in_use]);
00517 ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
00518 dns_name_toregion(origin, &r);
00519 dns_name_fromregion(ictx->origin, &r);
00520
00521 ictx->glue = NULL;
00522 ictx->current = NULL;
00523 ictx->glue_in_use = -1;
00524 ictx->current_in_use = -1;
00525 ictx->parent = NULL;
00526 ictx->drop = ISC_FALSE;
00527 ictx->glue_line = 0;
00528 ictx->current_line = 0;
00529 ictx->origin_changed = ISC_TRUE;
00530
00531 *ictxp = ictx;
00532 return (ISC_R_SUCCESS);
00533 }
00534
00535 static isc_result_t
00536 loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
00537 unsigned int options, isc_uint32_t resign, dns_name_t *top,
00538 dns_rdataclass_t zclass, dns_name_t *origin,
00539 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
00540 dns_loaddonefunc_t done, void *done_arg,
00541 dns_masterincludecb_t include_cb, void *include_arg,
00542 isc_lex_t *lex, dns_loadctx_t **lctxp)
00543 {
00544 dns_loadctx_t *lctx;
00545 isc_result_t result;
00546 isc_region_t r;
00547 isc_lexspecials_t specials;
00548
00549 REQUIRE(lctxp != NULL && *lctxp == NULL);
00550 REQUIRE(callbacks != NULL);
00551 REQUIRE(callbacks->add != NULL);
00552 REQUIRE(callbacks->error != NULL);
00553 REQUIRE(callbacks->warn != NULL);
00554 REQUIRE(mctx != NULL);
00555 REQUIRE(dns_name_isabsolute(top));
00556 REQUIRE(dns_name_isabsolute(origin));
00557 REQUIRE((task == NULL && done == NULL) ||
00558 (task != NULL && done != NULL));
00559
00560 lctx = isc_mem_get(mctx, sizeof(*lctx));
00561 if (lctx == NULL)
00562 return (ISC_R_NOMEMORY);
00563 result = isc_mutex_init(&lctx->lock);
00564 if (result != ISC_R_SUCCESS) {
00565 isc_mem_put(mctx, lctx, sizeof(*lctx));
00566 return (result);
00567 }
00568
00569 lctx->inc = NULL;
00570 result = incctx_create(mctx, origin, &lctx->inc);
00571 if (result != ISC_R_SUCCESS)
00572 goto cleanup_ctx;
00573
00574 lctx->maxttl = 0;
00575
00576 lctx->format = format;
00577 switch (format) {
00578 default:
00579 INSIST(0);
00580 case dns_masterformat_text:
00581 lctx->openfile = openfile_text;
00582 lctx->load = load_text;
00583 break;
00584 case dns_masterformat_raw:
00585 lctx->openfile = openfile_raw;
00586 lctx->load = load_raw;
00587 break;
00588 case dns_masterformat_map:
00589 lctx->openfile = openfile_map;
00590 lctx->load = load_map;
00591 break;
00592 }
00593
00594 if (lex != NULL) {
00595 lctx->lex = lex;
00596 lctx->keep_lex = ISC_TRUE;
00597 } else {
00598 lctx->lex = NULL;
00599 result = isc_lex_create(mctx, TOKENSIZ, &lctx->lex);
00600 if (result != ISC_R_SUCCESS)
00601 goto cleanup_inc;
00602 lctx->keep_lex = ISC_FALSE;
00603 memset(specials, 0, sizeof(specials));
00604 specials[0] = 1;
00605 specials['('] = 1;
00606 specials[')'] = 1;
00607 specials['"'] = 1;
00608 isc_lex_setspecials(lctx->lex, specials);
00609 isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE);
00610 }
00611
00612 lctx->ttl_known = ISC_TF((options & DNS_MASTER_NOTTL) != 0);
00613 lctx->ttl = 0;
00614 lctx->default_ttl_known = lctx->ttl_known;
00615 lctx->default_ttl = 0;
00616 lctx->warn_1035 = ISC_TRUE;
00617 lctx->warn_tcr = ISC_TRUE;
00618 lctx->warn_sigexpired = ISC_TRUE;
00619 lctx->options = options;
00620 lctx->seen_include = ISC_FALSE;
00621 lctx->zclass = zclass;
00622 lctx->resign = resign;
00623 lctx->result = ISC_R_SUCCESS;
00624 lctx->include_cb = include_cb;
00625 lctx->include_arg = include_arg;
00626
00627 dns_fixedname_init(&lctx->fixed_top);
00628 lctx->top = dns_fixedname_name(&lctx->fixed_top);
00629 dns_name_toregion(top, &r);
00630 dns_name_fromregion(lctx->top, &r);
00631
00632 lctx->f = NULL;
00633 lctx->first = ISC_TRUE;
00634 dns_master_initrawheader(&lctx->header);
00635
00636 lctx->loop_cnt = (done != NULL) ? 100 : 0;
00637 lctx->callbacks = callbacks;
00638 lctx->task = NULL;
00639 if (task != NULL)
00640 isc_task_attach(task, &lctx->task);
00641 lctx->done = done;
00642 lctx->done_arg = done_arg;
00643 lctx->canceled = ISC_FALSE;
00644 lctx->mctx = NULL;
00645 isc_mem_attach(mctx, &lctx->mctx);
00646 lctx->references = 1;
00647 lctx->magic = DNS_LCTX_MAGIC;
00648 *lctxp = lctx;
00649 return (ISC_R_SUCCESS);
00650
00651 cleanup_inc:
00652 incctx_destroy(mctx, lctx->inc);
00653 cleanup_ctx:
00654 isc_mem_put(mctx, lctx, sizeof(*lctx));
00655 return (result);
00656 }
00657
00658 static const char *hex = "0123456789abcdef0123456789ABCDEF";
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 static unsigned int
00669 nibbles(char *numbuf, size_t length, unsigned int width, char mode, int value) {
00670 unsigned int count = 0;
00671
00672
00673
00674
00675 if (length > 0U) {
00676 *numbuf = '\0';
00677 length--;
00678 }
00679 do {
00680 char val = hex[(value & 0x0f) + ((mode == 'n') ? 0 : 16)];
00681 value >>= 4;
00682 if (length > 0U) {
00683 *numbuf++ = val;
00684 *numbuf = '\0';
00685 length--;
00686 }
00687 if (width > 0)
00688 width--;
00689 count++;
00690
00691
00692
00693
00694
00695 if (width > 0 || value != 0) {
00696 if (length > 0U) {
00697 *numbuf++ = '.';
00698 *numbuf = '\0';
00699 length--;
00700 }
00701 if (width > 0)
00702 width--;
00703 count++;
00704 }
00705 } while (value != 0 || width > 0);
00706 return (count);
00707 }
00708
00709 static isc_result_t
00710 genname(char *name, int it, char *buffer, size_t length) {
00711 char fmt[sizeof("%04000000000d")];
00712 char numbuf[128];
00713 char *cp;
00714 char mode[2];
00715 int delta = 0;
00716 isc_textregion_t r;
00717 unsigned int n;
00718 unsigned int width;
00719 isc_boolean_t nibblemode;
00720
00721 r.base = buffer;
00722 r.length = (unsigned int)length;
00723
00724 while (*name != '\0') {
00725 if (*name == '$') {
00726 name++;
00727 if (*name == '$') {
00728 if (r.length == 0)
00729 return (ISC_R_NOSPACE);
00730 r.base[0] = *name++;
00731 isc_textregion_consume(&r, 1);
00732 continue;
00733 }
00734 nibblemode = ISC_FALSE;
00735 strcpy(fmt, "%d");
00736
00737 if (*name == '{' ) {
00738 n = sscanf(name, "{%d,%u,%1[doxXnN]}",
00739 &delta, &width, mode);
00740 switch (n) {
00741 case 1:
00742 break;
00743 case 2:
00744 n = snprintf(fmt, sizeof(fmt),
00745 "%%0%ud", width);
00746 break;
00747 case 3:
00748 if (mode[0] == 'n' || mode[0] == 'N')
00749 nibblemode = ISC_TRUE;
00750 n = snprintf(fmt, sizeof(fmt),
00751 "%%0%u%c", width, mode[0]);
00752 break;
00753 default:
00754 return (DNS_R_SYNTAX);
00755 }
00756 if (n >= sizeof(fmt))
00757 return (ISC_R_NOSPACE);
00758
00759 while (*name != '\0' && *name++ != '}')
00760 continue;
00761 }
00762 if (nibblemode)
00763 n = nibbles(numbuf, sizeof(numbuf), width,
00764 mode[0], it + delta);
00765 else
00766 n = snprintf(numbuf, sizeof(numbuf), fmt,
00767 it + delta);
00768 if (n >= sizeof(numbuf))
00769 return (ISC_R_NOSPACE);
00770 cp = numbuf;
00771 while (*cp != '\0') {
00772 if (r.length == 0)
00773 return (ISC_R_NOSPACE);
00774 r.base[0] = *cp++;
00775 isc_textregion_consume(&r, 1);
00776 }
00777 } else if (*name == '\\') {
00778 if (r.length == 0)
00779 return (ISC_R_NOSPACE);
00780 r.base[0] = *name++;
00781 isc_textregion_consume(&r, 1);
00782 if (*name == '\0')
00783 continue;
00784 if (r.length == 0)
00785 return (ISC_R_NOSPACE);
00786 r.base[0] = *name++;
00787 isc_textregion_consume(&r, 1);
00788 } else {
00789 if (r.length == 0)
00790 return (ISC_R_NOSPACE);
00791 r.base[0] = *name++;
00792 isc_textregion_consume(&r, 1);
00793 }
00794 }
00795 if (r.length == 0)
00796 return (ISC_R_NOSPACE);
00797 r.base[0] = '\0';
00798 return (ISC_R_SUCCESS);
00799 }
00800
00801 static isc_result_t
00802 generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
00803 const char *source, unsigned int line)
00804 {
00805 char *target_mem = NULL;
00806 char *lhsbuf = NULL;
00807 char *rhsbuf = NULL;
00808 dns_fixedname_t ownerfixed;
00809 dns_name_t *owner;
00810 dns_rdata_t rdata = DNS_RDATA_INIT;
00811 dns_rdatacallbacks_t *callbacks;
00812 dns_rdatalist_t rdatalist;
00813 dns_rdatatype_t type;
00814 rdatalist_head_t head;
00815 int target_size = MINTSIZ;
00816 isc_buffer_t buffer;
00817 isc_buffer_t target;
00818 isc_result_t result;
00819 isc_textregion_t r;
00820 int i, n, start, stop, step = 0;
00821 dns_incctx_t *ictx;
00822 char dummy;
00823
00824 ictx = lctx->inc;
00825 callbacks = lctx->callbacks;
00826 dns_fixedname_init(&ownerfixed);
00827 owner = dns_fixedname_name(&ownerfixed);
00828 ISC_LIST_INIT(head);
00829
00830 target_mem = isc_mem_get(lctx->mctx, target_size);
00831 rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_RHS);
00832 lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_LHS);
00833 if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) {
00834 result = ISC_R_NOMEMORY;
00835 goto error_cleanup;
00836 }
00837 isc_buffer_init(&target, target_mem, target_size);
00838
00839 n = sscanf(range, "%d-%d%[/]%d", &start, &stop, &dummy, &step);
00840 if ((n != 2 && n != 4) || (start < 0) || (stop < 0) ||
00841 (n == 4 && step < 1) || (stop < start))
00842 {
00843 (*callbacks->error)(callbacks,
00844 "%s: %s:%lu: invalid range '%s'",
00845 "$GENERATE", source, line, range);
00846 result = DNS_R_SYNTAX;
00847 goto insist_cleanup;
00848 }
00849 if (n == 2)
00850 step = 1;
00851
00852
00853
00854
00855 r.base = gtype;
00856 r.length = strlen(gtype);
00857 result = dns_rdatatype_fromtext(&type, &r);
00858 if (result != ISC_R_SUCCESS) {
00859 (*callbacks->error)(callbacks,
00860 "%s: %s:%lu: unknown RR type '%s'",
00861 "$GENERATE", source, line, gtype);
00862 goto insist_cleanup;
00863 }
00864
00865 for (i = start; i <= stop; i += step) {
00866 result = genname(lhs, i, lhsbuf, DNS_MASTER_LHS);
00867 if (result != ISC_R_SUCCESS)
00868 goto error_cleanup;
00869 result = genname(rhs, i, rhsbuf, DNS_MASTER_RHS);
00870 if (result != ISC_R_SUCCESS)
00871 goto error_cleanup;
00872
00873 isc_buffer_init(&buffer, lhsbuf, strlen(lhsbuf));
00874 isc_buffer_add(&buffer, strlen(lhsbuf));
00875 isc_buffer_setactive(&buffer, strlen(lhsbuf));
00876 result = dns_name_fromtext(owner, &buffer, ictx->origin,
00877 0, NULL);
00878 if (result != ISC_R_SUCCESS)
00879 goto error_cleanup;
00880
00881 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
00882 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
00883 (lctx->options & DNS_MASTER_KEY) == 0 &&
00884 !dns_name_issubdomain(owner, lctx->top))
00885 {
00886 char namebuf[DNS_NAME_FORMATSIZE];
00887 dns_name_format(owner, namebuf, sizeof(namebuf));
00888
00889
00890
00891 (*callbacks->warn)(callbacks,
00892 "%s:%lu: "
00893 "ignoring out-of-zone data (%s)",
00894 source, line, namebuf);
00895 continue;
00896 }
00897
00898 isc_buffer_init(&buffer, rhsbuf, strlen(rhsbuf));
00899 isc_buffer_add(&buffer, strlen(rhsbuf));
00900 isc_buffer_setactive(&buffer, strlen(rhsbuf));
00901
00902 result = isc_lex_openbuffer(lctx->lex, &buffer);
00903 if (result != ISC_R_SUCCESS)
00904 goto error_cleanup;
00905
00906 isc_buffer_init(&target, target_mem, target_size);
00907 result = dns_rdata_fromtext(&rdata, lctx->zclass, type,
00908 lctx->lex, ictx->origin, 0,
00909 lctx->mctx, &target, callbacks);
00910 RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
00911 if (result != ISC_R_SUCCESS)
00912 goto error_cleanup;
00913
00914 dns_rdatalist_init(&rdatalist);
00915 rdatalist.type = type;
00916 rdatalist.rdclass = lctx->zclass;
00917 rdatalist.ttl = lctx->ttl;
00918 ISC_LIST_PREPEND(head, &rdatalist, link);
00919 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
00920 result = commit(callbacks, lctx, &head, owner, source, line);
00921 ISC_LIST_UNLINK(rdatalist.rdata, &rdata, link);
00922 if (result != ISC_R_SUCCESS)
00923 goto error_cleanup;
00924 dns_rdata_reset(&rdata);
00925 }
00926 result = ISC_R_SUCCESS;
00927 goto cleanup;
00928
00929 error_cleanup:
00930 if (result == ISC_R_NOMEMORY)
00931 (*callbacks->error)(callbacks, "$GENERATE: %s",
00932 dns_result_totext(result));
00933 else
00934 (*callbacks->error)(callbacks, "$GENERATE: %s:%lu: %s",
00935 source, line, dns_result_totext(result));
00936
00937 insist_cleanup:
00938 INSIST(result != ISC_R_SUCCESS);
00939
00940 cleanup:
00941 if (target_mem != NULL)
00942 isc_mem_put(lctx->mctx, target_mem, target_size);
00943 if (lhsbuf != NULL)
00944 isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_LHS);
00945 if (rhsbuf != NULL)
00946 isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_RHS);
00947 return (result);
00948 }
00949
00950 static void
00951 limit_ttl(dns_rdatacallbacks_t *callbacks, const char *source,
00952 unsigned int line, isc_uint32_t *ttlp)
00953 {
00954 if (*ttlp > 0x7fffffffUL) {
00955 (callbacks->warn)(callbacks,
00956 "%s: %s:%lu: "
00957 "$TTL %lu > MAXTTL, "
00958 "setting $TTL to 0",
00959 "dns_master_load",
00960 source, line,
00961 *ttlp);
00962 *ttlp = 0;
00963 }
00964 }
00965
00966 static isc_result_t
00967 check_ns(dns_loadctx_t *lctx, isc_token_t *token, const char *source,
00968 unsigned long line)
00969 {
00970 char *tmp = NULL;
00971 isc_result_t result = ISC_R_SUCCESS;
00972 void (*callback)(struct dns_rdatacallbacks *, const char *, ...);
00973
00974 if ((lctx->options & DNS_MASTER_FATALNS) != 0)
00975 callback = lctx->callbacks->error;
00976 else
00977 callback = lctx->callbacks->warn;
00978
00979 if (token->type == isc_tokentype_string) {
00980 struct in_addr addr;
00981 struct in6_addr addr6;
00982
00983 tmp = isc_mem_strdup(lctx->mctx, DNS_AS_STR(*token));
00984 if (tmp == NULL)
00985 return (ISC_R_NOMEMORY);
00986
00987
00988
00989 if (tmp[strlen(tmp) - 1] == '.')
00990 tmp[strlen(tmp) - 1] = '\0';
00991 if (inet_aton(tmp, &addr) == 1 ||
00992 inet_pton(AF_INET6, tmp, &addr6) == 1)
00993 result = DNS_R_NSISADDRESS;
00994 }
00995 if (result != ISC_R_SUCCESS)
00996 (*callback)(lctx->callbacks, "%s:%lu: NS record '%s' "
00997 "appears to be an address",
00998 source, line, DNS_AS_STR(*token));
00999 if (tmp != NULL)
01000 isc_mem_free(lctx->mctx, tmp);
01001 return (result);
01002 }
01003
01004 static void
01005 check_wildcard(dns_incctx_t *ictx, const char *source, unsigned long line,
01006 dns_rdatacallbacks_t *callbacks)
01007 {
01008 dns_name_t *name;
01009
01010 name = (ictx->glue != NULL) ? ictx->glue : ictx->current;
01011 if (dns_name_internalwildcard(name)) {
01012 char namebuf[DNS_NAME_FORMATSIZE];
01013
01014 dns_name_format(name, namebuf, sizeof(namebuf));
01015 (*callbacks->warn)(callbacks, "%s:%lu: warning: ownername "
01016 "'%s' contains an non-terminal wildcard",
01017 source, line, namebuf);
01018 }
01019 }
01020
01021 static isc_result_t
01022 openfile_text(dns_loadctx_t *lctx, const char *master_file) {
01023 return (isc_lex_openfile(lctx->lex, master_file));
01024 }
01025
01026 static isc_result_t
01027 load_text(dns_loadctx_t *lctx) {
01028 dns_rdataclass_t rdclass;
01029 dns_rdatatype_t type, covers;
01030 isc_uint32_t ttl_offset = 0;
01031 dns_name_t *new_name;
01032 isc_boolean_t current_has_delegation = ISC_FALSE;
01033 isc_boolean_t done = ISC_FALSE;
01034 isc_boolean_t finish_origin = ISC_FALSE;
01035 isc_boolean_t finish_include = ISC_FALSE;
01036 isc_boolean_t read_till_eol = ISC_FALSE;
01037 isc_boolean_t initialws;
01038 char *include_file = NULL;
01039 isc_token_t token;
01040 isc_result_t result = ISC_R_UNEXPECTED;
01041 rdatalist_head_t glue_list;
01042 rdatalist_head_t current_list;
01043 dns_rdatalist_t *this;
01044 dns_rdatalist_t *rdatalist = NULL;
01045 dns_rdatalist_t *new_rdatalist;
01046 int rdlcount = 0;
01047 int rdlcount_save = 0;
01048 int rdatalist_size = 0;
01049 isc_buffer_t buffer;
01050 isc_buffer_t target;
01051 isc_buffer_t target_ft;
01052 isc_buffer_t target_save;
01053 dns_rdata_t *rdata = NULL;
01054 dns_rdata_t *new_rdata;
01055 int rdcount = 0;
01056 int rdcount_save = 0;
01057 int rdata_size = 0;
01058 unsigned char *target_mem = NULL;
01059 int target_size = TSIZ;
01060 int new_in_use;
01061 unsigned int loop_cnt = 0;
01062 isc_mem_t *mctx;
01063 dns_rdatacallbacks_t *callbacks;
01064 dns_incctx_t *ictx;
01065 char *range = NULL;
01066 char *lhs = NULL;
01067 char *gtype = NULL;
01068 char *rhs = NULL;
01069 const char *source = "";
01070 unsigned long line = 0;
01071 isc_boolean_t explicit_ttl;
01072 isc_stdtime_t now;
01073 char classname1[DNS_RDATACLASS_FORMATSIZE];
01074 char classname2[DNS_RDATACLASS_FORMATSIZE];
01075 unsigned int options = 0;
01076
01077 REQUIRE(DNS_LCTX_VALID(lctx));
01078 callbacks = lctx->callbacks;
01079 mctx = lctx->mctx;
01080 ictx = lctx->inc;
01081
01082 ISC_LIST_INIT(glue_list);
01083 ISC_LIST_INIT(current_list);
01084
01085 isc_stdtime_get(&now);
01086
01087
01088
01089
01090
01091 target_mem = isc_mem_get(mctx, target_size);
01092 if (target_mem == NULL) {
01093 result = ISC_R_NOMEMORY;
01094 goto log_and_cleanup;
01095 }
01096 isc_buffer_init(&target, target_mem, target_size);
01097 target_save = target;
01098
01099 if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0)
01100 options |= DNS_RDATA_CHECKNAMES;
01101 if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0)
01102 options |= DNS_RDATA_CHECKNAMESFAIL;
01103 if ((lctx->options & DNS_MASTER_CHECKMX) != 0)
01104 options |= DNS_RDATA_CHECKMX;
01105 if ((lctx->options & DNS_MASTER_CHECKMXFAIL) != 0)
01106 options |= DNS_RDATA_CHECKMXFAIL;
01107 source = isc_lex_getsourcename(lctx->lex);
01108 do {
01109 initialws = ISC_FALSE;
01110 line = isc_lex_getsourceline(lctx->lex);
01111 GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS | ISC_LEXOPT_QSTRING,
01112 &token, ISC_TRUE);
01113 line = isc_lex_getsourceline(lctx->lex);
01114
01115 if (token.type == isc_tokentype_eof) {
01116 if (read_till_eol)
01117 WARNUNEXPECTEDEOF(lctx->lex);
01118
01119 if (ictx->parent != NULL) {
01120 COMMITALL;
01121 lctx->inc = ictx->parent;
01122 ictx->parent = NULL;
01123 incctx_destroy(lctx->mctx, ictx);
01124 RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
01125 line = isc_lex_getsourceline(lctx->lex);
01126 source = isc_lex_getsourcename(lctx->lex);
01127 ictx = lctx->inc;
01128 continue;
01129 }
01130 done = ISC_TRUE;
01131 continue;
01132 }
01133
01134 if (token.type == isc_tokentype_eol) {
01135 read_till_eol = ISC_FALSE;
01136 continue;
01137 }
01138
01139 if (read_till_eol)
01140 continue;
01141
01142 if (token.type == isc_tokentype_initialws) {
01143
01144
01145
01146 initialws = ISC_TRUE;
01147 } else if (token.type == isc_tokentype_string ||
01148 token.type == isc_tokentype_qstring) {
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 if (strcasecmp(DNS_AS_STR(token), "$ORIGIN") == 0) {
01159 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
01160 finish_origin = ISC_TRUE;
01161 } else if (strcasecmp(DNS_AS_STR(token),
01162 "$TTL") == 0) {
01163 GETTOKENERR(lctx->lex, 0, &token, ISC_FALSE,
01164 lctx->ttl = 0;
01165 lctx->default_ttl_known = ISC_TRUE;);
01166 result =
01167 dns_ttl_fromtext(&token.value.as_textregion,
01168 &lctx->ttl);
01169 if (MANYERRS(lctx, result)) {
01170 SETRESULT(lctx, result);
01171 lctx->ttl = 0;
01172 } else if (result != ISC_R_SUCCESS)
01173 goto insist_and_cleanup;
01174 limit_ttl(callbacks, source, line, &lctx->ttl);
01175 lctx->default_ttl = lctx->ttl;
01176 lctx->default_ttl_known = ISC_TRUE;
01177 EXPECTEOL;
01178 continue;
01179 } else if (strcasecmp(DNS_AS_STR(token),
01180 "$INCLUDE") == 0) {
01181 COMMITALL;
01182 if ((lctx->options & DNS_MASTER_NOINCLUDE)
01183 != 0)
01184 {
01185 (callbacks->error)(callbacks,
01186 "%s: %s:%lu: $INCLUDE not allowed",
01187 "dns_master_load",
01188 source, line);
01189 result = DNS_R_REFUSED;
01190 goto insist_and_cleanup;
01191 }
01192 if (ttl_offset != 0) {
01193 (callbacks->error)(callbacks,
01194 "%s: %s:%lu: $INCLUDE "
01195 "may not be used with $DATE",
01196 "dns_master_load",
01197 source, line);
01198 result = DNS_R_SYNTAX;
01199 goto insist_and_cleanup;
01200 }
01201 GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
01202 ISC_FALSE);
01203 if (include_file != NULL)
01204 isc_mem_free(mctx, include_file);
01205 include_file = isc_mem_strdup(mctx,
01206 DNS_AS_STR(token));
01207 if (include_file == NULL) {
01208 result = ISC_R_NOMEMORY;
01209 goto log_and_cleanup;
01210 }
01211 GETTOKEN(lctx->lex, 0, &token, ISC_TRUE);
01212
01213 if (token.type == isc_tokentype_eol ||
01214 token.type == isc_tokentype_eof) {
01215 if (token.type == isc_tokentype_eof)
01216 WARNUNEXPECTEDEOF(lctx->lex);
01217
01218
01219
01220 result = pushfile(include_file,
01221 ictx->origin, lctx);
01222 if (MANYERRS(lctx, result)) {
01223 SETRESULT(lctx, result);
01224 LOGITFILE(result, include_file);
01225 continue;
01226 } else if (result != ISC_R_SUCCESS) {
01227 LOGITFILE(result, include_file);
01228 goto insist_and_cleanup;
01229 }
01230 ictx = lctx->inc;
01231 source =
01232 isc_lex_getsourcename(lctx->lex);
01233 line = isc_lex_getsourceline(lctx->lex);
01234 POST(line);
01235 continue;
01236 }
01237
01238
01239
01240
01241
01242 finish_include = ISC_TRUE;
01243 } else if (strcasecmp(DNS_AS_STR(token),
01244 "$DATE") == 0) {
01245 isc_int64_t dump_time64;
01246 isc_stdtime_t dump_time, current_time;
01247 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
01248 isc_stdtime_get(¤t_time);
01249 result = dns_time64_fromtext(DNS_AS_STR(token),
01250 &dump_time64);
01251 if (MANYERRS(lctx, result)) {
01252 SETRESULT(lctx, result);
01253 LOGIT(result);
01254 dump_time64 = 0;
01255 } else if (result != ISC_R_SUCCESS)
01256 goto log_and_cleanup;
01257 dump_time = (isc_stdtime_t)dump_time64;
01258 if (dump_time != dump_time64) {
01259 UNEXPECTED_ERROR(__FILE__, __LINE__,
01260 "%s: %s:%lu: $DATE outside epoch",
01261 "dns_master_load", source, line);
01262 result = ISC_R_UNEXPECTED;
01263 goto insist_and_cleanup;
01264 }
01265 if (dump_time > current_time) {
01266 UNEXPECTED_ERROR(__FILE__, __LINE__,
01267 "%s: %s:%lu: "
01268 "$DATE in future, using current date",
01269 "dns_master_load", source, line);
01270 dump_time = current_time;
01271 }
01272 ttl_offset = current_time - dump_time;
01273 EXPECTEOL;
01274 continue;
01275 } else if (strcasecmp(DNS_AS_STR(token),
01276 "$GENERATE") == 0) {
01277
01278
01279
01280 if (range != NULL)
01281 isc_mem_free(mctx, range);
01282 if (lhs != NULL)
01283 isc_mem_free(mctx, lhs);
01284 if (gtype != NULL)
01285 isc_mem_free(mctx, gtype);
01286 if (rhs != NULL)
01287 isc_mem_free(mctx, rhs);
01288 range = lhs = gtype = rhs = NULL;
01289
01290 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
01291 range = isc_mem_strdup(mctx,
01292 DNS_AS_STR(token));
01293 if (range == NULL) {
01294 result = ISC_R_NOMEMORY;
01295 goto log_and_cleanup;
01296 }
01297
01298 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
01299 lhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
01300 if (lhs == NULL) {
01301 result = ISC_R_NOMEMORY;
01302 goto log_and_cleanup;
01303 }
01304 rdclass = 0;
01305 explicit_ttl = ISC_FALSE;
01306
01307 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
01308 if (dns_rdataclass_fromtext(&rdclass,
01309 &token.value.as_textregion)
01310 == ISC_R_SUCCESS) {
01311 GETTOKEN(lctx->lex, 0, &token,
01312 ISC_FALSE);
01313 }
01314
01315 if (dns_ttl_fromtext(&token.value.as_textregion,
01316 &lctx->ttl)
01317 == ISC_R_SUCCESS) {
01318 limit_ttl(callbacks, source, line,
01319 &lctx->ttl);
01320 lctx->ttl_known = ISC_TRUE;
01321 explicit_ttl = ISC_TRUE;
01322 GETTOKEN(lctx->lex, 0, &token,
01323 ISC_FALSE);
01324 }
01325
01326 if (rdclass == 0 &&
01327 dns_rdataclass_fromtext(&rdclass,
01328 &token.value.as_textregion)
01329 == ISC_R_SUCCESS)
01330 GETTOKEN(lctx->lex, 0, &token,
01331 ISC_FALSE);
01332
01333 gtype = isc_mem_strdup(mctx,
01334 DNS_AS_STR(token));
01335 if (gtype == NULL) {
01336 result = ISC_R_NOMEMORY;
01337 goto log_and_cleanup;
01338 }
01339
01340 GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING,
01341 &token, ISC_FALSE);
01342 rhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
01343 if (rhs == NULL) {
01344 result = ISC_R_NOMEMORY;
01345 goto log_and_cleanup;
01346 }
01347 if (!lctx->ttl_known &&
01348 !lctx->default_ttl_known) {
01349 (*callbacks->error)(callbacks,
01350 "%s: %s:%lu: no TTL specified",
01351 "dns_master_load", source, line);
01352 result = DNS_R_NOTTL;
01353 if (MANYERRS(lctx, result)) {
01354 SETRESULT(lctx, result);
01355 lctx->ttl = 0;
01356 } else if (result != ISC_R_SUCCESS)
01357 goto insist_and_cleanup;
01358 } else if (!explicit_ttl &&
01359 lctx->default_ttl_known) {
01360 lctx->ttl = lctx->default_ttl;
01361 }
01362
01363
01364
01365
01366
01367 if (rdclass != 0 && rdclass != lctx->zclass) {
01368 goto bad_class;
01369 }
01370 result = generate(lctx, range, lhs, gtype, rhs,
01371 source, line);
01372 if (MANYERRS(lctx, result)) {
01373 SETRESULT(lctx, result);
01374 } else if (result != ISC_R_SUCCESS)
01375 goto insist_and_cleanup;
01376 EXPECTEOL;
01377 continue;
01378 } else if (strncasecmp(DNS_AS_STR(token),
01379 "$", 1) == 0) {
01380 (callbacks->error)(callbacks,
01381 "%s: %s:%lu: "
01382 "unknown $ directive '%s'",
01383 "dns_master_load", source, line,
01384 DNS_AS_STR(token));
01385 result = DNS_R_SYNTAX;
01386 if (MANYERRS(lctx, result)) {
01387 SETRESULT(lctx, result);
01388 } else if (result != ISC_R_SUCCESS)
01389 goto insist_and_cleanup;
01390 }
01391
01392
01393
01394
01395
01396
01397 for (new_in_use = 0; new_in_use < NBUFS; new_in_use++)
01398 if (!ictx->in_use[new_in_use])
01399 break;
01400 INSIST(new_in_use < NBUFS);
01401 dns_fixedname_init(&ictx->fixed[new_in_use]);
01402 new_name = dns_fixedname_name(&ictx->fixed[new_in_use]);
01403 isc_buffer_init(&buffer, token.value.as_region.base,
01404 token.value.as_region.length);
01405 isc_buffer_add(&buffer, token.value.as_region.length);
01406 isc_buffer_setactive(&buffer,
01407 token.value.as_region.length);
01408 result = dns_name_fromtext(new_name, &buffer,
01409 ictx->origin, 0, NULL);
01410 if (MANYERRS(lctx, result)) {
01411 SETRESULT(lctx, result);
01412 LOGIT(result);
01413 read_till_eol = ISC_TRUE;
01414 continue;
01415 } else if (result != ISC_R_SUCCESS)
01416 goto log_and_cleanup;
01417
01418
01419
01420
01421 if (finish_origin) {
01422 if (ictx->origin_in_use != -1)
01423 ictx->in_use[ictx->origin_in_use] =
01424 ISC_FALSE;
01425 ictx->origin_in_use = new_in_use;
01426 ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
01427 ictx->origin = new_name;
01428 ictx->origin_changed = ISC_TRUE;
01429 finish_origin = ISC_FALSE;
01430 EXPECTEOL;
01431 continue;
01432 }
01433 if (finish_include) {
01434 finish_include = ISC_FALSE;
01435 EXPECTEOL;
01436 result = pushfile(include_file, new_name, lctx);
01437 if (MANYERRS(lctx, result)) {
01438 SETRESULT(lctx, result);
01439 LOGITFILE(result, include_file);
01440 continue;
01441 } else if (result != ISC_R_SUCCESS) {
01442 LOGITFILE(result, include_file);
01443 goto insist_and_cleanup;
01444 }
01445 ictx = lctx->inc;
01446 ictx->origin_changed = ISC_TRUE;
01447 source = isc_lex_getsourcename(lctx->lex);
01448 line = isc_lex_getsourceline(lctx->lex);
01449 POST(line);
01450 continue;
01451 }
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463 if (ictx->glue != NULL &&
01464 dns_name_compare(ictx->glue, new_name) != 0) {
01465 result = commit(callbacks, lctx, &glue_list,
01466 ictx->glue, source,
01467 ictx->glue_line);
01468 if (MANYERRS(lctx, result)) {
01469 SETRESULT(lctx, result);
01470 } else if (result != ISC_R_SUCCESS)
01471 goto insist_and_cleanup;
01472 if (ictx->glue_in_use != -1)
01473 ictx->in_use[ictx->glue_in_use] =
01474 ISC_FALSE;
01475 ictx->glue_in_use = -1;
01476 ictx->glue = NULL;
01477 rdcount = rdcount_save;
01478 rdlcount = rdlcount_save;
01479 target = target_save;
01480 }
01481
01482
01483
01484
01485
01486
01487
01488
01489 if ((ictx->glue == NULL) && (ictx->current == NULL ||
01490 dns_name_compare(ictx->current, new_name) != 0)) {
01491 if (current_has_delegation &&
01492 is_glue(¤t_list, new_name)) {
01493 rdcount_save = rdcount;
01494 rdlcount_save = rdlcount;
01495 target_save = target;
01496 ictx->glue = new_name;
01497 ictx->glue_in_use = new_in_use;
01498 ictx->in_use[ictx->glue_in_use] =
01499 ISC_TRUE;
01500 } else {
01501 result = commit(callbacks, lctx,
01502 ¤t_list,
01503 ictx->current,
01504 source,
01505 ictx->current_line);
01506 if (MANYERRS(lctx, result)) {
01507 SETRESULT(lctx, result);
01508 } else if (result != ISC_R_SUCCESS)
01509 goto insist_and_cleanup;
01510 rdcount = 0;
01511 rdlcount = 0;
01512 if (ictx->current_in_use != -1)
01513 ictx->in_use[ictx->current_in_use] =
01514 ISC_FALSE;
01515 ictx->current_in_use = new_in_use;
01516 ictx->in_use[ictx->current_in_use] =
01517 ISC_TRUE;
01518 ictx->current = new_name;
01519 current_has_delegation = ISC_FALSE;
01520 isc_buffer_init(&target, target_mem,
01521 target_size);
01522 }
01523
01524
01525
01526 if ((lctx->options & DNS_MASTER_CHECKWILDCARD)
01527 != 0)
01528 check_wildcard(ictx, source, line,
01529 callbacks);
01530
01531 }
01532 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
01533 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
01534 (lctx->options & DNS_MASTER_KEY) == 0 &&
01535 !dns_name_issubdomain(new_name, lctx->top))
01536 {
01537 char namebuf[DNS_NAME_FORMATSIZE];
01538 dns_name_format(new_name, namebuf,
01539 sizeof(namebuf));
01540
01541
01542
01543 (*callbacks->warn)(callbacks,
01544 "%s:%lu: "
01545 "ignoring out-of-zone data (%s)",
01546 source, line, namebuf);
01547 ictx->drop = ISC_TRUE;
01548 } else
01549 ictx->drop = ISC_FALSE;
01550 } else {
01551 UNEXPECTED_ERROR(__FILE__, __LINE__,
01552 "%s:%lu: isc_lex_gettoken() returned "
01553 "unexpected token type (%d)",
01554 source, line, token.type);
01555 result = ISC_R_UNEXPECTED;
01556 if (MANYERRS(lctx, result)) {
01557 SETRESULT(lctx, result);
01558 LOGIT(result);
01559 continue;
01560 } else if (result != ISC_R_SUCCESS)
01561 goto insist_and_cleanup;
01562 }
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573 type = 0;
01574 rdclass = 0;
01575
01576 GETTOKEN(lctx->lex, 0, &token, initialws);
01577
01578 if (initialws) {
01579 if (token.type == isc_tokentype_eol) {
01580 read_till_eol = ISC_FALSE;
01581 continue;
01582 }
01583
01584 if (token.type == isc_tokentype_eof) {
01585 WARNUNEXPECTEDEOF(lctx->lex);
01586 read_till_eol = ISC_FALSE;
01587 isc_lex_ungettoken(lctx->lex, &token);
01588 continue;
01589 }
01590
01591 if (ictx->current == NULL) {
01592 (*callbacks->error)(callbacks,
01593 "%s:%lu: no current owner name",
01594 source, line);
01595 result = DNS_R_NOOWNER;
01596 if (MANYERRS(lctx, result)) {
01597 SETRESULT(lctx, result);
01598 read_till_eol = ISC_TRUE;
01599 continue;
01600 } else if (result != ISC_R_SUCCESS)
01601 goto insist_and_cleanup;
01602 }
01603
01604 if (ictx->origin_changed) {
01605 char cbuf[DNS_NAME_FORMATSIZE];
01606 char obuf[DNS_NAME_FORMATSIZE];
01607 dns_name_format(ictx->current, cbuf,
01608 sizeof(cbuf));
01609 dns_name_format(ictx->origin, obuf,
01610 sizeof(obuf));
01611 (*callbacks->warn)(callbacks,
01612 "%s:%lu: record with inherited "
01613 "owner (%s) immediately after "
01614 "$ORIGIN (%s)", source, line,
01615 cbuf, obuf);
01616 }
01617 }
01618
01619 ictx->origin_changed = ISC_FALSE;
01620
01621 if (dns_rdataclass_fromtext(&rdclass,
01622 &token.value.as_textregion)
01623 == ISC_R_SUCCESS)
01624 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
01625
01626 explicit_ttl = ISC_FALSE;
01627 result = dns_ttl_fromtext(&token.value.as_textregion,
01628 &lctx->ttl);
01629 if (result == ISC_R_SUCCESS) {
01630 limit_ttl(callbacks, source, line, &lctx->ttl);
01631 explicit_ttl = ISC_TRUE;
01632 lctx->ttl_known = ISC_TRUE;
01633 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
01634 }
01635
01636 if (token.type != isc_tokentype_string) {
01637 UNEXPECTED_ERROR(__FILE__, __LINE__,
01638 "isc_lex_gettoken() returned unexpected token type");
01639 result = ISC_R_UNEXPECTED;
01640 if (MANYERRS(lctx, result)) {
01641 SETRESULT(lctx, result);
01642 read_till_eol = ISC_TRUE;
01643 continue;
01644 } else if (result != ISC_R_SUCCESS)
01645 goto insist_and_cleanup;
01646 }
01647
01648 if (rdclass == 0 &&
01649 dns_rdataclass_fromtext(&rdclass,
01650 &token.value.as_textregion)
01651 == ISC_R_SUCCESS)
01652 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
01653
01654 if (token.type != isc_tokentype_string) {
01655 UNEXPECTED_ERROR(__FILE__, __LINE__,
01656 "isc_lex_gettoken() returned unexpected token type");
01657 result = ISC_R_UNEXPECTED;
01658 if (MANYERRS(lctx, result)) {
01659 SETRESULT(lctx, result);
01660 read_till_eol = ISC_TRUE;
01661 continue;
01662 } else if (result != ISC_R_SUCCESS)
01663 goto insist_and_cleanup;
01664 }
01665
01666 result = dns_rdatatype_fromtext(&type,
01667 &token.value.as_textregion);
01668 if (result != ISC_R_SUCCESS) {
01669 (*callbacks->warn)(callbacks,
01670 "%s:%lu: unknown RR type '%.*s'",
01671 source, line,
01672 token.value.as_textregion.length,
01673 token.value.as_textregion.base);
01674 if (MANYERRS(lctx, result)) {
01675 SETRESULT(lctx, result);
01676 read_till_eol = ISC_TRUE;
01677 continue;
01678 } else if (result != ISC_R_SUCCESS)
01679 goto insist_and_cleanup;
01680 }
01681
01682
01683
01684
01685
01686 if (rdclass != 0 && rdclass != lctx->zclass) {
01687 bad_class:
01688
01689 dns_rdataclass_format(rdclass, classname1,
01690 sizeof(classname1));
01691 dns_rdataclass_format(lctx->zclass, classname2,
01692 sizeof(classname2));
01693 (*callbacks->error)(callbacks,
01694 "%s:%lu: class '%s' != "
01695 "zone class '%s'",
01696 source, line,
01697 classname1, classname2);
01698 result = DNS_R_BADCLASS;
01699 if (MANYERRS(lctx, result)) {
01700 SETRESULT(lctx, result);
01701 read_till_eol = ISC_TRUE;
01702 continue;
01703 } else if (result != ISC_R_SUCCESS)
01704 goto insist_and_cleanup;
01705 }
01706
01707 if (type == dns_rdatatype_ns && ictx->glue == NULL)
01708 current_has_delegation = ISC_TRUE;
01709
01710
01711
01712
01713
01714 if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
01715 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
01716 (type == dns_rdatatype_md || type == dns_rdatatype_mf)) {
01717 char typename[DNS_RDATATYPE_FORMATSIZE];
01718
01719 result = DNS_R_OBSOLETE;
01720
01721 dns_rdatatype_format(type, typename, sizeof(typename));
01722 (*callbacks->error)(callbacks,
01723 "%s:%lu: %s '%s': %s",
01724 source, line,
01725 "type", typename,
01726 dns_result_totext(result));
01727 if (MANYERRS(lctx, result)) {
01728 SETRESULT(lctx, result);
01729 } else
01730 goto insist_and_cleanup;
01731 }
01732
01733
01734
01735
01736 if (rdcount == rdata_size) {
01737 new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
01738 rdata_size, ¤t_list,
01739 &glue_list, mctx);
01740 if (new_rdata == NULL) {
01741 result = ISC_R_NOMEMORY;
01742 goto log_and_cleanup;
01743 }
01744 rdata_size += RDSZ;
01745 rdata = new_rdata;
01746 }
01747
01748
01749
01750
01751 if (type == dns_rdatatype_ns &&
01752 lctx->zclass == dns_rdataclass_in &&
01753 (lctx->options & DNS_MASTER_CHECKNS) != 0) {
01754
01755 GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
01756 result = check_ns(lctx, &token, source, line);
01757 isc_lex_ungettoken(lctx->lex, &token);
01758 if ((lctx->options & DNS_MASTER_FATALNS) != 0) {
01759 if (MANYERRS(lctx, result)) {
01760 SETRESULT(lctx, result);
01761 } else if (result != ISC_R_SUCCESS)
01762 goto insist_and_cleanup;
01763 }
01764 }
01765
01766
01767
01768
01769 options &= ~DNS_RDATA_CHECKREVERSE;
01770 if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0) {
01771 isc_boolean_t ok;
01772 dns_name_t *name;
01773
01774 name = (ictx->glue != NULL) ? ictx->glue :
01775 ictx->current;
01776 ok = dns_rdata_checkowner(name, lctx->zclass, type,
01777 ISC_TRUE);
01778 if (!ok) {
01779 char namebuf[DNS_NAME_FORMATSIZE];
01780 const char *desc;
01781 dns_name_format(name, namebuf, sizeof(namebuf));
01782 result = DNS_R_BADOWNERNAME;
01783 desc = dns_result_totext(result);
01784 if (CHECKNAMESFAIL(lctx->options) ||
01785 type == dns_rdatatype_nsec3) {
01786 (*callbacks->error)(callbacks,
01787 "%s:%lu: %s: %s",
01788 source, line,
01789 namebuf, desc);
01790 if (MANYERRS(lctx, result)) {
01791 SETRESULT(lctx, result);
01792 } else if (result != ISC_R_SUCCESS)
01793 goto cleanup;
01794 } else {
01795 (*callbacks->warn)(callbacks,
01796 "%s:%lu: %s: %s",
01797 source, line,
01798 namebuf, desc);
01799 }
01800 }
01801 if (type == dns_rdatatype_ptr &&
01802 (dns_name_issubdomain(name, &in_addr_arpa) ||
01803 dns_name_issubdomain(name, &ip6_arpa) ||
01804 dns_name_issubdomain(name, &ip6_int)))
01805 options |= DNS_RDATA_CHECKREVERSE;
01806 }
01807
01808
01809
01810
01811 dns_rdata_init(&rdata[rdcount]);
01812 target_ft = target;
01813 result = dns_rdata_fromtext(&rdata[rdcount], lctx->zclass,
01814 type, lctx->lex, ictx->origin,
01815 options, lctx->mctx, &target,
01816 callbacks);
01817 if (MANYERRS(lctx, result)) {
01818 SETRESULT(lctx, result);
01819 continue;
01820 } else if (result != ISC_R_SUCCESS)
01821 goto insist_and_cleanup;
01822
01823 if (ictx->drop) {
01824 target = target_ft;
01825 continue;
01826 }
01827
01828 if (type == dns_rdatatype_soa &&
01829 (lctx->options & DNS_MASTER_ZONE) != 0 &&
01830 dns_name_compare(ictx->current, lctx->top) != 0) {
01831 char namebuf[DNS_NAME_FORMATSIZE];
01832 dns_name_format(ictx->current, namebuf,
01833 sizeof(namebuf));
01834 (*callbacks->error)(callbacks, "%s:%lu: SOA "
01835 "record not at top of zone (%s)",
01836 source, line, namebuf);
01837 result = DNS_R_NOTZONETOP;
01838 if (MANYERRS(lctx, result)) {
01839 SETRESULT(lctx, result);
01840 read_till_eol = ISC_TRUE;
01841 target = target_ft;
01842 continue;
01843 } else if (result != ISC_R_SUCCESS)
01844 goto insist_and_cleanup;
01845 }
01846
01847 if (type == dns_rdatatype_rrsig ||
01848 type == dns_rdatatype_sig)
01849 covers = dns_rdata_covers(&rdata[rdcount]);
01850 else
01851 covers = 0;
01852
01853 if (!lctx->ttl_known && !lctx->default_ttl_known) {
01854 if (type == dns_rdatatype_soa) {
01855 (*callbacks->warn)(callbacks,
01856 "%s:%lu: no TTL specified; "
01857 "using SOA MINTTL instead",
01858 source, line);
01859 lctx->ttl = dns_soa_getminimum(&rdata[rdcount]);
01860 limit_ttl(callbacks, source, line, &lctx->ttl);
01861 lctx->default_ttl = lctx->ttl;
01862 lctx->default_ttl_known = ISC_TRUE;
01863 } else if ((lctx->options & DNS_MASTER_HINT) != 0) {
01864
01865
01866
01867 lctx->ttl = 0;
01868 lctx->default_ttl = lctx->ttl;
01869 lctx->default_ttl_known = ISC_TRUE;
01870 } else {
01871 (*callbacks->warn)(callbacks,
01872 "%s:%lu: no TTL specified; "
01873 "zone rejected",
01874 source, line);
01875 result = DNS_R_NOTTL;
01876 if (MANYERRS(lctx, result)) {
01877 SETRESULT(lctx, result);
01878 lctx->ttl = 0;
01879 } else {
01880 goto insist_and_cleanup;
01881 }
01882 }
01883 } else if (!explicit_ttl && lctx->default_ttl_known) {
01884 lctx->ttl = lctx->default_ttl;
01885 } else if (!explicit_ttl && lctx->warn_1035) {
01886 (*callbacks->warn)(callbacks,
01887 "%s:%lu: "
01888 "using RFC1035 TTL semantics",
01889 source, line);
01890 lctx->warn_1035 = ISC_FALSE;
01891 }
01892
01893 if (type == dns_rdatatype_rrsig && lctx->warn_sigexpired) {
01894 dns_rdata_rrsig_t sig;
01895 result = dns_rdata_tostruct(&rdata[rdcount], &sig,
01896 NULL);
01897 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01898 if (isc_serial_lt(sig.timeexpire, now)) {
01899 (*callbacks->warn)(callbacks,
01900 "%s:%lu: "
01901 "signature has expired",
01902 source, line);
01903 lctx->warn_sigexpired = ISC_FALSE;
01904 }
01905 }
01906
01907 if ((type == dns_rdatatype_sig || type == dns_rdatatype_nxt) &&
01908 lctx->warn_tcr && (lctx->options & DNS_MASTER_ZONE) != 0 &&
01909 (lctx->options & DNS_MASTER_SLAVE) == 0) {
01910 (*callbacks->warn)(callbacks, "%s:%lu: old style DNSSEC "
01911 " zone detected", source, line);
01912 lctx->warn_tcr = ISC_FALSE;
01913 }
01914
01915 if ((lctx->options & DNS_MASTER_AGETTL) != 0) {
01916
01917
01918
01919
01920 if (lctx->ttl < ttl_offset)
01921 continue;
01922 lctx->ttl -= ttl_offset;
01923 }
01924
01925
01926
01927
01928
01929
01930 if (ictx->glue != NULL)
01931 this = ISC_LIST_HEAD(glue_list);
01932 else
01933 this = ISC_LIST_HEAD(current_list);
01934
01935 while (this != NULL) {
01936 if (this->type == type && this->covers == covers)
01937 break;
01938 this = ISC_LIST_NEXT(this, link);
01939 }
01940
01941 if (this == NULL) {
01942 if (rdlcount == rdatalist_size) {
01943 new_rdatalist =
01944 grow_rdatalist(rdatalist_size + RDLSZ,
01945 rdatalist,
01946 rdatalist_size,
01947 ¤t_list,
01948 &glue_list,
01949 mctx);
01950 if (new_rdatalist == NULL) {
01951 result = ISC_R_NOMEMORY;
01952 goto log_and_cleanup;
01953 }
01954 rdatalist = new_rdatalist;
01955 rdatalist_size += RDLSZ;
01956 }
01957 this = &rdatalist[rdlcount++];
01958 dns_rdatalist_init(this);
01959 this->type = type;
01960 this->covers = covers;
01961 this->rdclass = lctx->zclass;
01962 this->ttl = lctx->ttl;
01963 if (ictx->glue != NULL)
01964 ISC_LIST_INITANDPREPEND(glue_list, this, link);
01965 else
01966 ISC_LIST_INITANDPREPEND(current_list, this,
01967 link);
01968 } else if (this->ttl != lctx->ttl) {
01969 (*callbacks->warn)(callbacks,
01970 "%s:%lu: "
01971 "TTL set to prior TTL (%lu)",
01972 source, line, this->ttl);
01973 lctx->ttl = this->ttl;
01974 }
01975
01976 if ((lctx->options & DNS_MASTER_CHECKTTL) != 0 &&
01977 lctx->ttl > lctx->maxttl)
01978 {
01979 (callbacks->error)(callbacks,
01980 "dns_master_load: %s:%lu: "
01981 "TTL %d exceeds configured max-zone-ttl %d",
01982 source, line, lctx->ttl, lctx->maxttl);
01983 result = ISC_R_RANGE;
01984 goto log_and_cleanup;
01985 }
01986
01987 ISC_LIST_APPEND(this->rdata, &rdata[rdcount], link);
01988 if (ictx->glue != NULL)
01989 ictx->glue_line = line;
01990 else
01991 ictx->current_line = line;
01992 rdcount++;
01993
01994
01995
01996
01997
01998 if ((target.length - target.used) < MINTSIZ)
01999 COMMITALL;
02000 next_line:
02001 ;
02002 } while (!done && (lctx->loop_cnt == 0 || loop_cnt++ < lctx->loop_cnt));
02003
02004
02005
02006
02007 result = commit(callbacks, lctx, ¤t_list, ictx->current,
02008 source, ictx->current_line);
02009 if (MANYERRS(lctx, result)) {
02010 SETRESULT(lctx, result);
02011 } else if (result != ISC_R_SUCCESS)
02012 goto insist_and_cleanup;
02013 result = commit(callbacks, lctx, &glue_list, ictx->glue,
02014 source, ictx->glue_line);
02015 if (MANYERRS(lctx, result)) {
02016 SETRESULT(lctx, result);
02017 } else if (result != ISC_R_SUCCESS)
02018 goto insist_and_cleanup;
02019
02020 if (!done) {
02021 INSIST(lctx->done != NULL && lctx->task != NULL);
02022 result = DNS_R_CONTINUE;
02023 } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) {
02024 result = lctx->result;
02025 } else if (result == ISC_R_SUCCESS && lctx->seen_include)
02026 result = DNS_R_SEENINCLUDE;
02027 goto cleanup;
02028
02029 log_and_cleanup:
02030 LOGIT(result);
02031
02032 insist_and_cleanup:
02033 INSIST(result != ISC_R_SUCCESS);
02034
02035 cleanup:
02036 while ((this = ISC_LIST_HEAD(current_list)) != NULL)
02037 ISC_LIST_UNLINK(current_list, this, link);
02038 while ((this = ISC_LIST_HEAD(glue_list)) != NULL)
02039 ISC_LIST_UNLINK(glue_list, this, link);
02040 if (rdatalist != NULL)
02041 isc_mem_put(mctx, rdatalist,
02042 rdatalist_size * sizeof(*rdatalist));
02043 if (rdata != NULL)
02044 isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
02045 if (target_mem != NULL)
02046 isc_mem_put(mctx, target_mem, target_size);
02047 if (include_file != NULL)
02048 isc_mem_free(mctx, include_file);
02049 if (range != NULL)
02050 isc_mem_free(mctx, range);
02051 if (lhs != NULL)
02052 isc_mem_free(mctx, lhs);
02053 if (gtype != NULL)
02054 isc_mem_free(mctx, gtype);
02055 if (rhs != NULL)
02056 isc_mem_free(mctx, rhs);
02057 return (result);
02058 }
02059
02060 static isc_result_t
02061 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) {
02062 isc_result_t result;
02063 dns_incctx_t *ictx;
02064 dns_incctx_t *new = NULL;
02065 isc_region_t r;
02066 int new_in_use;
02067
02068 REQUIRE(master_file != NULL);
02069 REQUIRE(DNS_LCTX_VALID(lctx));
02070
02071 ictx = lctx->inc;
02072 lctx->seen_include = ISC_TRUE;
02073
02074 result = incctx_create(lctx->mctx, origin, &new);
02075 if (result != ISC_R_SUCCESS)
02076 return (result);
02077
02078
02079
02080
02081 new->origin_changed = ictx->origin_changed;
02082
02083
02084 if (ictx->glue != NULL || ictx->current != NULL) {
02085 for (new_in_use = 0; new_in_use < NBUFS; new_in_use++)
02086 if (!new->in_use[new_in_use])
02087 break;
02088 INSIST(new_in_use < NBUFS);
02089 new->current_in_use = new_in_use;
02090 new->current =
02091 dns_fixedname_name(&new->fixed[new->current_in_use]);
02092 new->in_use[new->current_in_use] = ISC_TRUE;
02093 dns_name_toregion((ictx->glue != NULL) ?
02094 ictx->glue : ictx->current, &r);
02095 dns_name_fromregion(new->current, &r);
02096 new->drop = ictx->drop;
02097 }
02098
02099 result = (lctx->openfile)(lctx, master_file);
02100 if (result != ISC_R_SUCCESS)
02101 goto cleanup;
02102 new->parent = ictx;
02103 lctx->inc = new;
02104
02105 if (lctx->include_cb != NULL)
02106 lctx->include_cb(master_file, lctx->include_arg);
02107 return (ISC_R_SUCCESS);
02108
02109 cleanup:
02110 incctx_destroy(lctx->mctx, new);
02111 return (result);
02112 }
02113
02114 static inline isc_result_t
02115 read_and_check(isc_boolean_t do_read, isc_buffer_t *buffer,
02116 size_t len, FILE *f)
02117 {
02118 isc_result_t result;
02119
02120 if (do_read) {
02121 INSIST(isc_buffer_availablelength(buffer) >= len);
02122 result = isc_stdio_read(isc_buffer_used(buffer), 1, len,
02123 f, NULL);
02124 if (result != ISC_R_SUCCESS)
02125 return (result);
02126 isc_buffer_add(buffer, (unsigned int)len);
02127 } else if (isc_buffer_remaininglength(buffer) < len)
02128 return (ISC_R_RANGE);
02129
02130 return (ISC_R_SUCCESS);
02131 }
02132
02133 static isc_result_t
02134 load_header(dns_loadctx_t *lctx) {
02135 isc_result_t result = ISC_R_SUCCESS;
02136 dns_masterrawheader_t header;
02137 dns_rdatacallbacks_t *callbacks;
02138 size_t commonlen = sizeof(header.format) + sizeof(header.version);
02139 size_t remainder;
02140 unsigned char data[sizeof(header)];
02141 isc_buffer_t target;
02142
02143 REQUIRE(DNS_LCTX_VALID(lctx));
02144
02145 if (lctx->format != dns_masterformat_raw &&
02146 lctx->format != dns_masterformat_map)
02147 return (ISC_R_NOTIMPLEMENTED);
02148
02149 callbacks = lctx->callbacks;
02150 dns_master_initrawheader(&header);
02151
02152 INSIST(commonlen <= sizeof(header));
02153 isc_buffer_init(&target, data, sizeof(data));
02154
02155 result = isc_stdio_read(data, 1, commonlen, lctx->f, NULL);
02156 if (result != ISC_R_SUCCESS) {
02157 UNEXPECTED_ERROR(__FILE__, __LINE__,
02158 "isc_stdio_read failed: %s",
02159 isc_result_totext(result));
02160 return (result);
02161 }
02162
02163 isc_buffer_add(&target, (unsigned int)commonlen);
02164 header.format = isc_buffer_getuint32(&target);
02165 if (header.format != lctx->format) {
02166 (*callbacks->error)(callbacks, "dns_master_load: "
02167 "file format mismatch (not %s)",
02168 lctx->format == dns_masterformat_map
02169 ? "map"
02170 : "raw");
02171 return (ISC_R_NOTIMPLEMENTED);
02172 }
02173
02174 header.version = isc_buffer_getuint32(&target);
02175
02176 switch (header.version) {
02177 case 0:
02178 remainder = sizeof(header.dumptime);
02179 break;
02180 case DNS_RAWFORMAT_VERSION:
02181 remainder = sizeof(header) - commonlen;
02182 break;
02183 default:
02184 (*callbacks->error)(callbacks,
02185 "dns_master_load: "
02186 "unsupported file format version");
02187 return (ISC_R_NOTIMPLEMENTED);
02188 }
02189
02190 result = isc_stdio_read(data + commonlen, 1, remainder, lctx->f, NULL);
02191 if (result != ISC_R_SUCCESS) {
02192 UNEXPECTED_ERROR(__FILE__, __LINE__,
02193 "isc_stdio_read failed: %s",
02194 isc_result_totext(result));
02195 return (result);
02196 }
02197
02198 isc_buffer_add(&target, (unsigned int)remainder);
02199 header.dumptime = isc_buffer_getuint32(&target);
02200 if (header.version == DNS_RAWFORMAT_VERSION) {
02201 header.flags = isc_buffer_getuint32(&target);
02202 header.sourceserial = isc_buffer_getuint32(&target);
02203 header.lastxfrin = isc_buffer_getuint32(&target);
02204 }
02205
02206 lctx->first = ISC_FALSE;
02207 lctx->header = header;
02208
02209 return (ISC_R_SUCCESS);
02210 }
02211
02212 static isc_result_t
02213 openfile_map(dns_loadctx_t *lctx, const char *master_file) {
02214 isc_result_t result;
02215
02216 result = isc_stdio_open(master_file, "rb", &lctx->f);
02217 if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
02218 UNEXPECTED_ERROR(__FILE__, __LINE__,
02219 "isc_stdio_open() failed: %s",
02220 isc_result_totext(result));
02221 }
02222
02223 return (result);
02224 }
02225
02226
02227
02228
02229 static isc_result_t
02230 load_map(dns_loadctx_t *lctx) {
02231 isc_result_t result = ISC_R_SUCCESS;
02232 dns_rdatacallbacks_t *callbacks;
02233
02234 REQUIRE(DNS_LCTX_VALID(lctx));
02235
02236 callbacks = lctx->callbacks;
02237
02238 if (lctx->first) {
02239 result = load_header(lctx);
02240 if (result != ISC_R_SUCCESS)
02241 return (result);
02242
02243 result = (*callbacks->deserialize)
02244 (callbacks->deserialize_private,
02245 lctx->f, sizeof(dns_masterrawheader_t));
02246 }
02247
02248 return (result);
02249 }
02250
02251 static isc_result_t
02252 openfile_raw(dns_loadctx_t *lctx, const char *master_file) {
02253 isc_result_t result;
02254
02255 result = isc_stdio_open(master_file, "rb", &lctx->f);
02256 if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
02257 UNEXPECTED_ERROR(__FILE__, __LINE__,
02258 "isc_stdio_open() failed: %s",
02259 isc_result_totext(result));
02260 }
02261
02262 return (result);
02263 }
02264
02265 static isc_result_t
02266 load_raw(dns_loadctx_t *lctx) {
02267 isc_result_t result = ISC_R_SUCCESS;
02268 isc_boolean_t done = ISC_FALSE;
02269 unsigned int loop_cnt = 0;
02270 dns_rdatacallbacks_t *callbacks;
02271 unsigned char namebuf[DNS_NAME_MAXWIRE];
02272 dns_fixedname_t fixed;
02273 dns_name_t *name;
02274 rdatalist_head_t head, dummy;
02275 dns_rdatalist_t rdatalist;
02276 isc_mem_t *mctx = lctx->mctx;
02277 dns_rdata_t *rdata = NULL;
02278 unsigned int rdata_size = 0;
02279 int target_size = TSIZ;
02280 isc_buffer_t target, buf;
02281 unsigned char *target_mem = NULL;
02282 dns_decompress_t dctx;
02283
02284 REQUIRE(DNS_LCTX_VALID(lctx));
02285 callbacks = lctx->callbacks;
02286 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
02287
02288 if (lctx->first) {
02289 result = load_header(lctx);
02290 if (result != ISC_R_SUCCESS)
02291 return (result);
02292 }
02293
02294 ISC_LIST_INIT(head);
02295 ISC_LIST_INIT(dummy);
02296
02297
02298
02299
02300
02301 target_mem = isc_mem_get(mctx, target_size);
02302 if (target_mem == NULL) {
02303 result = ISC_R_NOMEMORY;
02304 goto cleanup;
02305 }
02306 isc_buffer_init(&target, target_mem, target_size);
02307
02308 dns_fixedname_init(&fixed);
02309 name = dns_fixedname_name(&fixed);
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319 for (loop_cnt = 0;
02320 (lctx->loop_cnt == 0 || loop_cnt < lctx->loop_cnt);
02321 loop_cnt++) {
02322 unsigned int i, rdcount;
02323 isc_uint16_t namelen;
02324 isc_uint32_t totallen;
02325 size_t minlen, readlen;
02326 isc_boolean_t sequential_read = ISC_FALSE;
02327
02328
02329 isc_buffer_clear(&target);
02330 INSIST(isc_buffer_availablelength(&target) >=
02331 sizeof(totallen));
02332 result = isc_stdio_read(target.base, 1, sizeof(totallen),
02333 lctx->f, NULL);
02334 if (result == ISC_R_EOF) {
02335 result = ISC_R_SUCCESS;
02336 done = ISC_TRUE;
02337 break;
02338 }
02339 if (result != ISC_R_SUCCESS)
02340 goto cleanup;
02341 isc_buffer_add(&target, sizeof(totallen));
02342 totallen = isc_buffer_getuint32(&target);
02343
02344
02345
02346
02347 minlen = sizeof(totallen) + sizeof(isc_uint16_t) +
02348 sizeof(isc_uint16_t) + sizeof(isc_uint16_t) +
02349 sizeof(isc_uint32_t) + sizeof(isc_uint32_t);
02350 if (totallen < minlen) {
02351 result = ISC_R_RANGE;
02352 goto cleanup;
02353 }
02354 totallen -= sizeof(totallen);
02355
02356 isc_buffer_clear(&target);
02357 if (totallen > isc_buffer_availablelength(&target)) {
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370 sequential_read = ISC_TRUE;
02371 readlen = minlen - sizeof(totallen);
02372 } else {
02373
02374
02375
02376
02377 readlen = totallen;
02378 }
02379 result = isc_stdio_read(target.base, 1, readlen,
02380 lctx->f, NULL);
02381 if (result != ISC_R_SUCCESS)
02382 goto cleanup;
02383 isc_buffer_add(&target, (unsigned int)readlen);
02384
02385
02386 dns_rdatalist_init(&rdatalist);
02387 rdatalist.rdclass = isc_buffer_getuint16(&target);
02388 rdatalist.type = isc_buffer_getuint16(&target);
02389 rdatalist.covers = isc_buffer_getuint16(&target);
02390 rdatalist.ttl = isc_buffer_getuint32(&target);
02391 rdcount = isc_buffer_getuint32(&target);
02392 if (rdcount == 0 || rdcount > 0xffff) {
02393 result = ISC_R_RANGE;
02394 goto cleanup;
02395 }
02396 INSIST(isc_buffer_consumedlength(&target) <= readlen);
02397
02398
02399 result = read_and_check(sequential_read, &target,
02400 sizeof(namelen), lctx->f);
02401 if (result != ISC_R_SUCCESS)
02402 goto cleanup;
02403 namelen = isc_buffer_getuint16(&target);
02404 if (namelen > sizeof(namebuf)) {
02405 result = ISC_R_RANGE;
02406 goto cleanup;
02407 }
02408
02409 result = read_and_check(sequential_read, &target, namelen,
02410 lctx->f);
02411 if (result != ISC_R_SUCCESS)
02412 goto cleanup;
02413
02414 isc_buffer_setactive(&target, (unsigned int)namelen);
02415 result = dns_name_fromwire(name, &target, &dctx, 0, NULL);
02416 if (result != ISC_R_SUCCESS)
02417 goto cleanup;
02418
02419 if ((lctx->options & DNS_MASTER_CHECKTTL) != 0 &&
02420 rdatalist.ttl > lctx->maxttl)
02421 {
02422 (callbacks->error)(callbacks,
02423 "dns_master_load: "
02424 "TTL %d exceeds configured "
02425 "max-zone-ttl %d",
02426 rdatalist.ttl, lctx->maxttl);
02427 result = ISC_R_RANGE;
02428 goto cleanup;
02429 }
02430
02431
02432 if (rdcount > rdata_size) {
02433 dns_rdata_t *new_rdata = NULL;
02434
02435 new_rdata = grow_rdata(rdcount + RDSZ, rdata,
02436 rdata_size, &head,
02437 &dummy, mctx);
02438 if (new_rdata == NULL) {
02439 result = ISC_R_NOMEMORY;
02440 goto cleanup;
02441 }
02442 rdata_size = rdcount + RDSZ;
02443 rdata = new_rdata;
02444 }
02445
02446 continue_read:
02447 for (i = 0; i < rdcount; i++) {
02448 isc_uint16_t rdlen;
02449
02450 dns_rdata_init(&rdata[i]);
02451
02452 if (sequential_read &&
02453 isc_buffer_availablelength(&target) < MINTSIZ) {
02454 unsigned int j;
02455
02456 INSIST(i > 0);
02457
02458
02459 ISC_LIST_APPEND(head, &rdatalist, link);
02460 result = commit(callbacks, lctx, &head, name,
02461 NULL, 0);
02462 for (j = 0; j < i; j++) {
02463 ISC_LIST_UNLINK(rdatalist.rdata,
02464 &rdata[j], link);
02465 dns_rdata_reset(&rdata[j]);
02466 }
02467 if (result != ISC_R_SUCCESS)
02468 goto cleanup;
02469
02470
02471 isc_buffer_clear(&target);
02472
02473 rdcount -= i;
02474
02475 goto continue_read;
02476 }
02477
02478
02479 result = read_and_check(sequential_read, &target,
02480 sizeof(rdlen), lctx->f);
02481 if (result != ISC_R_SUCCESS)
02482 goto cleanup;
02483 rdlen = isc_buffer_getuint16(&target);
02484
02485
02486 result = read_and_check(sequential_read, &target,
02487 rdlen, lctx->f);
02488 if (result != ISC_R_SUCCESS)
02489 goto cleanup;
02490 isc_buffer_setactive(&target, (unsigned int)rdlen);
02491
02492
02493
02494
02495
02496
02497 isc_buffer_init(&buf, isc_buffer_current(&target),
02498 (unsigned int)rdlen);
02499 result = dns_rdata_fromwire(&rdata[i],
02500 rdatalist.rdclass,
02501 rdatalist.type, &target,
02502 &dctx, 0, &buf);
02503 if (result != ISC_R_SUCCESS)
02504 goto cleanup;
02505 ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link);
02506 }
02507
02508
02509
02510
02511
02512
02513 if (isc_buffer_remaininglength(&target) != 0) {
02514 result = ISC_R_RANGE;
02515 goto cleanup;
02516 }
02517
02518 ISC_LIST_APPEND(head, &rdatalist, link);
02519
02520
02521 result = commit(callbacks, lctx, &head, name, NULL, 0);
02522
02523 for (i = 0; i < rdcount; i++) {
02524 ISC_LIST_UNLINK(rdatalist.rdata, &rdata[i], link);
02525 dns_rdata_reset(&rdata[i]);
02526 }
02527
02528 if (result != ISC_R_SUCCESS)
02529 goto cleanup;
02530 }
02531
02532 if (!done) {
02533 INSIST(lctx->done != NULL && lctx->task != NULL);
02534 result = DNS_R_CONTINUE;
02535 } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS)
02536 result = lctx->result;
02537
02538 if (result == ISC_R_SUCCESS && callbacks->rawdata != NULL)
02539 (*callbacks->rawdata)(callbacks->zone, &lctx->header);
02540
02541 cleanup:
02542 if (rdata != NULL)
02543 isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
02544 if (target_mem != NULL)
02545 isc_mem_put(mctx, target_mem, target_size);
02546 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE) {
02547 (*callbacks->error)(callbacks, "dns_master_load: %s",
02548 dns_result_totext(result));
02549 }
02550
02551 return (result);
02552 }
02553
02554 isc_result_t
02555 dns_master_loadfile(const char *master_file, dns_name_t *top,
02556 dns_name_t *origin,
02557 dns_rdataclass_t zclass, unsigned int options,
02558 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
02559 {
02560 return (dns_master_loadfile5(master_file, top, origin, zclass,
02561 options, 0, callbacks, NULL, NULL,
02562 mctx, dns_masterformat_text, 0));
02563 }
02564
02565 isc_result_t
02566 dns_master_loadfile2(const char *master_file, dns_name_t *top,
02567 dns_name_t *origin,
02568 dns_rdataclass_t zclass, unsigned int options,
02569 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
02570 dns_masterformat_t format)
02571 {
02572 return (dns_master_loadfile5(master_file, top, origin, zclass,
02573 options, 0, callbacks, NULL, NULL,
02574 mctx, format, 0));
02575 }
02576
02577 isc_result_t
02578 dns_master_loadfile3(const char *master_file, dns_name_t *top,
02579 dns_name_t *origin, dns_rdataclass_t zclass,
02580 unsigned int options, isc_uint32_t resign,
02581 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
02582 dns_masterformat_t format)
02583 {
02584 return (dns_master_loadfile5(master_file, top, origin, zclass,
02585 options, resign, callbacks, NULL, NULL,
02586 mctx, format, 0));
02587 }
02588
02589 isc_result_t
02590 dns_master_loadfile4(const char *master_file, dns_name_t *top,
02591 dns_name_t *origin, dns_rdataclass_t zclass,
02592 unsigned int options, isc_uint32_t resign,
02593 dns_rdatacallbacks_t *callbacks,
02594 dns_masterincludecb_t include_cb, void *include_arg,
02595 isc_mem_t *mctx, dns_masterformat_t format)
02596 {
02597 return (dns_master_loadfile5(master_file, top, origin, zclass,
02598 options, resign, callbacks,
02599 include_cb, include_arg,
02600 mctx, format, 0));
02601 }
02602
02603 isc_result_t
02604 dns_master_loadfile5(const char *master_file, dns_name_t *top,
02605 dns_name_t *origin, dns_rdataclass_t zclass,
02606 unsigned int options, isc_uint32_t resign,
02607 dns_rdatacallbacks_t *callbacks,
02608 dns_masterincludecb_t include_cb, void *include_arg,
02609 isc_mem_t *mctx, dns_masterformat_t format,
02610 dns_ttl_t maxttl)
02611 {
02612 dns_loadctx_t *lctx = NULL;
02613 isc_result_t result;
02614
02615 result = loadctx_create(format, mctx, options, resign, top, zclass,
02616 origin, callbacks, NULL, NULL, NULL,
02617 include_cb, include_arg, NULL, &lctx);
02618 if (result != ISC_R_SUCCESS)
02619 return (result);
02620
02621 lctx->maxttl = maxttl;
02622
02623 result = (lctx->openfile)(lctx, master_file);
02624 if (result != ISC_R_SUCCESS)
02625 goto cleanup;
02626
02627 result = (lctx->load)(lctx);
02628 INSIST(result != DNS_R_CONTINUE);
02629
02630 cleanup:
02631 dns_loadctx_detach(&lctx);
02632 return (result);
02633 }
02634
02635 isc_result_t
02636 dns_master_loadfileinc(const char *master_file, dns_name_t *top,
02637 dns_name_t *origin, dns_rdataclass_t zclass,
02638 unsigned int options, dns_rdatacallbacks_t *callbacks,
02639 isc_task_t *task, dns_loaddonefunc_t done,
02640 void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx)
02641 {
02642 return (dns_master_loadfileinc4(master_file, top, origin, zclass,
02643 options, 0, callbacks, task, done,
02644 done_arg, lctxp, NULL, NULL, mctx,
02645 dns_masterformat_text));
02646 }
02647
02648 isc_result_t
02649 dns_master_loadfileinc2(const char *master_file, dns_name_t *top,
02650 dns_name_t *origin, dns_rdataclass_t zclass,
02651 unsigned int options, dns_rdatacallbacks_t *callbacks,
02652 isc_task_t *task, dns_loaddonefunc_t done,
02653 void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx,
02654 dns_masterformat_t format)
02655 {
02656 return (dns_master_loadfileinc4(master_file, top, origin, zclass,
02657 options, 0, callbacks, task, done,
02658 done_arg, lctxp, NULL, NULL, mctx,
02659 format));
02660 }
02661
02662 isc_result_t
02663 dns_master_loadfileinc3(const char *master_file, dns_name_t *top,
02664 dns_name_t *origin, dns_rdataclass_t zclass,
02665 unsigned int options, isc_uint32_t resign,
02666 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
02667 dns_loaddonefunc_t done, void *done_arg,
02668 dns_loadctx_t **lctxp, isc_mem_t *mctx,
02669 dns_masterformat_t format)
02670 {
02671 return (dns_master_loadfileinc4(master_file, top, origin, zclass,
02672 options, resign, callbacks, task,
02673 done, done_arg, lctxp, NULL, NULL,
02674 mctx, format));
02675 }
02676
02677 isc_result_t
02678 dns_master_loadfileinc4(const char *master_file, dns_name_t *top,
02679 dns_name_t *origin, dns_rdataclass_t zclass,
02680 unsigned int options, isc_uint32_t resign,
02681 dns_rdatacallbacks_t *callbacks,
02682 isc_task_t *task, dns_loaddonefunc_t done,
02683 void *done_arg, dns_loadctx_t **lctxp,
02684 dns_masterincludecb_t include_cb, void *include_arg,
02685 isc_mem_t *mctx, dns_masterformat_t format)
02686 {
02687 options &= ~DNS_MASTER_CHECKTTL;
02688 return (dns_master_loadfileinc5(master_file, top, origin, zclass,
02689 options, resign, callbacks, task,
02690 done, done_arg, lctxp, include_cb,
02691 include_arg, mctx, format, 0));
02692 }
02693
02694 isc_result_t
02695 dns_master_loadfileinc5(const char *master_file, dns_name_t *top,
02696 dns_name_t *origin, dns_rdataclass_t zclass,
02697 unsigned int options, isc_uint32_t resign,
02698 dns_rdatacallbacks_t *callbacks,
02699 isc_task_t *task, dns_loaddonefunc_t done,
02700 void *done_arg, dns_loadctx_t **lctxp,
02701 dns_masterincludecb_t include_cb, void *include_arg,
02702 isc_mem_t *mctx, dns_masterformat_t format,
02703 isc_uint32_t maxttl)
02704 {
02705 dns_loadctx_t *lctx = NULL;
02706 isc_result_t result;
02707
02708 REQUIRE(task != NULL);
02709 REQUIRE(done != NULL);
02710
02711 result = loadctx_create(format, mctx, options, resign, top, zclass,
02712 origin, callbacks, task, done, done_arg,
02713 include_cb, include_arg, NULL, &lctx);
02714 if (result != ISC_R_SUCCESS)
02715 return (result);
02716
02717 lctx->maxttl = maxttl;
02718
02719 result = (lctx->openfile)(lctx, master_file);
02720 if (result != ISC_R_SUCCESS)
02721 goto cleanup;
02722
02723 result = task_send(lctx);
02724 if (result == ISC_R_SUCCESS) {
02725 dns_loadctx_attach(lctx, lctxp);
02726 return (DNS_R_CONTINUE);
02727 }
02728
02729 cleanup:
02730 dns_loadctx_detach(&lctx);
02731 return (result);
02732 }
02733
02734 isc_result_t
02735 dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
02736 dns_rdataclass_t zclass, unsigned int options,
02737 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
02738 {
02739 isc_result_t result;
02740 dns_loadctx_t *lctx = NULL;
02741
02742 REQUIRE(stream != NULL);
02743
02744 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
02745 zclass, origin, callbacks, NULL, NULL, NULL,
02746 NULL, NULL, NULL, &lctx);
02747 if (result != ISC_R_SUCCESS)
02748 goto cleanup;
02749
02750 result = isc_lex_openstream(lctx->lex, stream);
02751 if (result != ISC_R_SUCCESS)
02752 goto cleanup;
02753
02754 result = (lctx->load)(lctx);
02755 INSIST(result != DNS_R_CONTINUE);
02756
02757 cleanup:
02758 if (lctx != NULL)
02759 dns_loadctx_detach(&lctx);
02760 return (result);
02761 }
02762
02763 isc_result_t
02764 dns_master_loadstreaminc(FILE *stream, dns_name_t *top, dns_name_t *origin,
02765 dns_rdataclass_t zclass, unsigned int options,
02766 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
02767 dns_loaddonefunc_t done, void *done_arg,
02768 dns_loadctx_t **lctxp, isc_mem_t *mctx)
02769 {
02770 isc_result_t result;
02771 dns_loadctx_t *lctx = NULL;
02772
02773 REQUIRE(stream != NULL);
02774 REQUIRE(task != NULL);
02775 REQUIRE(done != NULL);
02776
02777 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
02778 zclass, origin, callbacks, task, done,
02779 done_arg, NULL, NULL, NULL, &lctx);
02780 if (result != ISC_R_SUCCESS)
02781 goto cleanup;
02782
02783 result = isc_lex_openstream(lctx->lex, stream);
02784 if (result != ISC_R_SUCCESS)
02785 goto cleanup;
02786
02787 result = task_send(lctx);
02788 if (result == ISC_R_SUCCESS) {
02789 dns_loadctx_attach(lctx, lctxp);
02790 return (DNS_R_CONTINUE);
02791 }
02792
02793 cleanup:
02794 if (lctx != NULL)
02795 dns_loadctx_detach(&lctx);
02796 return (result);
02797 }
02798
02799 isc_result_t
02800 dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top,
02801 dns_name_t *origin, dns_rdataclass_t zclass,
02802 unsigned int options,
02803 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
02804 {
02805 isc_result_t result;
02806 dns_loadctx_t *lctx = NULL;
02807
02808 REQUIRE(buffer != NULL);
02809
02810 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
02811 zclass, origin, callbacks, NULL, NULL, NULL,
02812 NULL, NULL, NULL, &lctx);
02813 if (result != ISC_R_SUCCESS)
02814 return (result);
02815
02816 result = isc_lex_openbuffer(lctx->lex, buffer);
02817 if (result != ISC_R_SUCCESS)
02818 goto cleanup;
02819
02820 result = (lctx->load)(lctx);
02821 INSIST(result != DNS_R_CONTINUE);
02822
02823 cleanup:
02824 dns_loadctx_detach(&lctx);
02825 return (result);
02826 }
02827
02828 isc_result_t
02829 dns_master_loadbufferinc(isc_buffer_t *buffer, dns_name_t *top,
02830 dns_name_t *origin, dns_rdataclass_t zclass,
02831 unsigned int options,
02832 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
02833 dns_loaddonefunc_t done, void *done_arg,
02834 dns_loadctx_t **lctxp, isc_mem_t *mctx)
02835 {
02836 isc_result_t result;
02837 dns_loadctx_t *lctx = NULL;
02838
02839 REQUIRE(buffer != NULL);
02840 REQUIRE(task != NULL);
02841 REQUIRE(done != NULL);
02842
02843 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
02844 zclass, origin, callbacks, task, done,
02845 done_arg, NULL, NULL, NULL, &lctx);
02846 if (result != ISC_R_SUCCESS)
02847 return (result);
02848
02849 result = isc_lex_openbuffer(lctx->lex, buffer);
02850 if (result != ISC_R_SUCCESS)
02851 goto cleanup;
02852
02853 result = task_send(lctx);
02854 if (result == ISC_R_SUCCESS) {
02855 dns_loadctx_attach(lctx, lctxp);
02856 return (DNS_R_CONTINUE);
02857 }
02858
02859 cleanup:
02860 dns_loadctx_detach(&lctx);
02861 return (result);
02862 }
02863
02864 isc_result_t
02865 dns_master_loadlexer(isc_lex_t *lex, dns_name_t *top,
02866 dns_name_t *origin, dns_rdataclass_t zclass,
02867 unsigned int options,
02868 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
02869 {
02870 isc_result_t result;
02871 dns_loadctx_t *lctx = NULL;
02872
02873 REQUIRE(lex != NULL);
02874
02875 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
02876 zclass, origin, callbacks, NULL, NULL, NULL,
02877 NULL, NULL, lex, &lctx);
02878 if (result != ISC_R_SUCCESS)
02879 return (result);
02880
02881 result = (lctx->load)(lctx);
02882 INSIST(result != DNS_R_CONTINUE);
02883
02884 dns_loadctx_detach(&lctx);
02885 return (result);
02886 }
02887
02888 isc_result_t
02889 dns_master_loadlexerinc(isc_lex_t *lex, dns_name_t *top,
02890 dns_name_t *origin, dns_rdataclass_t zclass,
02891 unsigned int options,
02892 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
02893 dns_loaddonefunc_t done, void *done_arg,
02894 dns_loadctx_t **lctxp, isc_mem_t *mctx)
02895 {
02896 isc_result_t result;
02897 dns_loadctx_t *lctx = NULL;
02898
02899 REQUIRE(lex != NULL);
02900 REQUIRE(task != NULL);
02901 REQUIRE(done != NULL);
02902
02903 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
02904 zclass, origin, callbacks, task, done,
02905 done_arg, NULL, NULL, lex, &lctx);
02906 if (result != ISC_R_SUCCESS)
02907 return (result);
02908
02909 result = task_send(lctx);
02910 if (result == ISC_R_SUCCESS) {
02911 dns_loadctx_attach(lctx, lctxp);
02912 return (DNS_R_CONTINUE);
02913 }
02914
02915 dns_loadctx_detach(&lctx);
02916 return (result);
02917 }
02918
02919
02920
02921
02922
02923 static dns_rdatalist_t *
02924 grow_rdatalist(int new_len, dns_rdatalist_t *old, int old_len,
02925 rdatalist_head_t *current, rdatalist_head_t *glue,
02926 isc_mem_t *mctx)
02927 {
02928 dns_rdatalist_t *new;
02929 int rdlcount = 0;
02930 ISC_LIST(dns_rdatalist_t) save;
02931 dns_rdatalist_t *this;
02932
02933 new = isc_mem_get(mctx, new_len * sizeof(*new));
02934 if (new == NULL)
02935 return (NULL);
02936
02937 ISC_LIST_INIT(save);
02938 while ((this = ISC_LIST_HEAD(*current)) != NULL) {
02939 ISC_LIST_UNLINK(*current, this, link);
02940 ISC_LIST_APPEND(save, this, link);
02941 }
02942 while ((this = ISC_LIST_HEAD(save)) != NULL) {
02943 ISC_LIST_UNLINK(save, this, link);
02944 INSIST(rdlcount < new_len);
02945 new[rdlcount] = *this;
02946 ISC_LIST_APPEND(*current, &new[rdlcount], link);
02947 rdlcount++;
02948 }
02949
02950 ISC_LIST_INIT(save);
02951 while ((this = ISC_LIST_HEAD(*glue)) != NULL) {
02952 ISC_LIST_UNLINK(*glue, this, link);
02953 ISC_LIST_APPEND(save, this, link);
02954 }
02955 while ((this = ISC_LIST_HEAD(save)) != NULL) {
02956 ISC_LIST_UNLINK(save, this, link);
02957 INSIST(rdlcount < new_len);
02958 new[rdlcount] = *this;
02959 ISC_LIST_APPEND(*glue, &new[rdlcount], link);
02960 rdlcount++;
02961 }
02962
02963 INSIST(rdlcount == old_len);
02964 if (old != NULL)
02965 isc_mem_put(mctx, old, old_len * sizeof(*old));
02966 return (new);
02967 }
02968
02969
02970
02971
02972
02973 static dns_rdata_t *
02974 grow_rdata(int new_len, dns_rdata_t *old, int old_len,
02975 rdatalist_head_t *current, rdatalist_head_t *glue,
02976 isc_mem_t *mctx)
02977 {
02978 dns_rdata_t *new;
02979 int rdcount = 0;
02980 ISC_LIST(dns_rdata_t) save;
02981 dns_rdatalist_t *this;
02982 dns_rdata_t *rdata;
02983
02984 new = isc_mem_get(mctx, new_len * sizeof(*new));
02985 if (new == NULL)
02986 return (NULL);
02987 memset(new, 0, new_len * sizeof(*new));
02988
02989
02990
02991
02992 this = ISC_LIST_HEAD(*current);
02993 while (this != NULL) {
02994 ISC_LIST_INIT(save);
02995 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
02996 ISC_LIST_UNLINK(this->rdata, rdata, link);
02997 ISC_LIST_APPEND(save, rdata, link);
02998 }
02999 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
03000 ISC_LIST_UNLINK(save, rdata, link);
03001 INSIST(rdcount < new_len);
03002 new[rdcount] = *rdata;
03003 ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
03004 rdcount++;
03005 }
03006 this = ISC_LIST_NEXT(this, link);
03007 }
03008
03009
03010
03011
03012 this = ISC_LIST_HEAD(*glue);
03013 while (this != NULL) {
03014 ISC_LIST_INIT(save);
03015 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
03016 ISC_LIST_UNLINK(this->rdata, rdata, link);
03017 ISC_LIST_APPEND(save, rdata, link);
03018 }
03019 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
03020 ISC_LIST_UNLINK(save, rdata, link);
03021 INSIST(rdcount < new_len);
03022 new[rdcount] = *rdata;
03023 ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
03024 rdcount++;
03025 }
03026 this = ISC_LIST_NEXT(this, link);
03027 }
03028 INSIST(rdcount == old_len || rdcount == 0);
03029 if (old != NULL)
03030 isc_mem_put(mctx, old, old_len * sizeof(*old));
03031 return (new);
03032 }
03033
03034 static isc_uint32_t
03035 resign_fromlist(dns_rdatalist_t *this, isc_uint32_t resign) {
03036 dns_rdata_t *rdata;
03037 dns_rdata_rrsig_t sig;
03038 isc_uint32_t when;
03039
03040 rdata = ISC_LIST_HEAD(this->rdata);
03041 INSIST(rdata != NULL);
03042 (void)dns_rdata_tostruct(rdata, &sig, NULL);
03043 when = sig.timeexpire - resign;
03044
03045 rdata = ISC_LIST_NEXT(rdata, link);
03046 while (rdata != NULL) {
03047 (void)dns_rdata_tostruct(rdata, &sig, NULL);
03048 if (sig.timeexpire - resign < when)
03049 when = sig.timeexpire - resign;
03050 rdata = ISC_LIST_NEXT(rdata, link);
03051 }
03052 return (when);
03053 }
03054
03055
03056
03057
03058
03059
03060 static isc_result_t
03061 commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
03062 rdatalist_head_t *head, dns_name_t *owner,
03063 const char *source, unsigned int line)
03064 {
03065 dns_rdatalist_t *this;
03066 dns_rdataset_t dataset;
03067 isc_result_t result;
03068 char namebuf[DNS_NAME_FORMATSIZE];
03069 void (*error)(struct dns_rdatacallbacks *, const char *, ...);
03070
03071 this = ISC_LIST_HEAD(*head);
03072 error = callbacks->error;
03073
03074 if (this == NULL)
03075 return (ISC_R_SUCCESS);
03076 do {
03077 dns_rdataset_init(&dataset);
03078 RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset)
03079 == ISC_R_SUCCESS);
03080 dataset.trust = dns_trust_ultimate;
03081
03082
03083
03084 if (dataset.type == dns_rdatatype_rrsig &&
03085 (lctx->options & DNS_MASTER_RESIGN) != 0) {
03086 dataset.attributes |= DNS_RDATASETATTR_RESIGN;
03087 dataset.resign = resign_fromlist(this, lctx->resign);
03088 }
03089 result = ((*callbacks->add)(callbacks->add_private, owner,
03090 &dataset));
03091 if (result == ISC_R_NOMEMORY) {
03092 (*error)(callbacks, "dns_master_load: %s",
03093 dns_result_totext(result));
03094 } else if (result != ISC_R_SUCCESS) {
03095 dns_name_format(owner, namebuf, sizeof(namebuf));
03096 if (source != NULL) {
03097 (*error)(callbacks, "%s: %s:%lu: %s: %s",
03098 "dns_master_load", source, line,
03099 namebuf, dns_result_totext(result));
03100 } else {
03101 (*error)(callbacks, "%s: %s: %s",
03102 "dns_master_load", namebuf,
03103 dns_result_totext(result));
03104 }
03105 }
03106 if (MANYERRS(lctx, result))
03107 SETRESULT(lctx, result);
03108 else if (result != ISC_R_SUCCESS)
03109 return (result);
03110 ISC_LIST_UNLINK(*head, this, link);
03111 this = ISC_LIST_HEAD(*head);
03112 } while (this != NULL);
03113 return (ISC_R_SUCCESS);
03114 }
03115
03116
03117
03118
03119
03120 static isc_boolean_t
03121 is_glue(rdatalist_head_t *head, dns_name_t *owner) {
03122 dns_rdatalist_t *this;
03123 dns_rdata_t *rdata;
03124 isc_region_t region;
03125 dns_name_t name;
03126
03127
03128
03129
03130 this = ISC_LIST_HEAD(*head);
03131 while (this != NULL) {
03132 if (this->type == dns_rdatatype_ns)
03133 break;
03134 this = ISC_LIST_NEXT(this, link);
03135 }
03136 if (this == NULL)
03137 return (ISC_FALSE);
03138
03139 rdata = ISC_LIST_HEAD(this->rdata);
03140 while (rdata != NULL) {
03141 dns_name_init(&name, NULL);
03142 dns_rdata_toregion(rdata, ®ion);
03143 dns_name_fromregion(&name, ®ion);
03144 if (dns_name_compare(&name, owner) == 0)
03145 return (ISC_TRUE);
03146 rdata = ISC_LIST_NEXT(rdata, link);
03147 }
03148 return (ISC_FALSE);
03149 }
03150
03151 static void
03152 load_quantum(isc_task_t *task, isc_event_t *event) {
03153 isc_result_t result;
03154 dns_loadctx_t *lctx;
03155
03156 REQUIRE(event != NULL);
03157 lctx = event->ev_arg;
03158 REQUIRE(DNS_LCTX_VALID(lctx));
03159
03160 if (lctx->canceled)
03161 result = ISC_R_CANCELED;
03162 else
03163 result = (lctx->load)(lctx);
03164 if (result == DNS_R_CONTINUE) {
03165 event->ev_arg = lctx;
03166 isc_task_send(task, &event);
03167 } else {
03168 (lctx->done)(lctx->done_arg, result);
03169 isc_event_free(&event);
03170 dns_loadctx_detach(&lctx);
03171 }
03172 }
03173
03174 static isc_result_t
03175 task_send(dns_loadctx_t *lctx) {
03176 isc_event_t *event;
03177
03178 event = isc_event_allocate(lctx->mctx, NULL,
03179 DNS_EVENT_MASTERQUANTUM,
03180 load_quantum, lctx, sizeof(*event));
03181 if (event == NULL)
03182 return (ISC_R_NOMEMORY);
03183 isc_task_send(lctx->task, &event);
03184 return (ISC_R_SUCCESS);
03185 }
03186
03187 void
03188 dns_loadctx_cancel(dns_loadctx_t *lctx) {
03189 REQUIRE(DNS_LCTX_VALID(lctx));
03190
03191 LOCK(&lctx->lock);
03192 lctx->canceled = ISC_TRUE;
03193 UNLOCK(&lctx->lock);
03194 }
03195
03196 void
03197 dns_master_initrawheader(dns_masterrawheader_t *header) {
03198 memset(header, 0, sizeof(dns_masterrawheader_t));
03199 }