📄 master.c
字号:
cleanup: while ((this = ISC_LIST_HEAD(current_list)) != NULL) ISC_LIST_UNLINK(current_list, this, link); while ((this = ISC_LIST_HEAD(glue_list)) != NULL) ISC_LIST_UNLINK(glue_list, this, link); if (rdatalist != NULL) isc_mem_put(mctx, rdatalist, rdatalist_size * sizeof(*rdatalist)); if (rdata != NULL) isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata)); if (target_mem != NULL) isc_mem_put(mctx, target_mem, target_size); if (include_file != NULL) isc_mem_free(mctx, include_file); if (range != NULL) isc_mem_free(mctx, range); if (lhs != NULL) isc_mem_free(mctx, lhs); if (gtype != NULL) isc_mem_free(mctx, gtype); if (rhs != NULL) isc_mem_free(mctx, rhs); return (result);}static isc_result_tpushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) { isc_result_t result; dns_incctx_t *ictx; dns_incctx_t *new = NULL; isc_region_t r; int new_in_use; REQUIRE(master_file != NULL); REQUIRE(DNS_LCTX_VALID(lctx)); ictx = lctx->inc; lctx->seen_include = ISC_TRUE; result = incctx_create(lctx->mctx, origin, &new); if (result != ISC_R_SUCCESS) return (result); /* Set current domain. */ if (ictx->glue != NULL || ictx->current != NULL) { for (new_in_use = 0; new_in_use < NBUFS; new_in_use++) if (!new->in_use[new_in_use]) break; INSIST(new_in_use < NBUFS); new->current_in_use = new_in_use; new->current = dns_fixedname_name(&new->fixed[new->current_in_use]); new->in_use[new->current_in_use] = ISC_TRUE; dns_name_toregion((ictx->glue != NULL) ? ictx->glue : ictx->current, &r); dns_name_fromregion(new->current, &r); new->drop = ictx->drop; } result = (lctx->openfile)(lctx, master_file); if (result != ISC_R_SUCCESS) goto cleanup; new->parent = ictx; lctx->inc = new; return (ISC_R_SUCCESS); cleanup: if (new != NULL) incctx_destroy(lctx->mctx, new); return (result);}static inline isc_result_tread_and_check(isc_boolean_t do_read, isc_buffer_t *buffer, size_t len, FILE *f){ isc_result_t result; if (do_read) { INSIST(isc_buffer_availablelength(buffer) >= len); result = isc_stdio_read(isc_buffer_used(buffer), 1, len, f, NULL); if (result != ISC_R_SUCCESS) return (result); isc_buffer_add(buffer, len); } else if (isc_buffer_remaininglength(buffer) < len) return (ISC_R_RANGE); return (ISC_R_SUCCESS);}static isc_result_tload_raw(dns_loadctx_t *lctx) { isc_result_t result = ISC_R_SUCCESS; isc_boolean_t done = ISC_FALSE; unsigned int loop_cnt = 0; dns_rdatacallbacks_t *callbacks; unsigned char namebuf[DNS_NAME_MAXWIRE]; isc_region_t r; dns_name_t name; rdatalist_head_t head, dummy; dns_rdatalist_t rdatalist; isc_mem_t *mctx = lctx->mctx; dns_rdata_t *rdata = NULL; unsigned int rdata_size = 0; int target_size = TSIZ; isc_buffer_t target; unsigned char *target_mem = NULL; REQUIRE(DNS_LCTX_VALID(lctx)); callbacks = lctx->callbacks; if (lctx->first) { dns_masterrawheader_t header; isc_uint32_t format, version, dumptime; size_t hdrlen = sizeof(format) + sizeof(version) + sizeof(dumptime); INSIST(hdrlen <= sizeof(header)); isc_buffer_init(&target, &header, sizeof(header)); result = isc_stdio_read(&header, 1, hdrlen, lctx->f, NULL); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_stdio_read failed: %s", isc_result_totext(result)); return (result); } isc_buffer_add(&target, hdrlen); format = isc_buffer_getuint32(&target); if (format != dns_masterformat_raw) { (*callbacks->error)(callbacks, "dns_master_load: " "file format mismatch"); return (ISC_R_NOTIMPLEMENTED); } version = isc_buffer_getuint32(&target); if (version > DNS_RAWFORMAT_VERSION) { (*callbacks->error)(callbacks, "dns_master_load: " "unsupported file format version"); return (ISC_R_NOTIMPLEMENTED); } /* Empty read: currently, we do not use dumptime */ dumptime = isc_buffer_getuint32(&target); lctx->first = ISC_FALSE; } ISC_LIST_INIT(head); ISC_LIST_INIT(dummy); dns_rdatalist_init(&rdatalist); /* * Allocate target_size of buffer space. This is greater than twice * the maximum individual RR data size. */ target_mem = isc_mem_get(mctx, target_size); if (target_mem == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } isc_buffer_init(&target, target_mem, target_size); /* * In the following loop, we regard any error fatal regardless of * whether "MANYERRORS" is set in the context option. This is because * normal errors should already have been checked at creation time. * Besides, it is very unlikely that we can recover from an error * in this format, and so trying to continue parsing erroneous data * does not really make sense. */ for (loop_cnt = 0; (lctx->loop_cnt == 0 || loop_cnt < lctx->loop_cnt); loop_cnt++) { unsigned int i, rdcount, consumed_name; isc_uint16_t namelen; isc_uint32_t totallen; size_t minlen, readlen; isc_boolean_t sequential_read = ISC_FALSE; /* Read the data length */ isc_buffer_clear(&target); INSIST(isc_buffer_availablelength(&target) >= sizeof(totallen)); result = isc_stdio_read(target.base, 1, sizeof(totallen), lctx->f, NULL); if (result == ISC_R_EOF) { result = ISC_R_SUCCESS; done = ISC_TRUE; break; } if (result != ISC_R_SUCCESS) goto cleanup; isc_buffer_add(&target, sizeof(totallen)); totallen = isc_buffer_getuint32(&target); /* * Validation: the input data must at least contain the common * header. */ minlen = sizeof(totallen) + sizeof(isc_uint16_t) + sizeof(isc_uint16_t) + sizeof(isc_uint16_t) + sizeof(isc_uint32_t) + sizeof(isc_uint32_t); if (totallen < minlen) { result = ISC_R_RANGE; goto cleanup; } totallen -= sizeof(totallen); isc_buffer_clear(&target); if (totallen > isc_buffer_availablelength(&target)) { /* * The default buffer size should typically be large * enough to store the entire RRset. We could try to * allocate enough space if this is not the case, but * it might cause a hazardous result when "totallen" * is forged. Thus, we'd rather take an inefficient * but robust approach in this atypical case: read * data step by step, and commit partial data when * necessary. Note that the buffer must be large * enough to store the "header part", owner name, and * at least one rdata (however large it is). */ sequential_read = ISC_TRUE; readlen = minlen - sizeof(totallen); } else { /* * Typical case. We can read the whole RRset at once * with the default buffer. */ readlen = totallen; } result = isc_stdio_read(target.base, 1, readlen, lctx->f, NULL); if (result != ISC_R_SUCCESS) goto cleanup; isc_buffer_add(&target, readlen); /* Construct RRset headers */ rdatalist.rdclass = isc_buffer_getuint16(&target); rdatalist.type = isc_buffer_getuint16(&target); rdatalist.covers = isc_buffer_getuint16(&target); rdatalist.ttl = isc_buffer_getuint32(&target); rdcount = isc_buffer_getuint32(&target); if (rdcount == 0) { result = ISC_R_RANGE; goto cleanup; } INSIST(isc_buffer_consumedlength(&target) <= readlen); /* Owner name: length followed by name */ result = read_and_check(sequential_read, &target, sizeof(namelen), lctx->f); if (result != ISC_R_SUCCESS) goto cleanup; namelen = isc_buffer_getuint16(&target); if (namelen > sizeof(namebuf)) { result = ISC_R_RANGE; goto cleanup; } result = read_and_check(sequential_read, &target, namelen, lctx->f); if (result != ISC_R_SUCCESS) goto cleanup; isc_buffer_setactive(&target, (unsigned int)namelen); isc_buffer_activeregion(&target, &r); dns_name_init(&name, NULL); dns_name_fromregion(&name, &r); isc_buffer_forward(&target, (unsigned int)namelen); consumed_name = isc_buffer_consumedlength(&target); /* Rdata contents. */ if (rdcount > rdata_size) { dns_rdata_t *new_rdata = NULL; new_rdata = grow_rdata(rdata_size + RDSZ, rdata, rdata_size, &head, &dummy, mctx); if (new_rdata == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } rdata_size += RDSZ; rdata = new_rdata; } continue_read: for (i = 0; i < rdcount; i++) { isc_uint16_t rdlen; dns_rdata_init(&rdata[i]); if (sequential_read && isc_buffer_availablelength(&target) < MINTSIZ) { unsigned int j; INSIST(i > 0); /* detect an infinite loop */ /* Partial Commit. */ ISC_LIST_APPEND(head, &rdatalist, link); result = commit(callbacks, lctx, &head, &name, NULL, 0); for (j = 0; j < i; j++) { ISC_LIST_UNLINK(rdatalist.rdata, &rdata[j], link); dns_rdata_reset(&rdata[j]); } if (result != ISC_R_SUCCESS) goto cleanup; /* Rewind the buffer and continue */ isc_buffer_clear(&target); isc_buffer_add(&target, consumed_name); isc_buffer_forward(&target, consumed_name); rdcount -= i; i = 0; goto continue_read; } /* rdata length */ result = read_and_check(sequential_read, &target, sizeof(rdlen), lctx->f); if (result != ISC_R_SUCCESS) goto cleanup; rdlen = isc_buffer_getuint16(&target); /* rdata */ result = read_and_check(sequential_read, &target, rdlen, lctx->f); if (result != ISC_R_SUCCESS) goto cleanup; isc_buffer_setactive(&target, (unsigned int)rdlen); isc_buffer_activeregion(&target, &r); isc_buffer_forward(&target, (unsigned int)rdlen); dns_rdata_fromregion(&rdata[i], rdatalist.rdclass, rdatalist.type, &r); ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link); } /* * Sanity check. Still having remaining space is not * necessarily critical, but it very likely indicates broken * or malformed data. */ if (isc_buffer_remaininglength(&target) != 0) { result = ISC_R_RANGE; goto cleanup; } ISC_LIST_APPEND(head, &rdatalist, link); /* Commit this RRset. rdatalist will be unlinked. */ result = commit(callbacks, lctx, &head, &name, NULL, 0); for (i = 0; i < rdcount; i++) { ISC_LIST_UNLINK(rdatalist.rdata, &rdata[i], link); dns_rdata_reset(&rdata[i]); } if (result != ISC_R_SUCCESS) goto cleanup; } if (!done) { INSIST(lctx->done != NULL && lctx->task != NULL); result = DNS_R_CONTINUE; } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) result = lctx->result; cleanup: if (rdata != NULL) isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata)); if (target_mem != NULL) isc_mem_put(mctx, target_mem, target_size); if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE) { (*callbacks->error)(callbacks, "dns_master_load: %s", dns_result_totext(result)); } return (result);}isc_result_tdns_master_loadfile(const char *master_file, dns_name_t *top, dns_name_t *origin, dns_rdataclass_t zclass, unsigned int options, dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx){ return (dns_master_loadfile2(master_file, top, origin, zclass, options, callbacks, mctx, dns_masterformat_text));}isc_result_tdns_master_loadfile2(const char *master_file, dns_name_t *top, dns_name_t *origin, dns_rdataclass_t zclass, unsigned int options, dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx, dns_masterformat_t format){ dns_loadctx_t *lctx = NULL; isc_result_t result; result = loadctx_create(format, mctx, options, top, zclass, origin, callbacks, NULL, NULL, NULL, NULL, &lctx); if (result != ISC_R_SUCCESS) return (result); result = (lctx->openfile)(lctx, master_file); if (result != ISC_R_SUCCESS) goto cleanup; result = (lctx->load)(lctx); INSIST(result != DNS_R_CONTINUE); cleanup: if (lctx != NULL) dns_loadctx_detach(&lctx); return (result);}isc_result_tdns_master_loadfileinc(const char *master_file, dns_name_t *top, dns_name_t *origin, dns_rdataclass_t zclass, unsigned int options, dns_rdatacallbacks_t *callbacks, isc_task_t *task, dns_loaddonefunc_t done, void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx){ return (dns_master_loadfileinc2(master_file, top, origin, zclass, options, callbacks, task, done, done_arg, lctxp, mctx, dns_masterformat_text));}isc_result_tdns_master_loadfileinc2(const char *master_file, dns_name_t *top, dns_name_t *origin, dns_rdataclass_t zclass, unsigned int options, dns_rdatacallbacks_t *callbacks, isc_task_t *task, dns_loaddonefunc_t done, void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx, dns_masterformat_t format){ dns_loadctx_t *lctx = NULL; isc_result_t result; REQUIRE(task != NULL); REQUIRE(done != NULL); result = loadctx_create(format, mctx, options, top, zclass, origin, callbacks, task, done, done_arg, NULL, &lctx); if (result != ISC_R_SUCCESS) return (result); result = (lctx->openfile)(lctx, master_file); if (result != ISC_R_SUCCESS) goto cleanup; result = task_send(lctx); if (result == ISC_R_SUCCESS) { dns_loadctx_attach(lctx, lctxp); return (DNS_R_CONTINUE); } cleanup: if (lctx != NULL) dns_loadctx_detach(&lctx); return (result);}isc_result_tdns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin, dns_rdataclass_t zclass, unsigned int options, dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -