⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 update.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
		return (result);	} else {		return (ISC_R_SUCCESS);	}}/* * Conditionally delete RRs.  Apply 'predicate' to the RRs * specified by 'db', 'ver', 'name', and 'type' (which can * be dns_rdatatype_any to match any type).  Delete those * RRs for which the predicate returns true, and log the * deletions in 'diff'. */static isc_result_tdelete_if(rr_predicate *predicate,	  dns_db_t *db,	  dns_dbversion_t *ver,	  dns_name_t *name,	  dns_rdatatype_t type,	  dns_rdatatype_t covers,	  dns_rdata_t *update_rr,	  dns_diff_t *diff){	conditional_delete_ctx_t ctx;	ctx.predicate = predicate;	ctx.db = db;	ctx.ver = ver;	ctx.diff = diff;	ctx.name = name;	ctx.update_rr = update_rr;	return (foreach_rr(db, ver, name, type, covers,			   delete_if_action, &ctx));}/**************************************************************************//* * Prepare an RR for the addition of the new RR 'ctx->update_rr', * with TTL 'ctx->update_rr_ttl', to its rdataset, by deleting * the RRs if it is replaced by the new RR or has a conflicting TTL. * The necessary changes are appended to ctx->del_diff and ctx->add_diff; * we need to do all deletions before any additions so that we don't run * into transient states with conflicting TTLs. */typedef struct {	dns_db_t *db;	dns_dbversion_t *ver;	dns_diff_t *diff;	dns_name_t *name;	dns_rdata_t *update_rr;	dns_ttl_t update_rr_ttl;	isc_boolean_t ignore_add;	dns_diff_t del_diff;	dns_diff_t add_diff;} add_rr_prepare_ctx_t;static isc_result_tadd_rr_prepare_action(void *data, rr_t *rr) {	isc_result_t result = ISC_R_SUCCESS;		add_rr_prepare_ctx_t *ctx = data;	dns_difftuple_t *tuple = NULL;	/*	 * If the update RR is a "duplicate" of the update RR,	 * the update should be silently ignored.	 */	if (dns_rdata_compare(&rr->rdata, ctx->update_rr) == 0 &&	    rr->ttl == ctx->update_rr_ttl) {		ctx->ignore_add = ISC_TRUE;	}	/*	 * If this RR is "equal" to the update RR, it should	 * be deleted before the update RR is added.	 */	if (replaces_p(ctx->update_rr, &rr->rdata)) {		CHECK(dns_difftuple_create(ctx->del_diff.mctx,					   DNS_DIFFOP_DEL, ctx->name,					   rr->ttl,					   &rr->rdata,					   &tuple));		dns_diff_append(&ctx->del_diff, &tuple);		return (ISC_R_SUCCESS);	}	/*	 * If this RR differs in TTL from the update RR,	 * its TTL must be adjusted.	 */	if (rr->ttl != ctx->update_rr_ttl) {		CHECK(dns_difftuple_create(ctx->del_diff.mctx,					   DNS_DIFFOP_DEL, ctx->name,					   rr->ttl,					   &rr->rdata,					   &tuple));		dns_diff_append(&ctx->del_diff, &tuple);		CHECK(dns_difftuple_create(ctx->add_diff.mctx,					   DNS_DIFFOP_ADD, ctx->name,					   ctx->update_rr_ttl,					   &rr->rdata,					   &tuple));		dns_diff_append(&ctx->add_diff, &tuple);	} failure:	return (result);}/**************************************************************************//* * Miscellaneous subroutines. *//* * Extract a single update RR from 'section' of dynamic update message * 'msg', with consistency checking. * * Stores the owner name, rdata, and TTL of the update RR at 'name', * 'rdata', and 'ttl', respectively. */static voidget_current_rr(dns_message_t *msg, dns_section_t section,	       dns_rdataclass_t zoneclass,	       dns_name_t **name, dns_rdata_t *rdata, dns_rdatatype_t *covers,	       dns_ttl_t *ttl,	       dns_rdataclass_t *update_class){	dns_rdataset_t *rdataset;	isc_result_t result;	dns_message_currentname(msg, section, name);	rdataset = ISC_LIST_HEAD((*name)->list);	INSIST(rdataset != NULL);	INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);	*covers = rdataset->covers;	*ttl = rdataset->ttl;	result = dns_rdataset_first(rdataset);	INSIST(result == ISC_R_SUCCESS);	dns_rdataset_current(rdataset, rdata);	INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE);	*update_class = rdata->rdclass;	rdata->rdclass = zoneclass;}/* * Increment the SOA serial number of database 'db', version 'ver'. * Replace the SOA record in the database, and log the * change in 'diff'. */	/*	 * XXXRTH  Failures in this routine will be worth logging, when	 *         we have a logging system.  Failure to find the zonename	 *	   or the SOA rdataset warrant at least an UNEXPECTED_ERROR().	 */static isc_result_tincrement_soa_serial(dns_db_t *db, dns_dbversion_t *ver,		     dns_diff_t *diff, isc_mem_t *mctx){	dns_difftuple_t *deltuple = NULL;	dns_difftuple_t *addtuple = NULL;	isc_uint32_t serial;	isc_result_t result;	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));	CHECK(dns_difftuple_copy(deltuple, &addtuple));	addtuple->op = DNS_DIFFOP_ADD;	serial = dns_soa_getserial(&addtuple->rdata);	/* RFC1982 */	serial = (serial + 1) & 0xFFFFFFFF;	if (serial == 0)		serial = 1;	dns_soa_setserial(serial, &addtuple->rdata);	CHECK(do_one_tuple(&deltuple, db, ver, diff));	CHECK(do_one_tuple(&addtuple, db, ver, diff));	result = ISC_R_SUCCESS; failure:	if (addtuple != NULL)		dns_difftuple_free(&addtuple);	if (deltuple != NULL)		dns_difftuple_free(&deltuple);	return (result);}/* * Check that the new SOA record at 'update_rdata' does not * illegally cause the SOA serial number to decrease or stay * unchanged relative to the existing SOA in 'db'. * * Sets '*ok' to ISC_TRUE if the update is legal, ISC_FALSE if not. * * William King points out that RFC2136 is inconsistent about * the case where the serial number stays unchanged: * *   section 3.4.2.2 requires a server to ignore a SOA update request *   if the serial number on the update SOA is less_than_or_equal to *   the zone SOA serial. * *   section 3.6 requires a server to ignore a SOA update request if *   the serial is less_than the zone SOA serial. * * Paul says 3.4.2.2 is correct. * */static isc_result_tcheck_soa_increment(dns_db_t *db, dns_dbversion_t *ver,		    dns_rdata_t *update_rdata,		    isc_boolean_t *ok){	isc_uint32_t db_serial;	isc_uint32_t update_serial;	isc_result_t result;	update_serial = dns_soa_getserial(update_rdata);	result = dns_db_getsoaserial(db, ver, &db_serial);	if (result != ISC_R_SUCCESS)		return (result);	if (DNS_SERIAL_GE(db_serial, update_serial)) {		*ok = ISC_FALSE;	} else {		*ok = ISC_TRUE;	}	return (ISC_R_SUCCESS);}/**************************************************************************//* * Incremental updating of NXTs and SIGs. */#define MAXZONEKEYS 32	/* Maximum number of zone keys supported. *//* * We abuse the dns_diff_t type to represent a set of domain names * affected by the update. */static isc_result_tnamelist_append_name(dns_diff_t *list, dns_name_t *name) {	isc_result_t result;	dns_difftuple_t *tuple = NULL;	static dns_rdata_t dummy_rdata = { NULL, 0, 0, 0, 0,					   { (void*)(-1), (void*)(-1) } };	CHECK(dns_difftuple_create(list->mctx, DNS_DIFFOP_EXISTS, name, 0,				   &dummy_rdata, &tuple));	dns_diff_append(list, &tuple); failure:	return (result);}static isc_result_tnamelist_append_subdomain(dns_db_t *db, dns_name_t *name, dns_diff_t *affected){	isc_result_t result;	dns_fixedname_t fixedname;	dns_name_t *child;	dns_dbiterator_t *dbit = NULL;	dns_fixedname_init(&fixedname);	child = dns_fixedname_name(&fixedname);	CHECK(dns_db_createiterator(db, ISC_FALSE, &dbit));	for (result = dns_dbiterator_seek(dbit, name);	     result == ISC_R_SUCCESS;	     result = dns_dbiterator_next(dbit))	{		dns_dbnode_t *node = NULL;		result = dns_dbiterator_current(dbit, &node, child);		dns_db_detachnode(db, &node);		CHECK(result);		if (! dns_name_issubdomain(child, name))			break;		CHECK(namelist_append_name(affected, child));	}	if (result == ISC_R_NOMORE)		result = ISC_R_SUCCESS; failure:	if (dbit != NULL)		dns_dbiterator_destroy(&dbit);	return (result);}/* * Helper function for non_nxt_rrset_exists(). */static isc_result_tis_non_nxt_action(void *data, dns_rdataset_t *rrset) {	UNUSED(data);	if (!(rrset->type == dns_rdatatype_nxt ||	      (rrset->type == dns_rdatatype_sig &&	       rrset->covers == dns_rdatatype_nxt)))		return (ISC_R_EXISTS);	return (ISC_R_SUCCESS);}/* * Check whether there is an rrset other than a NXT or SIG NXT, * i.e., anything that justifies the continued existence of a name * after a secure update. * * If such an rrset exists, set '*exists' to ISC_TRUE. * Otherwise, set it to ISC_FALSE. */static isc_result_tnon_nxt_rrset_exists(dns_db_t *db, dns_dbversion_t *ver,		     dns_name_t *name, isc_boolean_t *exists){	isc_result_t result;	result = foreach_rrset(db, ver, name,			       is_non_nxt_action, NULL);	RETURN_EXISTENCE_FLAG;}/* * A comparison function for sorting dns_diff_t:s by name. */static intname_order(const void *av, const void *bv) {	dns_difftuple_t const * const *ap = av;	dns_difftuple_t const * const *bp = bv;	dns_difftuple_t const *a = *ap;	dns_difftuple_t const *b = *bp;	return (dns_name_compare(&a->name, &b->name));}static isc_result_tuniqify_name_list(dns_diff_t *list) {	isc_result_t result;	dns_difftuple_t *p, *q;	CHECK(dns_diff_sort(list, name_order));	p = ISC_LIST_HEAD(list->tuples);	while (p != NULL) {		do {			q = ISC_LIST_NEXT(p, link);			if (q == NULL || ! dns_name_equal(&p->name, &q->name))				break;			ISC_LIST_UNLINK(list->tuples, q, link);			dns_difftuple_free(&q);		} while (1);		p = ISC_LIST_NEXT(p, link);	} failure:	return (result);}static isc_result_tis_glue(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,	isc_boolean_t *flag){	isc_result_t result;	dns_fixedname_t foundname;	dns_fixedname_init(&foundname);	result = dns_db_find(db, name, ver, dns_rdatatype_any,			     DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,			     (isc_stdtime_t) 0, NULL,			     dns_fixedname_name(&foundname),			     NULL, NULL);	if (result == ISC_R_SUCCESS) {		*flag = ISC_FALSE;		return (ISC_R_SUCCESS);	} else if (result == DNS_R_ZONECUT) {		/*		 * We are at the zonecut.  The name will have an NXT, but		 * non-delegation will be omitted from the type bit map.		 */		*flag = ISC_FALSE;		return (ISC_R_SUCCESS);	} else if (result == DNS_R_GLUE || result == DNS_R_DNAME) {		*flag = ISC_TRUE;		return (ISC_R_SUCCESS);	} else {		return (result);	}}/* * Find the next/previous name that has a NXT record. * In other words, skip empty database nodes and names that * have had their NXTs removed because they are obscured by * a zone cut. */static isc_result_tnext_active(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *oldname,     dns_name_t *newname, isc_boolean_t forward){	isc_result_t result;	dns_dbiterator_t *dbit = NULL;	isc_boolean_t has_nxt;	unsigned int wraps = 0;	CHECK(dns_db_createiterator(db, ISC_FALSE, &dbit));	CHECK(dns_dbiterator_seek(dbit, oldname));	do {		dns_dbnode_t *node = NULL;		if (forward)			result = dns_dbiterator_next(dbit);		else			result = dns_dbiterator_prev(dbit);		if (result == ISC_R_NOMORE) {			/*			 * Wrap around.			 */			if (forward)				CHECK(dns_dbiterator_first(dbit));			else				CHECK(dns_dbiterator_last(dbit));			wraps++;			if (wraps == 2) {				isc_log_write(ns_g_lctx, NS_LOGCATEGORY_UPDATE,					      NS_LOGMODULE_UPDATE,					      ISC_LOG_ERROR,					      "secure zone with no NXTs");				result = DNS_R_BADZONE;				goto failure;			}		}		dns_dbiterator_current(dbit, &node, newname);		dns_db_detachnode(db, &node);		/*		 * The iterator may hold the tree lock, and		 * rrset_exists() calls dns_db_findnode() which		 * may try to reacquire it.  To avoid deadlock		 * we must pause the iterator first.		 */		CHECK(dns_dbiterator_pause(dbit));		CHECK(rrset_exists(db, ver, newname,				   dns_rdatatype_nxt, 0, &has_nxt));	} while (! has_nxt); failure:	if (dbit != NULL)		dns_dbiterator_destroy(&dbit);	return (result);}/* * Add a NXT record for "name", recording the change in "diff". * The existing NXT is removed. */static isc_result_tadd_nxt(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_diff_t *diff){	isc_result_t result;	dns_dbnode_t *node = NULL;	unsigned char buffer[DNS_NXT_BUFFERSIZE];	dns_rdata_t rdata = DNS_RDATA_INIT;	dns_difftuple_t *tuple = NULL;	dns_fixedname_t fixedname;	dns_name_t *target;	dns_fixedname_init(&fixedname);	target = dns_fixedname_name(&fixedname);	/*	 * Find the successor name, aka NXT target.	 */	CHECK(next_active(db, ver, name, target, ISC_TRUE));	/*	 * Create the NXT RDATA.	 */	CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));	dns_rdata_init(&rdata);	CHECK(dns_nxt_buildrdata(db, ver, node, target, buffer, &rdata));	dns_db_detachnode(db, &node);	/*	 * Delete the old NXT and record the change.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -