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

📄 update.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
		      "update zone section empty");	/*	 * The zone section must contain exactly one "question", and	 * it must be of type SOA.	 */	zonename = NULL;	dns_message_currentname(request, DNS_SECTION_ZONE, &zonename);	zone_rdataset = ISC_LIST_HEAD(zonename->list);	if (zone_rdataset->type != dns_rdatatype_soa)		FAILC(DNS_R_FORMERR,		      "update zone section contains non-SOA");	if (ISC_LIST_NEXT(zone_rdataset, link) != NULL)		FAILC(DNS_R_FORMERR,		      "update zone section contains multiple RRs");	/* The zone section must have exactly one name. */	result = dns_message_nextname(request, DNS_SECTION_ZONE);	if (result != ISC_R_NOMORE)		FAILC(DNS_R_FORMERR,		      "update zone section contains multiple RRs");	result = dns_zt_find(client->view->zonetable, zonename, 0, NULL,			     &zone);	if (result != ISC_R_SUCCESS)		FAILC(DNS_R_NOTAUTH,		      "not authoritative for update zone");	switch(dns_zone_gettype(zone)) {	case dns_zone_master:		/*		 * We can now fail due to a bad signature as we now know		 * that we are the master.		 */		if (sigresult != ISC_R_SUCCESS)			FAIL(sigresult);		CHECK(send_update_event(client, zone));		break;	case dns_zone_slave:		CHECK(ns_client_checkacl(client, "update forwarding",					 dns_zone_getforwardacl(zone),					 ISC_FALSE, ISC_LOG_ERROR));		CHECK(send_forward_event(client, zone));		break;	default:		FAILC(DNS_R_NOTAUTH,		      "not authoritative for update zone");	}	return; failure:	/*	 * We failed without having sent an update event to the zone.	 * We are still in the client task context, so we can	 * simply give an error response without switching tasks.	 */	respond(client, result);	if (zone != NULL)		dns_zone_detach(&zone);}static voidupdate_action(isc_task_t *task, isc_event_t *event) {	update_event_t *uev = (update_event_t *) event;	dns_zone_t *zone = uev->zone;	ns_client_t *client = (ns_client_t *)event->ev_arg;	isc_result_t result;	dns_db_t *db = NULL;	dns_dbversion_t *oldver = NULL;	dns_dbversion_t *ver = NULL;	dns_diff_t diff; 	/* Pending updates. */	dns_diff_t temp; 	/* Pending RR existence assertions. */	isc_boolean_t soa_serial_changed = ISC_FALSE;	isc_mem_t *mctx = client->mctx;	dns_rdatatype_t covers;	dns_message_t *request = client->message;	dns_rdataclass_t zoneclass;	dns_name_t *zonename;	dns_ssutable_t *ssutable = NULL;	INSIST(event->ev_type == DNS_EVENT_UPDATE);	dns_diff_init(mctx, &diff);	dns_diff_init(mctx, &temp);	CHECK(dns_zone_getdb(zone, &db));	zonename = dns_db_origin(db);	zoneclass = dns_db_class(db);	dns_zone_getssutable(zone, &ssutable);	dns_db_currentversion(db, &oldver);	CHECK(dns_db_newversion(db, &ver));	/*	 * Check prerequisites.	 */	for (result = dns_message_firstname(request, DNS_SECTION_PREREQUISITE);	     result == ISC_R_SUCCESS;	     result = dns_message_nextname(request, DNS_SECTION_PREREQUISITE))	{		dns_name_t *name = NULL;		dns_rdata_t rdata = DNS_RDATA_INIT;		dns_ttl_t ttl;		dns_rdataclass_t update_class;		isc_boolean_t flag;		get_current_rr(request, DNS_SECTION_PREREQUISITE, zoneclass,			       &name, &rdata, &covers, &ttl, &update_class);		if (ttl != 0)			FAILC(DNS_R_FORMERR, "prerequisite TTL is not zero");		if (! dns_name_issubdomain(name, zonename))			FAILC(DNS_R_NOTZONE,				"prerequisite name is out of zone");		if (update_class == dns_rdataclass_any) {			if (rdata.length != 0)				FAILC(DNS_R_FORMERR,				      "class ANY prerequisite "				      "RDATA is not empty");			if (rdata.type == dns_rdatatype_any) {				CHECK(name_exists(db, ver, name, &flag));				if (! flag) {					FAILC(DNS_R_NXDOMAIN,					      "'name in use' prerequisite "					      "not satisfied");				}			} else {				CHECK(rrset_exists(db, ver, name,						   rdata.type, covers, &flag));				if (! flag) {					/* RRset does not exist. */					FAILC(DNS_R_NXRRSET,					"'rrset exists (value independent)' "					"prerequisite not satisfied");				}			}		} else if (update_class == dns_rdataclass_none) {			if (rdata.length != 0)				FAILC(DNS_R_FORMERR,				      "class NONE prerequisite "				      "RDATA is not empty");			if (rdata.type == dns_rdatatype_any) {				CHECK(name_exists(db, ver, name, &flag));				if (flag) {					FAILC(DNS_R_YXDOMAIN,					      "'name not in use' prerequisite "					      "not satisfied");				}			} else {				CHECK(rrset_exists(db, ver, name,						   rdata.type, covers, &flag));				if (flag) {					/* RRset exists. */					FAILC(DNS_R_YXRRSET,					      "'rrset does not exist' "					      "prerequisite not satisfied");				}			}		} else if (update_class == zoneclass) {			/* "temp<rr.name, rr.type> += rr;" */			result = temp_append(&temp, name, &rdata);			if (result != ISC_R_SUCCESS) {				UNEXPECTED_ERROR(__FILE__, __LINE__,					 "temp entry creation failed: %s",						 dns_result_totext(result));				FAIL(ISC_R_UNEXPECTED);			}		} else {			FAILC(DNS_R_FORMERR, "malformed prerequisite");		}	}	if (result != ISC_R_NOMORE)		FAIL(result);	/*	 * Perform the final check of the "rrset exists (value dependent)"	 * prerequisites.	 */	result = temp_check(mctx, &temp, db, ver);	if (result != ISC_R_SUCCESS)		FAILC(result, "'RRset exists (value dependent)' "		      "prerequisite not satisfied");	update_log(client, zone, LOGLEVEL_DEBUG,		   "prerequisites are OK");	/*	 * Check Requestor's Permissions.  It seems a bit silly to do this	 * only after prerequisite testing, but that is what RFC2136 says.	 */	if (ssutable == NULL) {		char msg[DNS_RDATACLASS_FORMATSIZE + DNS_NAME_FORMATSIZE			 + sizeof("update '/'")];		ns_client_aclmsg("update", zonename, client->view->rdclass,                                 msg, sizeof(msg));		CHECK(ns_client_checkacl(client, msg,					 dns_zone_getupdateacl(zone),					 ISC_FALSE, ISC_LOG_ERROR));	} else if (client->signer == NULL) {		/* This gets us a free log message. */		char msg[DNS_RDATACLASS_FORMATSIZE + DNS_NAME_FORMATSIZE			 + sizeof("update '/'")];		ns_client_aclmsg("update", zonename, client->view->rdclass,                                 msg, sizeof(msg));		CHECK(ns_client_checkacl(client, msg, NULL, ISC_FALSE,					 ISC_LOG_ERROR));	}	/*	 * Perform the Update Section Prescan.	 */	for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);	     result == ISC_R_SUCCESS;	     result = dns_message_nextname(request, DNS_SECTION_UPDATE))	{		dns_name_t *name = NULL;		dns_rdata_t rdata = DNS_RDATA_INIT;		dns_ttl_t ttl;		dns_rdataclass_t update_class;		get_current_rr(request, DNS_SECTION_UPDATE, zoneclass,			       &name, &rdata, &covers, &ttl, &update_class);		if (! dns_name_issubdomain(name, zonename))			FAILC(DNS_R_NOTZONE,			      "update RR is outside zone");		if (update_class == zoneclass) {			/*			 * Check for meta-RRs.  The RFC2136 pseudocode says			 * check for ANY|AXFR|MAILA|MAILB, but the text adds			 * "or any other QUERY metatype"			 */			if (dns_rdatatype_ismeta(rdata.type)) {				FAILC(DNS_R_FORMERR,				      "meta-RR in update");			}		} else if (update_class == dns_rdataclass_any) {			if (ttl != 0 || rdata.length != 0 ||			    (dns_rdatatype_ismeta(rdata.type) &&			     rdata.type != dns_rdatatype_any))				FAILC(DNS_R_FORMERR,				      "meta-RR in update");		} else if (update_class == dns_rdataclass_none) {			if (ttl != 0 ||			    dns_rdatatype_ismeta(rdata.type))				FAILC(DNS_R_FORMERR,				      "meta-RR in update");		} else {			update_log(client, zone, ISC_LOG_WARNING,				   "update RR has incorrect class %d",				   update_class);			FAIL(DNS_R_FORMERR);		}		/*		 * draft-ietf-dnsind-simple-secure-update-01 says		 * "Unlike traditional dynamic update, the client		 * is forbidden from updating NXT records."		 */		if (dns_db_issecure(db)) {			if (rdata.type == dns_rdatatype_nxt) {				FAILC(DNS_R_REFUSED,				      "explicit NXT updates are not allowed "				      "in secure zones");			}			else if (rdata.type == dns_rdatatype_sig) {				FAILC(DNS_R_REFUSED,				      "explicit SIG updates are currently not "				      "supported in secure zones");			}		}		if (ssutable != NULL && client->signer != NULL) {			if (rdata.type != dns_rdatatype_any) {				if (!dns_ssutable_checkrules(ssutable,							     client->signer,							     name, rdata.type))					FAILC(DNS_R_REFUSED,					      "rejected by secure update");			}			else {				if (!ssu_checkall(db, ver, name, ssutable,						  client->signer))					FAILC(DNS_R_REFUSED,					      "rejected by secure update");			}		}	}	if (result != ISC_R_NOMORE)		FAIL(result);	update_log(client, zone, LOGLEVEL_DEBUG,		   "update section prescan OK");	/*	 * Process the Update Section.	 */	for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);	     result == ISC_R_SUCCESS;	     result = dns_message_nextname(request, DNS_SECTION_UPDATE))	{		dns_name_t *name = NULL;		dns_rdata_t rdata = DNS_RDATA_INIT;		dns_ttl_t ttl;		dns_rdataclass_t update_class;		isc_boolean_t flag;		get_current_rr(request, DNS_SECTION_UPDATE, zoneclass,			       &name, &rdata, &covers, &ttl, &update_class);		if (update_class == zoneclass) {			if (rdata.type == dns_rdatatype_cname) {				CHECK(cname_incompatible_rrset_exists(db, ver,								      name,								      &flag));				if (flag) {					update_log(client, zone,						   LOGLEVEL_PROTOCOL,						   "attempt to add CNAME "						   "alongside non-CNAME "						   "ignored");					continue;				}			} else {				CHECK(rrset_exists(db, ver, name,						   dns_rdatatype_cname, 0,						   &flag));				if (flag &&				    ! dns_rdatatype_isdnssec(rdata.type))				{					update_log(client, zone,						   LOGLEVEL_PROTOCOL,						   "attempt to add non-CNAME "						   "alongside CNAME ignored");					continue;				}			}			if (rdata.type == dns_rdatatype_soa) {				isc_boolean_t ok;				CHECK(rrset_exists(db, ver, name,						   dns_rdatatype_soa, 0,						   &flag));				if (! flag) {					update_log(client, zone,						   LOGLEVEL_PROTOCOL,						   "attempt to create 2nd "						   "SOA ignored");					continue;				}				CHECK(check_soa_increment(db, ver, &rdata,							  &ok));				if (! ok) {					update_log(client, zone,						   LOGLEVEL_PROTOCOL,						   "SOA update failed to "						   "increment serial, "						   "ignoring it");					continue;				}				soa_serial_changed = ISC_TRUE;			}						update_log(client, zone,				   LOGLEVEL_PROTOCOL, "adding an RR");			/* Prepare the affected RRset for the addition. */			{				add_rr_prepare_ctx_t ctx;				ctx.db = db;				ctx.ver = ver;				ctx.diff = &diff;				ctx.name = name;				ctx.update_rr = &rdata;				ctx.update_rr_ttl = ttl;				ctx.ignore_add = ISC_FALSE;				dns_diff_init(mctx, &ctx.del_diff);				dns_diff_init(mctx, &ctx.add_diff);				CHECK(foreach_rr(db, ver, name, rdata.type, covers,						 add_rr_prepare_action, &ctx));				if (ctx.ignore_add) {					dns_diff_clear(&ctx.del_diff);					dns_diff_clear(&ctx.add_diff);				} else {					CHECK(do_diff(&ctx.del_diff, db, ver, &diff));					CHECK(do_diff(&ctx.add_diff, db, ver, &diff));					CHECK(update_one_rr(db, ver, &diff,							    DNS_DIFFOP_ADD,							    name, ttl, &rdata));				}			}		} else if (update_class == dns_rdataclass_any) {			if (rdata.type == dns_rdatatype_any) {				update_log(client, zone,					   LOGLEVEL_PROTOCOL,					   "delete all rrsets from a name");				if (dns_name_equal(name, zonename)) {					CHECK(delete_if(type_not_soa_nor_ns_p,							db, ver, name,							dns_rdatatype_any, 0,							&rdata, &diff));				} else {					CHECK(delete_if(true_p, db, ver, name,							dns_rdatatype_any, 0,							&rdata, &diff));				}			} else if (dns_name_equal(name, zonename) &&				   (rdata.type == dns_rdatatype_soa ||				    rdata.type == dns_rdatatype_ns)) {				update_log(client, zone,					   LOGLEVEL_PROTOCOL,					   "attempt to delete all SOA "					   "or NS records ignored");				continue;			} else {				update_log(client, zone,					   LOGLEVEL_PROTOCOL,					   "deleting an rrset");				CHECK(delete_if(true_p, db, ver, name,						rdata.type, covers, &rdata,						&diff));			}		} else if (update_class == dns_rdataclass_none) {			/*			 * The (name == zonename) condition appears in			 * RFC2136 3.4.2.4 but is missing from the pseudocode.			 */			if (dns_name_equal(name, zonename)) {				if (rdata.type == dns_rdatatype_soa) {					update_log(client, zone,						   LOGLEVEL_PROTOCOL,						   "attempt to delete SOA "						   "ignored");					continue;				}				if (rdata.type == dns_rdatatype_ns) {					int count;					CHECK(rr_count(db, ver, name,						       dns_rdatatype_ns,						       0, &count));					if (count == 1) {						update_log(client, zone,							   LOGLEVEL_PROTOCOL,							   "attempt to "							   "delete last "							   "NS ignored");						continue;					}				}			}			update_log(client, zone,				   LOGLEVEL_PROTOCOL,				   "deleting an RR");			CHECK(delete_if(rr_equal_p, db, ver, name,					rdata.type, covers, &rdata, &diff));		}	}	if (result != ISC_R_NOMORE)		FAIL(result);	/*	 * If any changes were made, increment the SOA serial number,	 * update SIGs and NXTs (if zone is secure), and write the update	 * to the journal.	 */	if (! ISC_LIST_EMPTY(diff.tuples)) {		char *journalfile;		dns_journal_t *journal;		/*		 * Increment the SOA serial, but only if it was not		 * changed as a result of an update operation.		 */		if (! soa_serial_changed) {			CHECK(increment_soa_serial(db, ver, &diff, mctx));		}		if (dns_db_issecure(db)) {			result = update_signatures(mctx, db, o

⌨️ 快捷键说明

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