📄 master.c
字号:
/* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. *//* $Id: master.c,v 1.122.2.8.2.14 2004/05/05 01:32:16 marka Exp $ */#include <config.h>#include <isc/event.h>#include <isc/lex.h>#include <isc/magic.h>#include <isc/mem.h>#include <isc/print.h>#include <isc/serial.h>#include <isc/stdtime.h>#include <isc/string.h>#include <isc/task.h>#include <isc/util.h>#include <dns/callbacks.h>#include <dns/events.h>#include <dns/fixedname.h>#include <dns/master.h>#include <dns/name.h>#include <dns/rdata.h>#include <dns/rdataclass.h>#include <dns/rdatalist.h>#include <dns/rdataset.h>#include <dns/rdatastruct.h>#include <dns/rdatatype.h>#include <dns/result.h>#include <dns/soa.h>#include <dns/time.h>#include <dns/ttl.h>/* * Grow the number of dns_rdatalist_t (RDLSZ) and dns_rdata_t (RDSZ) structures * by these sizes when we need to. * * RDLSZ reflects the number of different types with the same name expected. * RDSZ reflects the number of rdata expected at a give name that can fit into * 64k. */#define RDLSZ 32#define RDSZ 512#define NBUFS 4#define MAXWIRESZ 255/* * Target buffer size and minimum target size. * MINTSIZ must be big enough to hold the largest rdata record. * * TSIZ >= MINTSIZ */#define TSIZ (128*1024)/* * max message size - header - root - type - class - ttl - rdlen */#define MINTSIZ (65535 - 12 - 1 - 2 - 2 - 4 - 2)/* * Size for tokens in the presentation format, * The largest tokens are the base64 blocks in KEY and CERT records, * Largest key allowed is about 1372 bytes but * there is no fixed upper bound on CERT records. * 2K is too small for some X.509s, 8K is overkill. */#define TOKENSIZ (8*1024)#define DNS_MASTER_BUFSZ 2048typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;typedef struct dns_incctx dns_incctx_t;/* * Master file load state. */struct dns_loadctx { unsigned int magic; isc_mem_t *mctx; isc_lex_t *lex; isc_boolean_t keep_lex; dns_rdatacallbacks_t *callbacks; isc_task_t *task; dns_loaddonefunc_t done; void *done_arg; unsigned int options; isc_boolean_t ttl_known; isc_boolean_t default_ttl_known; isc_boolean_t warn_1035; isc_boolean_t warn_tcr; isc_boolean_t warn_sigexpired; isc_boolean_t seen_include; isc_uint32_t ttl; isc_uint32_t default_ttl; dns_rdataclass_t zclass; dns_fixedname_t fixed_top; dns_name_t *top; /* top of zone */ /* Which fixed buffers we are using? */ unsigned int loop_cnt; /* records per quantum, * 0 => all. */ isc_boolean_t canceled; isc_mutex_t lock; isc_result_t result; /* locked by lock */ isc_uint32_t references; dns_incctx_t *inc;};struct dns_incctx { dns_incctx_t *parent; dns_name_t *origin; dns_name_t *current; dns_name_t *glue; dns_fixedname_t fixed[NBUFS]; /* working buffers */ unsigned int in_use[NBUFS]; /* covert to bitmap? */ int glue_in_use; int current_in_use; int origin_in_use; isc_boolean_t drop; unsigned int glue_line; unsigned int current_line;};#define DNS_LCTX_MAGIC ISC_MAGIC('L','c','t','x')#define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)#define DNS_AS_STR(t) ((t).value.as_textregion.base)static isc_result_tpushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx);static isc_result_tcommit(dns_rdatacallbacks_t *, dns_loadctx_t *, rdatalist_head_t *, dns_name_t *, const char *, unsigned int);static isc_boolean_tis_glue(rdatalist_head_t *, dns_name_t *);static dns_rdatalist_t *grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *, rdatalist_head_t *, isc_mem_t *mctx);static dns_rdata_t *grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *, isc_mem_t *);static voidload_quantum(isc_task_t *task, isc_event_t *event);static isc_result_ttask_send(dns_loadctx_t *lctx);static voidloadctx_destroy(dns_loadctx_t *lctx);#define GETTOKEN(lexer, options, token, eol) \ do { \ result = gettoken(lexer, options, token, eol, callbacks); \ switch (result) { \ case ISC_R_SUCCESS: \ break; \ case ISC_R_UNEXPECTED: \ goto insist_and_cleanup; \ default: \ if (MANYERRS(lctx, result)) { \ SETRESULT(lctx, result); \ LOGIT(result); \ read_till_eol = ISC_TRUE; \ goto next_line; \ } else \ goto log_and_cleanup; \ } \ if ((token)->type == isc_tokentype_special) { \ result = DNS_R_SYNTAX; \ if (MANYERRS(lctx, result)) { \ SETRESULT(lctx, result); \ LOGIT(result); \ read_till_eol = ISC_TRUE; \ goto next_line; \ } else \ goto log_and_cleanup; \ } \ } while (0)#define COMMITALL \ do { \ result = commit(callbacks, lctx, ¤t_list, \ ictx->current, source, ictx->current_line); \ if (MANYERRS(lctx, result)) { \ SETRESULT(lctx, result); \ } else if (result != ISC_R_SUCCESS) \ goto insist_and_cleanup; \ result = commit(callbacks, lctx, &glue_list, \ ictx->glue, source, ictx->glue_line); \ if (MANYERRS(lctx, result)) { \ SETRESULT(lctx, result); \ } else if (result != ISC_R_SUCCESS) \ goto insist_and_cleanup; \ rdcount = 0; \ rdlcount = 0; \ isc_buffer_init(&target, target_mem, target_size); \ rdcount_save = rdcount; \ rdlcount_save = rdlcount; \ } while (0)#define WARNUNEXPECTEDEOF(lexer) \ do { \ if (isc_lex_isfile(lexer)) \ (*callbacks->warn)(callbacks, \ "%s: file does not end with newline", \ source); \ } while (0)#define EXPECTEOL \ do { \ GETTOKEN(lctx->lex, 0, &token, ISC_TRUE); \ if (token.type != isc_tokentype_eol) { \ isc_lex_ungettoken(lctx->lex, &token); \ result = DNS_R_EXTRATOKEN; \ if (MANYERRS(lctx, result)) { \ SETRESULT(lctx, result); \ LOGIT(result); \ read_till_eol = ISC_TRUE; \ continue; \ } else if (result != ISC_R_SUCCESS) \ goto log_and_cleanup; \ } \ } while (0)#define MANYERRS(lctx, result) \ ((result != ISC_R_SUCCESS) && \ ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)#define SETRESULT(lctx, r) \ do { \ if ((lctx)->result == ISC_R_SUCCESS) \ (lctx)->result = r; \ } while (0)#define LOGITFILE(result, filename) \ if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \ result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \ result == ISC_R_NOPERM) \ (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \ "dns_master_load", source, line, \ filename, dns_result_totext(result)); \ else LOGIT(result)#define LOGIT(result) \ if (result == ISC_R_NOMEMORY) \ (*callbacks->error)(callbacks, "dns_master_load: %s", \ dns_result_totext(result)); \ else \ (*callbacks->error)(callbacks, "%s: %s:%lu: %s", \ "dns_master_load", \ source, line, dns_result_totext(result))static unsigned char in_addr_arpa_data[] = "\007IN-ADDR\004ARPA";static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 };static const dns_name_t in_addr_arpa ={ DNS_NAME_MAGIC, in_addr_arpa_data, 14, 3, DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, in_addr_arpa_offsets, NULL, {(void *)-1, (void *)-1}, {NULL, NULL}};static unsigned char ip6_int_data[] = "\003IP6\003INT";static unsigned char ip6_int_offsets[] = { 0, 4, 8 };static const dns_name_t ip6_int ={ DNS_NAME_MAGIC, ip6_int_data, 9, 3, DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, ip6_int_offsets, NULL, {(void *)-1, (void *)-1}, {NULL, NULL}};static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA";static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };static const dns_name_t ip6_arpa ={ DNS_NAME_MAGIC, ip6_arpa_data, 10, 3, DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, ip6_arpa_offsets, NULL, {(void *)-1, (void *)-1}, {NULL, NULL}};static inline isc_result_tgettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token, isc_boolean_t eol, dns_rdatacallbacks_t *callbacks){ isc_result_t result; options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE; result = isc_lex_gettoken(lex, options, token); if (result != ISC_R_SUCCESS) { switch (result) { case ISC_R_NOMEMORY: return (ISC_R_NOMEMORY); default: (*callbacks->error)(callbacks, "dns_master_load: %s:%lu:" " isc_lex_gettoken() failed: %s", isc_lex_getsourcename(lex), isc_lex_getsourceline(lex), isc_result_totext(result)); return (result); } /*NOTREACHED*/ } if (eol != ISC_TRUE) if (token->type == isc_tokentype_eol || token->type == isc_tokentype_eof) { (*callbacks->error)(callbacks, "dns_master_load: %s:%lu: unexpected end of %s", isc_lex_getsourcename(lex), isc_lex_getsourceline(lex), (token->type == isc_tokentype_eol) ? "line" : "file"); return (ISC_R_UNEXPECTEDEND); } return (ISC_R_SUCCESS);}voiddns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) { REQUIRE(target != NULL && *target == NULL); REQUIRE(DNS_LCTX_VALID(source)); LOCK(&source->lock); INSIST(source->references > 0); source->references++; INSIST(source->references != 0); /* Overflow? */ UNLOCK(&source->lock); *target = source;}voiddns_loadctx_detach(dns_loadctx_t **lctxp) { dns_loadctx_t *lctx; isc_boolean_t need_destroy = ISC_FALSE; REQUIRE(lctxp != NULL); lctx = *lctxp; REQUIRE(DNS_LCTX_VALID(lctx)); LOCK(&lctx->lock); INSIST(lctx->references > 0); lctx->references--; if (lctx->references == 0) need_destroy = ISC_TRUE; UNLOCK(&lctx->lock); if (need_destroy) loadctx_destroy(lctx); *lctxp = NULL;}static voidincctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) { dns_incctx_t *parent; again: parent = ictx->parent; ictx->parent = NULL; isc_mem_put(mctx, ictx, sizeof(*ictx)); if (parent != NULL) { ictx = parent; goto again; }}static voidloadctx_destroy(dns_loadctx_t *lctx) { isc_mem_t *mctx; REQUIRE(DNS_LCTX_VALID(lctx)); lctx->magic = 0; if (lctx->inc != NULL) incctx_destroy(lctx->mctx, lctx->inc); /* isc_lex_destroy() will close all open streams */ if (lctx->lex != NULL && !lctx->keep_lex) isc_lex_destroy(&lctx->lex); if (lctx->task != NULL) isc_task_detach(&lctx->task); DESTROYLOCK(&lctx->lock); mctx = NULL; isc_mem_attach(lctx->mctx, &mctx); isc_mem_detach(&lctx->mctx); isc_mem_put(mctx, lctx, sizeof(*lctx)); isc_mem_detach(&mctx);}static isc_result_tincctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) { dns_incctx_t *ictx; isc_region_t r; int i; ictx = isc_mem_get(mctx, sizeof(*ictx)); if (ictx == NULL) return (ISC_R_NOMEMORY); for (i = 0; i < NBUFS; i++) { dns_fixedname_init(&ictx->fixed[i]); ictx->in_use[i] = ISC_FALSE; } ictx->origin_in_use = 0; ictx->origin = dns_fixedname_name(&ictx->fixed[ictx->origin_in_use]); ictx->in_use[ictx->origin_in_use] = ISC_TRUE; dns_name_toregion(origin, &r); dns_name_fromregion(ictx->origin, &r); ictx->glue = NULL; ictx->current = NULL; ictx->glue_in_use = -1; ictx->current_in_use = -1; ictx->parent = NULL; ictx->drop = ISC_FALSE; ictx->glue_line = 0; ictx->current_line = 0; *ictxp = ictx; return (ISC_R_SUCCESS);}static isc_result_tloadctx_create(isc_mem_t *mctx, unsigned int options, dns_name_t *top, dns_rdataclass_t zclass, dns_name_t *origin, dns_rdatacallbacks_t *callbacks, isc_task_t *task, dns_loaddonefunc_t done, void *done_arg, isc_lex_t *lex, dns_loadctx_t **lctxp){ dns_loadctx_t *lctx; isc_result_t result; isc_region_t r; isc_lexspecials_t specials; REQUIRE(lctxp != NULL && *lctxp == NULL); REQUIRE(callbacks != NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -