📄 masterdump.c
字号:
return (ISC_R_SUCCESS);}isc_result_tdns_rdataset_totext(dns_rdataset_t *rdataset, dns_name_t *owner_name, isc_boolean_t omit_final_dot, isc_boolean_t question, isc_buffer_t *target){ dns_totext_ctx_t ctx; isc_result_t result; result = totext_ctx_init(&dns_master_style_debug, &ctx); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "could not set master file style"); return (ISC_R_UNEXPECTED); } /* * The caller might want to give us an empty owner * name (e.g. if they are outputting into a master * file and this rdataset has the same name as the * previous one.) */ if (dns_name_countlabels(owner_name) == 0) owner_name = NULL; if (question) return (question_totext(rdataset, owner_name, &ctx, omit_final_dot, target)); else return (rdataset_totext(rdataset, owner_name, &ctx, omit_final_dot, target));}isc_result_tdns_master_rdatasettotext(dns_name_t *owner_name, dns_rdataset_t *rdataset, const dns_master_style_t *style, isc_buffer_t *target){ dns_totext_ctx_t ctx; isc_result_t result; result = totext_ctx_init(style, &ctx); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "could not set master file style"); return (ISC_R_UNEXPECTED); } return (rdataset_totext(rdataset, owner_name, &ctx, ISC_FALSE, target));}isc_result_tdns_master_questiontotext(dns_name_t *owner_name, dns_rdataset_t *rdataset, const dns_master_style_t *style, isc_buffer_t *target){ dns_totext_ctx_t ctx; isc_result_t result; result = totext_ctx_init(style, &ctx); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "could not set master file style"); return (ISC_R_UNEXPECTED); } return (question_totext(rdataset, owner_name, &ctx, ISC_FALSE, target));}/* * Print an rdataset. 'buffer' is a scratch buffer, which must have been * dynamically allocated by the caller. It must be large enough to * hold the result from dns_ttl_totext(). If more than that is needed, * the buffer will be grown automatically. */static isc_result_tdump_rdataset(isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *rdataset, dns_totext_ctx_t *ctx, isc_buffer_t *buffer, FILE *f){ isc_region_t r; isc_result_t result; REQUIRE(buffer->length > 0); /* * Output a $TTL directive if needed. */ if ((ctx->style.flags & DNS_STYLEFLAG_TTL) != 0) { if (ctx->current_ttl_valid == ISC_FALSE || ctx->current_ttl != rdataset->ttl) { if ((ctx->style.flags & DNS_STYLEFLAG_COMMENT) != 0) { isc_buffer_clear(buffer); result = dns_ttl_totext(rdataset->ttl, ISC_TRUE, buffer); INSIST(result == ISC_R_SUCCESS); isc_buffer_usedregion(buffer, &r); fprintf(f, "$TTL %u\t; %.*s\n", rdataset->ttl, (int) r.length, (char *) r.base); } else { fprintf(f, "$TTL %u\n", rdataset->ttl); } ctx->current_ttl = rdataset->ttl; ctx->current_ttl_valid = ISC_TRUE; } } isc_buffer_clear(buffer); /* * Generate the text representation of the rdataset into * the buffer. If the buffer is too small, grow it. */ for (;;) { int newlength; void *newmem; result = rdataset_totext(rdataset, name, ctx, ISC_FALSE, buffer); if (result != ISC_R_NOSPACE) break; newlength = buffer->length * 2; newmem = isc_mem_get(mctx, newlength); if (newmem == NULL) return (ISC_R_NOMEMORY); isc_mem_put(mctx, buffer->base, buffer->length); isc_buffer_init(buffer, newmem, newlength); } if (result != ISC_R_SUCCESS) return (result); /* * Write the buffer contents to the master file. */ isc_buffer_usedregion(buffer, &r); result = isc_stdio_write(r.base, 1, (size_t)r.length, f, NULL); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "master file write failed: %s", isc_result_totext(result)); return (result); } return (ISC_R_SUCCESS);}/* * Define the order in which rdatasets should be printed in zone * files. We will print SOA and NS records before others, SIGs * immediately following the things they sign, and order everything * else by RR number. This is all just for aesthetics and * compatibility with buggy software that expects the SOA to be first; * the DNS specifications allow any order. */static intdump_order(const dns_rdataset_t *rds) { int t; int sig; if (rds->type == dns_rdatatype_sig) { t = rds->covers; sig = 1; } else { t = rds->type; sig = 0; } switch (t) { case dns_rdatatype_soa: t = 0; break; case dns_rdatatype_ns: t = 1; break; default: t += 2; break; } return (t << 1) + sig;}static intdump_order_compare(const void *a, const void *b) { return (dump_order(*((const dns_rdataset_t * const *) a)) - dump_order(*((const dns_rdataset_t * const *) b)));}/* * Dump all the rdatasets of a domain name to a master file. We make * a "best effort" attempt to sort the RRsets in a nice order, but if * there are more than MAXSORT RRsets, we punt and only sort them in * groups of MAXSORT. This is not expected to ever happen in practice * since much less than 64 RR types have been registered with the * IANA, so far, and the output will be correct (though not * aesthetically pleasing) even if it does happen. */#define MAXSORT 64static const char *trustnames[] = { "none", "pending", "additional", "glue", "answer", "authauthority", "authanswer", "secure", "local" /* aka ultimate */};static isc_result_tdump_rdatasets(isc_mem_t *mctx, dns_name_t *name, dns_rdatasetiter_t *rdsiter, dns_totext_ctx_t *ctx, isc_buffer_t *buffer, FILE *f){ isc_result_t itresult, dumpresult; isc_region_t r; dns_rdataset_t rdatasets[MAXSORT]; dns_rdataset_t *sorted[MAXSORT]; int i, n; itresult = dns_rdatasetiter_first(rdsiter); dumpresult = ISC_R_SUCCESS; if (itresult == ISC_R_SUCCESS && ctx->neworigin != NULL) { isc_buffer_clear(buffer); itresult = dns_name_totext(ctx->neworigin, ISC_FALSE, buffer); RUNTIME_CHECK(itresult == ISC_R_SUCCESS); isc_buffer_usedregion(buffer, &r); fprintf(f, "$ORIGIN %.*s\n", (int) r.length, (char *) r.base); ctx->neworigin = NULL; } again: for (i = 0; itresult == ISC_R_SUCCESS && i < MAXSORT; itresult = dns_rdatasetiter_next(rdsiter), i++) { dns_rdataset_init(&rdatasets[i]); dns_rdatasetiter_current(rdsiter, &rdatasets[i]); sorted[i] = &rdatasets[i]; } n = i; INSIST(n <= MAXSORT); qsort(sorted, n, sizeof(sorted[0]), dump_order_compare); for (i = 0; i < n; i++) { dns_rdataset_t *rds = sorted[i]; if (ctx->style.flags & DNS_STYLEFLAG_TRUST) { unsigned int trust = rds->trust; INSIST(trust < (sizeof(trustnames) / sizeof(trustnames[0]))); fprintf(f, "; %s\n", trustnames[trust]); } if (rds->type == 0 && (ctx->style.flags & DNS_STYLEFLAG_NCACHE) == 0) { /* Omit negative cache entries */ } else { isc_result_t result = dump_rdataset(mctx, name, rds, ctx, buffer, f); if (result != ISC_R_SUCCESS) dumpresult = result; if ((ctx->style.flags & DNS_STYLEFLAG_OMIT_OWNER) != 0) name = NULL; } dns_rdataset_disassociate(rds); } if (dumpresult != ISC_R_SUCCESS) return (dumpresult); /* * If we got more data than could be sorted at once, * go handle the rest. */ if (itresult == ISC_R_SUCCESS) goto again; if (itresult == ISC_R_NOMORE) itresult = ISC_R_SUCCESS; return (itresult);}/* * Initial size of text conversion buffer. The buffer is used * for several purposes: converting origin names, rdatasets, * $DATE timestamps, and comment strings for $TTL directives. * * When converting rdatasets, it is dynamically resized, but * when converting origins, timestamps, etc it is not. Therefore, * the initial size must large enough to hold the longest possible * text representation of any domain name (for $ORIGIN). */static const int initial_buffer_length = 1200;/* * Dump an entire database into a master file. */isc_result_tdns_master_dumptostream(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, FILE *f){ dns_fixedname_t fixname; dns_name_t *name; dns_dbiterator_t *dbiter = NULL; isc_result_t result; isc_buffer_t buffer; char *bufmem; isc_stdtime_t now; isc_region_t r; dns_totext_ctx_t ctx; result = totext_ctx_init(style, &ctx); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "could not set master file style"); return (ISC_R_UNEXPECTED); } dns_fixedname_init(&fixname); name = dns_fixedname_name(&fixname); isc_stdtime_get(&now); bufmem = isc_mem_get(mctx, initial_buffer_length); if (bufmem == NULL) return (ISC_R_NOMEMORY); isc_buffer_init(&buffer, bufmem, initial_buffer_length); /* * If the database has cache semantics, output an RFC2540 * $DATE directive so that the TTLs can be adjusted when * it is reloaded. For zones it is not really needed, and * it would make the file incompatible with pre-RFC2540 * software, so we omit it in the zone case. */ if (dns_db_iscache(db)) { result = dns_time32_totext(now, &buffer); RUNTIME_CHECK(result == ISC_R_SUCCESS); isc_buffer_usedregion(&buffer, &r); fprintf(f, "$DATE %.*s\n", (int) r.length, (char *) r.base); } result = dns_db_createiterator(db, ((ctx.style.flags & DNS_STYLEFLAG_REL_OWNER) != 0) ? ISC_TRUE : ISC_FALSE, &dbiter); if (result != ISC_R_SUCCESS) goto create_iter_failure; result = dns_dbiterator_first(dbiter); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_t *rdsiter = NULL; dns_dbnode_t *node = NULL; result = dns_dbiterator_current(dbiter, &node, name); if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) break; if (result == DNS_R_NEWORIGIN) { dns_name_t *origin = dns_fixedname_name(&ctx.origin_fixname); result = dns_dbiterator_origin(dbiter, origin); RUNTIME_CHECK(result == ISC_R_SUCCESS); if ((ctx.style.flags & DNS_STYLEFLAG_REL_DATA) != 0) ctx.origin = origin; ctx.neworigin = origin; } result = dns_db_allrdatasets(db, node, version, now, &rdsiter); if (result != ISC_R_SUCCESS) { dns_db_detachnode(db, &node); goto iter_failure; } result = dump_rdatasets(mctx, name, rdsiter, &ctx, &buffer, f); if (result != ISC_R_SUCCESS) { dns_db_detachnode(db, &node); goto iter_failure; } dns_rdatasetiter_destroy(&rdsiter); dns_db_detachnode(db, &node); result = dns_dbiterator_next(dbiter); } if (result != ISC_R_NOMORE) goto iter_failure; result = ISC_R_SUCCESS; iter_failure: dns_dbiterator_destroy(&dbiter); create_iter_failure: isc_mem_put(mctx, buffer.base, buffer.length); return (result);}isc_result_tdns_master_dump(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, const char *filename){ FILE *f = NULL; isc_result_t result; char *tempname; int tempnamelen; tempnamelen = strlen(filename) + 20; tempname = isc_mem_get(mctx, tempnamelen); if (tempname == NULL) return (ISC_R_NOMEMORY); result = isc_file_mktemplate(filename, tempname, tempnamelen); if (result != ISC_R_SUCCESS) goto cleanup; result = isc_file_openunique(tempname, &f); if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, "dumping master file: %s: open: %s", tempname, isc_result_totext(result)); goto cleanup; } result = dns_master_dumptostream(mctx, db, version, style, f); if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, "dumping master file: %s: %s", tempname, isc_result_totext(result)); (void)isc_stdio_close(f); (void)isc_file_remove(tempname); goto cleanup; } result = isc_stdio_sync(f); if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, "dumping master file: %s: fsync: %s", tempname, isc_result_totext(result)); (void)isc_stdio_close(f); (void)isc_file_remove(tempname); goto cleanup; } result = isc_stdio_close(f); if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, "dumping master file: %s: close: %s", tempname, isc_result_totext(result)); (void)isc_file_remove(tempname); goto cleanup; } result = isc_file_rename(tempname, filename); if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, "dumping master file: rename: %s: %s", filename, isc_result_totext(result)); goto cleanup; } cleanup: isc_mem_put(mctx, tempname, tempnamelen); return (result);}/* * Dump a database node into a master file. */isc_result_tdns_master_dumpnodetostream(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node, dns_name_t *name, const dns_master_style_t *style, FILE *f){ isc_result_t result; isc_buffer_t buffer; char *bufmem; isc_stdtime_t now; dns_totext_ctx_t ctx; dns_rdatasetiter_t *rdsiter = NULL; result = totext_ctx_init(style, &ctx); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "could not set master file style"); return (ISC_R_UNEXPECTED); } isc_stdtime_get(&now); bufmem = isc_mem_get(mctx, initial_buffer_length); if (bufmem == NULL) return (ISC_R_NOMEMORY); isc_buffer_init(&buffer, bufmem, initial_buffer_length); result = dns_db_allrdatasets(db, node, version, now, &rdsiter); if (result != ISC_R_SUCCESS) goto failure; result = dump_rdatasets(mctx, name, rdsiter, &ctx, &buffer, f); if (result != ISC_R_SUCCESS) goto failure; dns_rdatasetiter_destroy(&rdsiter); result = ISC_R_SUCCESS; failure: isc_mem_put(mctx, buffer.base, buffer.length); return (result);}isc_result_tdns_master_dumpnode(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node, dns_name_t *name, const dns_master_style_t *style, const char *filename){ FILE *f = NULL; isc_result_t result; result = isc_stdio_open(filename, "w", &f); if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, "dumping node to file: %s: open: %s", filename, isc_result_totext(result)); return (ISC_R_UNEXPECTED); } result = dns_master_dumpnodetostream(mctx, db, version, node, name, style, f); result = isc_stdio_close(f); if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, "dumping master file: %s: close: %s", filename, isc_result_totext(result)); return (ISC_R_UNEXPECTED); } return (result);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -