示例#1
0
void
dns_tkeyctx_destroy(dns_tkeyctx_t **tctxp) {
	isc_mem_t *mctx;
	dns_tkeyctx_t *tctx;

	REQUIRE(tctxp != NULL && *tctxp != NULL);

	tctx = *tctxp;
	mctx = tctx->mctx;

	if (tctx->dhkey != NULL)
		dst_key_free(&tctx->dhkey);
	if (tctx->domain != NULL) {
		if (dns_name_dynamic(tctx->domain))
			dns_name_free(tctx->domain, mctx);
		isc_mem_put(mctx, tctx->domain, sizeof(dns_name_t));
	}
	if (tctx->gssapi_keytab != NULL) {
		isc_mem_free(mctx, tctx->gssapi_keytab);
	}
	if (tctx->gsscred != NULL)
		dst_gssapi_releasecred(&tctx->gsscred);
	isc_entropy_detach(&tctx->ectx);
	isc_mem_put(mctx, tctx, sizeof(dns_tkeyctx_t));
	isc_mem_detach(&mctx);
	*tctxp = NULL;
}
示例#2
0
static void
levent_destroy(isc_event_t *event) {
	dns_lookupevent_t *levent;
	isc_mem_t *mctx;
 
	REQUIRE(event->ev_type == DNS_EVENT_LOOKUPDONE);
	mctx = event->ev_destroy_arg;
	levent = (dns_lookupevent_t *)event;

	if (levent->name != NULL) {
		if (dns_name_dynamic(levent->name))
			dns_name_free(levent->name, mctx);
		isc_mem_put(mctx, levent->name, sizeof(dns_name_t));
	}
	if (levent->rdataset != NULL) {
		dns_rdataset_disassociate(levent->rdataset);
		isc_mem_put(mctx, levent->rdataset, sizeof(dns_rdataset_t));
	}
	if (levent->sigrdataset != NULL) {
		dns_rdataset_disassociate(levent->sigrdataset);
		isc_mem_put(mctx, levent->sigrdataset, sizeof(dns_rdataset_t));
	}
	if (levent->node != NULL)
		dns_db_detachnode(levent->db, &levent->node);
	if (levent->db != NULL)
		dns_db_detach(&levent->db);
	isc_mem_put(mctx, event, event->ev_size);
}
示例#3
0
void
ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
			  isc_dscp_t **dscpsp, dns_name_t ***keysp,
			  isc_uint32_t count)
{
	unsigned int i;
	dns_name_t **keys;

	REQUIRE(addrsp != NULL && *addrsp != NULL);
	REQUIRE(dscpsp == NULL || *dscpsp != NULL);
	REQUIRE(keysp != NULL && *keysp != NULL);

	keys = *keysp;

	isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
	if (dscpsp != NULL)
		isc_mem_put(mctx, *dscpsp, count * sizeof(isc_dscp_t));
	for (i = 0; i < count; i++) {
		if (keys[i] == NULL)
			continue;
		if (dns_name_dynamic(keys[i]))
			dns_name_free(keys[i], mctx);
		isc_mem_put(mctx, keys[i], sizeof(dns_name_t));
	}
	isc_mem_put(mctx, *keysp, count * sizeof(dns_name_t *));
	*addrsp = NULL;
	if (dscpsp != NULL)
		*dscpsp = NULL;
	*keysp = NULL;
}
示例#4
0
isc_result_t
isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
			 dns_rdataset_t *nsec, dns_rdataset_t *nsecsig)
{
	dns_rdataclass_t rdclass = rdataset->rdclass;
	dns_rdataset_t *tnsec = NULL;
	dns_rdataset_t *tnsecsig = NULL;
	dns_name_t *noqname = rdataset->private6;

	REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0);
	(void)dns_name_dynamic(noqname);	/* Sanity Check. */

	for (rdataset = ISC_LIST_HEAD(noqname->list);
	     rdataset != NULL;
	     rdataset = ISC_LIST_NEXT(rdataset, link))
	{
		if (rdataset->rdclass != rdclass)
			continue;
		if (rdataset->type == dns_rdatatype_nsec)
			tnsec = rdataset;
		if (rdataset->type == dns_rdatatype_rrsig &&
		    rdataset->covers == dns_rdatatype_nsec)
			tnsecsig = rdataset;
	}
	if (tnsec == NULL || tnsecsig == NULL)
		return (ISC_R_NOTFOUND);

	dns_name_clone(noqname, name);
	dns_rdataset_clone(tnsec, nsec);
	dns_rdataset_clone(tnsecsig, nsecsig);
	return (ISC_R_SUCCESS);
}
示例#5
0
isc_result_t
ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
	      dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
	      void *driverarg, dns_db_t **dbp)
{
	ldapdb_t *ldapdb = NULL;
	isc_result_t result;
	isc_boolean_t lock_ready = ISC_FALSE;

	UNUSED(driverarg); /* Currently we don't need any data */

	/* Database instance name. */
	REQUIRE(argc == LDAP_DB_ARGC);
	REQUIRE(type == LDAP_DB_TYPE);
	REQUIRE(rdclass == LDAP_DB_RDATACLASS);
	REQUIRE(dbp != NULL && *dbp == NULL);

	CHECKED_MEM_GET_PTR(mctx, ldapdb);
	ZERO_PTR(ldapdb);

	isc_mem_attach(mctx, &ldapdb->common.mctx);
	CHECK(isc_mutex_init(&ldapdb->newversion_lock));
	lock_ready = ISC_TRUE;
	dns_name_init(&ldapdb->common.origin, NULL);
	isc_ondestroy_init(&ldapdb->common.ondest);

	ldapdb->common.magic = DNS_DB_MAGIC;
	ldapdb->common.impmagic = LDAPDB_MAGIC;

	ldapdb->common.methods = &ldapdb_methods;
	ldapdb->common.attributes = 0;
	ldapdb->common.rdclass = rdclass;

	CHECK(dns_name_dupwithoffsets(name, mctx, &ldapdb->common.origin));

	CHECK(isc_refcount_init(&ldapdb->refs, 1));
	CHECK(manager_get_ldap_instance(argv[0], &ldapdb->ldap_inst));

	CHECK(dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
			    dns_rdataclass_in, 0, NULL, &ldapdb->rbtdb));

	*dbp = (dns_db_t *)ldapdb;

	return ISC_R_SUCCESS;

cleanup:
	if (ldapdb != NULL) {
		if (lock_ready == ISC_TRUE)
			RUNTIME_CHECK(isc_mutex_destroy(&ldapdb->newversion_lock)
				      == ISC_R_SUCCESS);
		if (dns_name_dynamic(&ldapdb->common.origin))
			dns_name_free(&ldapdb->common.origin, mctx);

		isc_mem_putanddetach(&ldapdb->common.mctx, ldapdb,
				     sizeof(*ldapdb));
	}

	return result;
}
示例#6
0
static isc_result_t
build_event(dns_lookup_t *lookup) {
	dns_name_t *name = NULL;
	dns_rdataset_t *rdataset = NULL;
	dns_rdataset_t *sigrdataset = NULL;
	isc_result_t result;

	name = isc_mem_get(lookup->mctx, sizeof(dns_name_t));
	if (name == NULL) {
		result = ISC_R_NOMEMORY;
		goto fail;
	}
	dns_name_init(name, NULL);
	result = dns_name_dup(dns_fixedname_name(&lookup->name),
			      lookup->mctx, name);
	if (result != ISC_R_SUCCESS)
		goto fail;

	if (dns_rdataset_isassociated(&lookup->rdataset)) {
		rdataset = isc_mem_get(lookup->mctx, sizeof(dns_rdataset_t));
		if (rdataset == NULL) {
			result = ISC_R_NOMEMORY;
			goto fail;
		}
		dns_rdataset_init(rdataset);
		dns_rdataset_clone(&lookup->rdataset, rdataset);
	}

	if (dns_rdataset_isassociated(&lookup->sigrdataset)) {
		sigrdataset = isc_mem_get(lookup->mctx,
					  sizeof(dns_rdataset_t));
		if (sigrdataset == NULL) {
			result = ISC_R_NOMEMORY;
			goto fail;
		}
		dns_rdataset_init(sigrdataset);
		dns_rdataset_clone(&lookup->sigrdataset, sigrdataset);
	}

	lookup->event->name = name;
	lookup->event->rdataset = rdataset;
	lookup->event->sigrdataset = sigrdataset;

	return (ISC_R_SUCCESS);

 fail:
	if (name != NULL) {
		if (dns_name_dynamic(name))
			dns_name_free(name, lookup->mctx);
		isc_mem_put(lookup->mctx, name, sizeof(dns_name_t));
	}
	if (rdataset != NULL) {
		if (dns_rdataset_isassociated(rdataset))
			dns_rdataset_disassociate(rdataset);
		isc_mem_put(lookup->mctx, rdataset, sizeof(dns_rdataset_t));
	}
	return (result);
}
示例#7
0
文件: rpz.c 项目: KaiToTo/freebsd
/*
 * Forget a view's list of policy zones.
 */
void
dns_rpz_view_destroy(dns_view_t *view) {
	dns_rpz_zone_t *zone;

	REQUIRE(view != NULL);

	while (!ISC_LIST_EMPTY(view->rpz_zones)) {
		zone = ISC_LIST_HEAD(view->rpz_zones);
		ISC_LIST_UNLINK(view->rpz_zones, zone, link);
		if (dns_name_dynamic(&zone->origin))
			dns_name_free(&zone->origin, view->mctx);
		if (dns_name_dynamic(&zone->nsdname))
			dns_name_free(&zone->nsdname, view->mctx);
		if (dns_name_dynamic(&zone->cname))
			dns_name_free(&zone->cname, view->mctx);
		isc_mem_put(view->mctx, zone, sizeof(*zone));
	}
}
示例#8
0
static isc_result_t
dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
		dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
		void *driverarg, dns_db_t **dbp)
{
	dns_ecdb_t *ecdb;
	isc_result_t result;

	REQUIRE(mctx != NULL);
	REQUIRE(origin == dns_rootname);
	REQUIRE(type == dns_dbtype_cache);
	REQUIRE(dbp != NULL && *dbp == NULL);

	UNUSED(argc);
	UNUSED(argv);
	UNUSED(driverarg);

	ecdb = isc_mem_get(mctx, sizeof(*ecdb));
	if (ecdb == NULL)
		return (ISC_R_NOMEMORY);

	ecdb->common.attributes = DNS_DBATTR_CACHE;
	ecdb->common.rdclass = rdclass;
	ecdb->common.methods = &ecdb_methods;
	dns_name_init(&ecdb->common.origin, NULL);
	result = dns_name_dupwithoffsets(origin, mctx, &ecdb->common.origin);
	if (result != ISC_R_SUCCESS) {
		isc_mem_put(mctx, ecdb, sizeof(*ecdb));
		return (result);
	}

	result = isc_mutex_init(&ecdb->lock);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_mutex_init() failed: %s",
				 isc_result_totext(result));
		if (dns_name_dynamic(&ecdb->common.origin))
			dns_name_free(&ecdb->common.origin, mctx);
		isc_mem_put(mctx, ecdb, sizeof(*ecdb));
		return (ISC_R_UNEXPECTED);
	}

	ecdb->references = 1;
	ISC_LIST_INIT(ecdb->nodes);

	ecdb->common.mctx = NULL;
	isc_mem_attach(mctx, &ecdb->common.mctx);
	ecdb->common.impmagic = ECDB_MAGIC;
	ecdb->common.magic = DNS_DB_MAGIC;

	*dbp = (dns_db_t *)ecdb;

	return (ISC_R_SUCCESS);
}
示例#9
0
static void
destroy_ecdb(dns_ecdb_t **ecdbp) {
	dns_ecdb_t *ecdb = *ecdbp;
	isc_mem_t *mctx = ecdb->common.mctx;

	if (dns_name_dynamic(&ecdb->common.origin))
		dns_name_free(&ecdb->common.origin, mctx);

	DESTROYLOCK(&ecdb->lock);

	ecdb->common.impmagic = 0;
	ecdb->common.magic = 0;

	isc_mem_putanddetach(&mctx, ecdb, sizeof(*ecdb));

	*ecdbp = NULL;
}
示例#10
0
isc_result_t
isc__rdatalist_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
			  dns_rdataset_t *neg, dns_rdataset_t *negsig)
{
	dns_rdataclass_t rdclass = rdataset->rdclass;
	dns_rdataset_t *tneg = NULL;
	dns_rdataset_t *tnegsig = NULL;
	dns_name_t *closest = rdataset->private7;

	REQUIRE((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0);
	(void)dns_name_dynamic(closest);	/* Sanity Check. */

	for (rdataset = ISC_LIST_HEAD(closest->list);
	     rdataset != NULL;
	     rdataset = ISC_LIST_NEXT(rdataset, link))
	{
		if (rdataset->rdclass != rdclass)
			continue;
		if (rdataset->type == dns_rdatatype_nsec ||
		    rdataset->type == dns_rdatatype_nsec3)
			tneg = rdataset;
	}
	if (tneg == NULL)
		return (ISC_R_NOTFOUND);

	for (rdataset = ISC_LIST_HEAD(closest->list);
	     rdataset != NULL;
	     rdataset = ISC_LIST_NEXT(rdataset, link))
	{
		if (rdataset->type == dns_rdatatype_rrsig &&
		    rdataset->covers == tneg->type)
			tnegsig = rdataset;
	}
	if (tnegsig == NULL)
		return (ISC_R_NOTFOUND);

	dns_name_clone(closest, name);
	dns_rdataset_clone(tneg, neg);
	dns_rdataset_clone(tnegsig, negsig);
	return (ISC_R_SUCCESS);
}
isc_result_t
dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant,
		     dns_name_t *identity, unsigned int matchtype,
		     dns_name_t *name, unsigned int ntypes,
		     dns_rdatatype_t *types)
{
	dns_ssurule_t *rule;
	isc_mem_t *mctx;
	isc_result_t result;

	REQUIRE(VALID_SSUTABLE(table));
	REQUIRE(dns_name_isabsolute(identity));
	REQUIRE(dns_name_isabsolute(name));
	REQUIRE(matchtype <= DNS_SSUMATCHTYPE_MAX);
	if (matchtype == DNS_SSUMATCHTYPE_WILDCARD)
		REQUIRE(dns_name_iswildcard(name));
	if (ntypes > 0)
		REQUIRE(types != NULL);

	mctx = table->mctx;
	rule = isc_mem_get(mctx, sizeof(dns_ssurule_t));
	if (rule == NULL)
		return (ISC_R_NOMEMORY);

	rule->identity = NULL;
	rule->name = NULL;
	rule->types = NULL;

	rule->grant = grant;

	rule->identity = isc_mem_get(mctx, sizeof(dns_name_t));
	if (rule->identity == NULL) {
		result = ISC_R_NOMEMORY;
		goto failure;
	}
	dns_name_init(rule->identity, NULL);
	result = dns_name_dup(identity, mctx, rule->identity);
	if (result != ISC_R_SUCCESS)
		goto failure;

	rule->name = isc_mem_get(mctx, sizeof(dns_name_t));
	if (rule->name == NULL) {
		result = ISC_R_NOMEMORY;
		goto failure;
	}
	dns_name_init(rule->name, NULL);
	result = dns_name_dup(name, mctx, rule->name);
	if (result != ISC_R_SUCCESS)
		goto failure;

	rule->matchtype = matchtype;

	rule->ntypes = ntypes;
	if (ntypes > 0) {
		rule->types = isc_mem_get(mctx,
					  ntypes * sizeof(dns_rdatatype_t));
		if (rule->types == NULL) {
			result = ISC_R_NOMEMORY;
			goto failure;
		}
		memmove(rule->types, types, ntypes * sizeof(dns_rdatatype_t));
	} else
		rule->types = NULL;

	rule->magic = SSURULEMAGIC;
	ISC_LIST_INITANDAPPEND(table->rules, rule, link);

	return (ISC_R_SUCCESS);

 failure:
	if (rule->identity != NULL) {
		if (dns_name_dynamic(rule->identity))
			dns_name_free(rule->identity, mctx);
		isc_mem_put(mctx, rule->identity, sizeof(dns_name_t));
	}
	if (rule->name != NULL) {
		if (dns_name_dynamic(rule->name))
			dns_name_free(rule->name, mctx);
		isc_mem_put(mctx, rule->name, sizeof(dns_name_t));
	}
	if (rule->types != NULL)
		isc_mem_put(mctx, rule->types,
			    ntypes * sizeof(dns_rdatatype_t));
	isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));

	return (result);
}
示例#12
0
文件: tsig.c 项目: execunix/vinos
isc_result_t
dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
			  dst_key_t *dstkey, isc_boolean_t generated,
			  dns_name_t *creator, isc_stdtime_t inception,
			  isc_stdtime_t expire, isc_mem_t *mctx,
			  dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
{
	dns_tsigkey_t *tkey;
	isc_result_t ret;
	unsigned int refs = 0;

	REQUIRE(key == NULL || *key == NULL);
	REQUIRE(name != NULL);
	REQUIRE(algorithm != NULL);
	REQUIRE(mctx != NULL);
	REQUIRE(key != NULL || ring != NULL);

	tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
	if (tkey == NULL)
		return (ISC_R_NOMEMORY);

	dns_name_init(&tkey->name, NULL);
	ret = dns_name_dup(name, mctx, &tkey->name);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_key;
	(void)dns_name_downcase(&tkey->name, &tkey->name, NULL);

	if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACMD5_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA1_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA224_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA224) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA256_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA256) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA384_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA384) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA512_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA512) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
		tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
		tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else {
		if (dstkey != NULL) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
		tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t));
		if (tkey->algorithm == NULL) {
			ret = ISC_R_NOMEMORY;
			goto cleanup_name;
		}
		dns_name_init(tkey->algorithm, NULL);
		ret = dns_name_dup(algorithm, mctx, tkey->algorithm);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_algorithm;
		(void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
					NULL);
	}

	if (creator != NULL) {
		tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
		if (tkey->creator == NULL) {
			ret = ISC_R_NOMEMORY;
			goto cleanup_algorithm;
		}
		dns_name_init(tkey->creator, NULL);
		ret = dns_name_dup(creator, mctx, tkey->creator);
		if (ret != ISC_R_SUCCESS) {
			isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
			goto cleanup_algorithm;
		}
	} else
		tkey->creator = NULL;

	tkey->key = NULL;
	if (dstkey != NULL)
		dst_key_attach(dstkey, &tkey->key);
	tkey->ring = ring;

	if (key != NULL)
		refs = 1;
	if (ring != NULL)
		refs++;
	ret = isc_refcount_init(&tkey->refs, refs);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_creator;

	tkey->generated = generated;
	tkey->inception = inception;
	tkey->expire = expire;
	tkey->mctx = NULL;
	isc_mem_attach(mctx, &tkey->mctx);
	ISC_LINK_INIT(tkey, link);

	tkey->magic = TSIG_MAGIC;

	if (ring != NULL) {
		ret = keyring_add(ring, name, tkey);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_refs;
	}

	/*
	 * Ignore this if it's a GSS key, since the key size is meaningless.
	 */
	if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
	    !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
	    !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
		char namestr[DNS_NAME_FORMATSIZE];
		dns_name_format(name, namestr, sizeof(namestr));
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
			      DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
			      "the key '%s' is too short to be secure",
			      namestr);
	}

	if (key != NULL)
		*key = tkey;

	return (ISC_R_SUCCESS);

 cleanup_refs:
	tkey->magic = 0;
	while (refs-- > 0)
		isc_refcount_decrement(&tkey->refs, NULL);
	isc_refcount_destroy(&tkey->refs);
 cleanup_creator:
	if (tkey->key != NULL)
		dst_key_free(&tkey->key);
	if (tkey->creator != NULL) {
		dns_name_free(tkey->creator, mctx);
		isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
	}
 cleanup_algorithm:
	if (algname_is_allocated(tkey->algorithm)) {
		if (dns_name_dynamic(tkey->algorithm))
			dns_name_free(tkey->algorithm, mctx);
		isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t));
	}
 cleanup_name:
	dns_name_free(&tkey->name, mctx);
 cleanup_key:
	isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));

	return (ret);
}
示例#13
0
isc_result_t
dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
			  dst_key_t *dstkey, isc_boolean_t generated,
			  dns_name_t *creator, isc_stdtime_t inception,
			  isc_stdtime_t expire, isc_mem_t *mctx,
			  dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
{
	dns_tsigkey_t *tkey;
	isc_result_t ret;
	unsigned int refs = 0;

	REQUIRE(key == NULL || *key == NULL);
	REQUIRE(name != NULL);
	REQUIRE(algorithm != NULL);
	REQUIRE(mctx != NULL);

	tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
	if (tkey == NULL)
		return (ISC_R_NOMEMORY);

	dns_name_init(&tkey->name, NULL);
	ret = dns_name_dup(name, mctx, &tkey->name);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_key;
	(void)dns_name_downcase(&tkey->name, &tkey->name, NULL);

	if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACMD5_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
		tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
		tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else {
		if (key != NULL) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
		tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t));
		if (tkey->algorithm == NULL) {
			ret = ISC_R_NOMEMORY;
			goto cleanup_name;
		}
		dns_name_init(tkey->algorithm, NULL);
		ret = dns_name_dup(algorithm, mctx, tkey->algorithm);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_algorithm;
		(void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
					NULL);
	}

	if (creator != NULL) {
		tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
		if (tkey->creator == NULL) {
			ret = ISC_R_NOMEMORY;
			goto cleanup_algorithm;
		}
		dns_name_init(tkey->creator, NULL);
		ret = dns_name_dup(creator, mctx, tkey->creator);
		if (ret != ISC_R_SUCCESS) {
			isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
			goto cleanup_algorithm;
		}
	} else
		tkey->creator = NULL;

	tkey->key = dstkey;
	tkey->ring = ring;

	if (ring != NULL) {
		RWLOCK(&ring->lock, isc_rwlocktype_write);
		ret = dns_rbt_addname(ring->keys, name, tkey);
		if (ret != ISC_R_SUCCESS) {
			RWUNLOCK(&ring->lock, isc_rwlocktype_write);
			goto cleanup_algorithm;
		}
		refs++;
		RWUNLOCK(&ring->lock, isc_rwlocktype_write);
	}

	if (key != NULL)
		refs++;
	isc_refcount_init(&tkey->refs, refs);
	tkey->generated = generated;
	tkey->inception = inception;
	tkey->expire = expire;
	tkey->mctx = mctx;

	tkey->magic = TSIG_MAGIC;

	if (dstkey != NULL && dst_key_size(dstkey) < 64) {
		char namestr[DNS_NAME_FORMATSIZE];
		dns_name_format(name, namestr, sizeof(namestr));
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
			      DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
			      "the key '%s' is too short to be secure",
			      namestr);
	}
	if (key != NULL)
		*key = tkey;

	return (ISC_R_SUCCESS);

 cleanup_algorithm:
	if (algname_is_allocated(tkey->algorithm)) {
		if (dns_name_dynamic(tkey->algorithm))
			dns_name_free(tkey->algorithm, mctx);
		isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t));
	}
 cleanup_name:
	dns_name_free(&tkey->name, mctx);
 cleanup_key:
	isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));

	return (ret);
}
示例#14
0
文件: db.c 项目: pecharmin/bind9
/*
 * Driver-specific implementation of dns_db_create().
 *
 * @param[in] argv      Database-specific parameters from dns_db_create().
 * @param[in] driverarg Driver-specific parameter from dns_db_register().
 */
isc_result_t
create_db(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
	  dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
	  void *driverarg, dns_db_t **dbp)
{
	sampledb_t *sampledb = NULL;
	isc_result_t result;
	dns_dbversion_t *version = NULL;
	struct in_addr a_addr;

	REQUIRE(type == dns_dbtype_zone);
	REQUIRE(rdclass == dns_rdataclass_in);
	REQUIRE(argc == 0);
	REQUIRE(argv != NULL);
	REQUIRE(driverarg != NULL); /* pointer to driver instance */
	REQUIRE(dbp != NULL && *dbp == NULL);

	UNUSED(driverarg); /* no driver-specific configuration */

	a_addr.s_addr = 0x0100007fU;

	CHECKED_MEM_GET_PTR(mctx, sampledb);
	ZERO_PTR(sampledb);

	isc_mem_attach(mctx, &sampledb->common.mctx);
	dns_name_init(&sampledb->common.origin, NULL);
	isc_ondestroy_init(&sampledb->common.ondest);

	sampledb->common.magic = DNS_DB_MAGIC;
	sampledb->common.impmagic = SAMPLEDB_MAGIC;

	sampledb->common.methods = &sampledb_methods;
	sampledb->common.attributes = 0;
	sampledb->common.rdclass = rdclass;

	CHECK(dns_name_dupwithoffsets(origin, mctx, &sampledb->common.origin));

	CHECK(isc_refcount_init(&sampledb->refs, 1));

	/* Translate instance name to instance pointer. */
	sampledb->inst = driverarg;

	/* Create internal instance of RBT DB implementation from BIND. */
	CHECK(dns_db_create(mctx, "rbt", origin, dns_dbtype_zone,
			    dns_rdataclass_in, 0, NULL, &sampledb->rbtdb));

	/* Create fake SOA, NS, and A records to make database loadable. */
	CHECK(dns_db_newversion(sampledb->rbtdb, &version));
	CHECK(add_soa(sampledb->rbtdb, version, origin, origin, origin));
	CHECK(add_ns(sampledb->rbtdb, version, origin, origin));
	CHECK(add_a(sampledb->rbtdb, version, origin, a_addr));
	dns_db_closeversion(sampledb->rbtdb, &version, ISC_TRUE);

	*dbp = (dns_db_t *)sampledb;

	return (ISC_R_SUCCESS);

cleanup:
	if (sampledb != NULL) {
		if (dns_name_dynamic(&sampledb->common.origin))
			dns_name_free(&sampledb->common.origin, mctx);

		isc_mem_putanddetach(&sampledb->common.mctx, sampledb,
				     sizeof(*sampledb));
	}

	return (result);
}
示例#15
0
/**
 * Convert LDAP DN to absolute DNS names.
 *
 * @param[in]  dn     LDAP DN with one or two idnsName components at the
 *                    beginning.
 * @param[out] target Absolute DNS name derived from the first two idnsNames.
 * @param[out] origin Absolute DNS name derived from the last idnsName
 *                    component of DN, i.e. zone. Can be NULL.
 * @param[out] iszone ISC_TRUE if DN points to zone object, ISC_FALSE otherwise.
 *
 * @code
 * Examples:
 * dn = "idnsName=foo.bar, idnsName=example.org., cn=dns, dc=example, dc=org"
 * target = "foo.bar.example.org."
 * origin = "example.org."
 *
 * dn = "idnsname=89, idnsname=4.34.10.in-addr.arpa, cn=dns, dc=example, dc=org"
 * target = "89.4.34.10.in-addr.arpa."
 * origin = "4.34.10.in-addr.arpa."
 *
 * dn = "idnsname=third.test., idnsname=test., cn=dns, dc=example, dc=org"
 * target = "third.test."
 * origin = "test."
 * @endcode
 */
isc_result_t
dn_to_dnsname(isc_mem_t *mctx, const char *dn_str, dns_name_t *target,
	      dns_name_t *otarget, isc_boolean_t *iszone)
{
	LDAPDN dn = NULL;
	LDAPRDN rdn = NULL;
	LDAPAVA *attr = NULL;
	int idx;
	int ret;

	DECLARE_BUFFERED_NAME(name);
	DECLARE_BUFFERED_NAME(origin);
	isc_buffer_t name_buf;
	isc_buffer_t origin_buf;
	isc_result_t result;

	REQUIRE(dn_str != NULL);
	REQUIRE(target != NULL);

	INIT_BUFFERED_NAME(name);
	INIT_BUFFERED_NAME(origin);
	isc_buffer_initnull(&name_buf);
	isc_buffer_initnull(&origin_buf);

	/* Example DN: cn=a+sn=b, ou=people */

	ret = ldap_str2dn(dn_str, &dn, LDAP_DN_FORMAT_LDAPV3);
	if (ret != LDAP_SUCCESS || dn == NULL) {
		log_bug("ldap_str2dn failed: %u", ret);
		CLEANUP_WITH(ISC_R_UNEXPECTED);
	}

	/* iterate over DN components: e.g. cn=a+sn=b */
	for (idx = 0; dn[idx] != NULL; idx++) {
		rdn = dn[idx];

		/* "iterate" over RDN components: e.g. cn=a */
		INSIST(rdn[0] != NULL); /* RDN without (attr=value)?! */
		if (rdn[1] != NULL) {
			log_bug("multi-valued RDNs are not supported");
			CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
		}

		/* attribute in current RDN component */
		attr = rdn[0];
		if ((attr->la_flags & LDAP_AVA_STRING) == 0) {
			log_error("non-string attribute detected: position %u",
				  idx);
			CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
		}

		if (strncasecmp("idnsName", attr->la_attr.bv_val,
				attr->la_attr.bv_len) == 0) {
			if (idx == 0) {
				isc_buffer_init(&name_buf,
						attr->la_value.bv_val,
						attr->la_value.bv_len);
				isc_buffer_add(&name_buf,
					       attr->la_value.bv_len);
			} else if (idx == 1) {
				isc_buffer_init(&origin_buf,
						attr->la_value.bv_val,
						attr->la_value.bv_len);
				isc_buffer_add(&origin_buf,
					       attr->la_value.bv_len);
			} else { /* more than two idnsNames?! */
				break;
			}
		} else { /* no match - idx holds position */
			break;
		}
	}

	/* filter out unsupported cases */
	if (idx <= 0) {
		log_error("no idnsName component found in DN");
		CLEANUP_WITH(ISC_R_UNEXPECTEDEND);
	} else if (idx == 1) { /* zone only */
		if (iszone != NULL)
			*iszone = ISC_TRUE;
		CHECK(dns_name_copy(dns_rootname, &origin, NULL));
		CHECK(dns_name_fromtext(&name, &name_buf, dns_rootname, 0, NULL));
	} else if (idx == 2) { /* owner and zone */
		if (iszone != NULL)
			*iszone = ISC_FALSE;
		CHECK(dns_name_fromtext(&origin, &origin_buf, dns_rootname, 0,
					NULL));
		CHECK(dns_name_fromtext(&name, &name_buf, &origin, 0, NULL));
		if (dns_name_issubdomain(&name, &origin) == ISC_FALSE) {
			log_error("out-of-zone data: first idnsName is not a "
				  "subdomain of the other");
			CLEANUP_WITH(DNS_R_BADOWNERNAME);
		} else if (dns_name_equal(&name, &origin) == ISC_TRUE) {
			log_error("attempt to redefine zone apex: first "
				  "idnsName equals to zone name");
			CLEANUP_WITH(DNS_R_BADOWNERNAME);
		}
	} else {
		log_error("unsupported number of idnsName components in DN: "
			  "%u components found", idx);
		CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
	}

cleanup:
	if (result == ISC_R_SUCCESS)
		result = dns_name_dupwithoffsets(&name, mctx, target);
	else
		log_error_r("failed to convert DN '%s' to DNS name", dn_str);

	if (result == ISC_R_SUCCESS && otarget != NULL)
		result = dns_name_dupwithoffsets(&origin, mctx, otarget);

	if (result != ISC_R_SUCCESS) {
		if (dns_name_dynamic(target))
			dns_name_free(target, mctx);
		if (otarget) {
			if (dns_name_dynamic(otarget))
				dns_name_free(otarget, mctx);
		}
	}

	if (dn != NULL)
		ldap_dnfree(dn);

	return result;
}
示例#16
0
isc_result_t
ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
			  isc_mem_t *mctx, isc_sockaddr_t **addrsp,
			  isc_dscp_t **dscpsp, dns_name_t ***keysp,
			  isc_uint32_t *countp)
{
	isc_uint32_t addrcount = 0, dscpcount = 0, keycount = 0, i = 0;
	isc_uint32_t listcount = 0, l = 0, j;
	isc_uint32_t stackcount = 0, pushed = 0;
	isc_result_t result;
	const cfg_listelt_t *element;
	const cfg_obj_t *addrlist;
	const cfg_obj_t *portobj;
	const cfg_obj_t *dscpobj;
	in_port_t port;
	isc_dscp_t dscp = -1;
	dns_fixedname_t fname;
	isc_sockaddr_t *addrs = NULL;
	isc_dscp_t *dscps = NULL;
	dns_name_t **keys = NULL;
	struct { const char *name; } *lists = NULL;
	struct {
		const cfg_listelt_t *element;
		in_port_t port;
		isc_dscp_t dscp;
	} *stack = NULL;

	REQUIRE(addrsp != NULL && *addrsp == NULL);
	REQUIRE(dscpsp != NULL && *dscpsp == NULL);
	REQUIRE(keysp != NULL && *keysp == NULL);
	REQUIRE(countp != NULL);

	/*
	 * Get system defaults.
	 */
	result = ns_config_getport(config, &port);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	result = ns_config_getdscp(config, &dscp);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

 newlist:
	addrlist = cfg_tuple_get(list, "addresses");
	portobj = cfg_tuple_get(list, "port");
	dscpobj = cfg_tuple_get(list, "dscp");

	if (cfg_obj_isuint32(portobj)) {
		isc_uint32_t val = cfg_obj_asuint32(portobj);
		if (val > ISC_UINT16_MAX) {
			cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
				    "port '%u' out of range", val);
			result = ISC_R_RANGE;
			goto cleanup;
		}
		port = (in_port_t) val;
	}

	if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) {
		if (cfg_obj_asuint32(dscpobj) > 63) {
			cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
				    "dscp value '%u' is out of range",
				    cfg_obj_asuint32(dscpobj));
			result = ISC_R_RANGE;
			goto cleanup;
		}
		dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
	}

	result = ISC_R_NOMEMORY;

	element = cfg_list_first(addrlist);
 resume:
	for ( ;
	     element != NULL;
	     element = cfg_list_next(element))
	{
		const cfg_obj_t *addr;
		const cfg_obj_t *key;
		const char *keystr;
		isc_buffer_t b;

		addr = cfg_tuple_get(cfg_listelt_value(element),
				     "masterselement");
		key = cfg_tuple_get(cfg_listelt_value(element), "key");

		if (!cfg_obj_issockaddr(addr)) {
			const char *listname = cfg_obj_asstring(addr);
			isc_result_t tresult;

			/* Grow lists? */
			if (listcount == l) {
				void * tmp;
				isc_uint32_t newlen = listcount + 16;
				size_t newsize, oldsize;

				newsize = newlen * sizeof(*lists);
				oldsize = listcount * sizeof(*lists);
				tmp = isc_mem_get(mctx, newsize);
				if (tmp == NULL)
					goto cleanup;
				if (listcount != 0) {
					memmove(tmp, lists, oldsize);
					isc_mem_put(mctx, lists, oldsize);
				}
				lists = tmp;
				listcount = newlen;
			}
			/* Seen? */
			for (j = 0; j < l; j++)
				if (strcasecmp(lists[j].name, listname) == 0)
					break;
			if (j < l)
				continue;
			tresult = get_masters_def(config, listname, &list);
			if (tresult == ISC_R_NOTFOUND) {
				cfg_obj_log(addr, ns_g_lctx, ISC_LOG_ERROR,
				    "masters \"%s\" not found", listname);

				result = tresult;
				goto cleanup;
			}
			if (tresult != ISC_R_SUCCESS)
				goto cleanup;
			lists[l++].name = listname;
			/* Grow stack? */
			if (stackcount == pushed) {
				void * tmp;
				isc_uint32_t newlen = stackcount + 16;
				size_t newsize, oldsize;

				newsize = newlen * sizeof(*stack);
				oldsize = stackcount * sizeof(*stack);
				tmp = isc_mem_get(mctx, newsize);
				if (tmp == NULL)
					goto cleanup;
				if (stackcount != 0) {
					memmove(tmp, stack, oldsize);
					isc_mem_put(mctx, stack, oldsize);
				}
				stack = tmp;
				stackcount = newlen;
			}
			/*
			 * We want to resume processing this list on the
			 * next element.
			 */
			stack[pushed].element = cfg_list_next(element);
			stack[pushed].port = port;
			stack[pushed].dscp = dscp;
			pushed++;
			goto newlist;
		}

		if (i == addrcount) {
			void * tmp;
			isc_uint32_t newlen = addrcount + 16;
			size_t newsize, oldsize;

			newsize = newlen * sizeof(isc_sockaddr_t);
			oldsize = addrcount * sizeof(isc_sockaddr_t);
			tmp = isc_mem_get(mctx, newsize);
			if (tmp == NULL)
				goto cleanup;
			if (addrcount != 0) {
				memmove(tmp, addrs, oldsize);
				isc_mem_put(mctx, addrs, oldsize);
			}
			addrs = tmp;
			addrcount = newlen;

			newsize = newlen * sizeof(isc_dscp_t);
			oldsize = dscpcount * sizeof(isc_dscp_t);
			tmp = isc_mem_get(mctx, newsize);
			if (tmp == NULL)
				goto cleanup;
			if (dscpcount != 0) {
				memmove(tmp, dscps, oldsize);
				isc_mem_put(mctx, dscps, oldsize);
			}
			dscps = tmp;
			dscpcount = newlen;

			newsize = newlen * sizeof(dns_name_t *);
			oldsize = keycount * sizeof(dns_name_t *);
			tmp = isc_mem_get(mctx, newsize);
			if (tmp == NULL)
				goto cleanup;
			if (keycount != 0) {
				memmove(tmp, keys, oldsize);
				isc_mem_put(mctx, keys, oldsize);
			}
			keys = tmp;
			keycount = newlen;
		}

		addrs[i] = *cfg_obj_assockaddr(addr);
		if (isc_sockaddr_getport(&addrs[i]) == 0)
			isc_sockaddr_setport(&addrs[i], port);
		dscps[i] = cfg_obj_getdscp(addr);
		if (dscps[i] == -1)
			dscps[i] = dscp;
		keys[i] = NULL;
		i++;	/* Increment here so that cleanup on error works. */
		if (!cfg_obj_isstring(key))
			continue;
		keys[i - 1] = isc_mem_get(mctx, sizeof(dns_name_t));
		if (keys[i - 1] == NULL)
			goto cleanup;
		dns_name_init(keys[i - 1], NULL);

		keystr = cfg_obj_asstring(key);
		isc_buffer_constinit(&b, keystr, strlen(keystr));
		isc_buffer_add(&b, strlen(keystr));
		dns_fixedname_init(&fname);
		result = dns_name_fromtext(dns_fixedname_name(&fname), &b,
					   dns_rootname, 0, NULL);
		if (result != ISC_R_SUCCESS)
			goto cleanup;
		result = dns_name_dup(dns_fixedname_name(&fname), mctx,
				      keys[i - 1]);
		if (result != ISC_R_SUCCESS)
			goto cleanup;
	}
	if (pushed != 0) {
		pushed--;
		element = stack[pushed].element;
		port = stack[pushed].port;
		dscp = stack[pushed].dscp;
		goto resume;
	}
	if (i < addrcount) {
		void * tmp;
		size_t newsize, oldsize;

		newsize = i * sizeof(isc_sockaddr_t);
		oldsize = addrcount * sizeof(isc_sockaddr_t);
		if (i != 0) {
			tmp = isc_mem_get(mctx, newsize);
			if (tmp == NULL)
				goto cleanup;
			memmove(tmp, addrs, newsize);
		} else
			tmp = NULL;
		isc_mem_put(mctx, addrs, oldsize);
		addrs = tmp;
		addrcount = i;

		newsize = i * sizeof(isc_dscp_t);
		oldsize = dscpcount * sizeof(isc_dscp_t);
		if (i != 0) {
			tmp = isc_mem_get(mctx, newsize);
			if (tmp == NULL)
				goto cleanup;
			memmove(tmp, dscps, newsize);
		} else
			tmp = NULL;
		isc_mem_put(mctx, dscps, oldsize);
		dscps = tmp;
		dscpcount = i;

		newsize = i * sizeof(dns_name_t *);
		oldsize = keycount * sizeof(dns_name_t *);
		if (i != 0) {
			tmp = isc_mem_get(mctx, newsize);
			if (tmp == NULL)
				goto cleanup;
			memmove(tmp, keys,  newsize);
		} else
			tmp = NULL;
		isc_mem_put(mctx, keys, oldsize);
		keys = tmp;
		keycount = i;
	}

	if (lists != NULL)
		isc_mem_put(mctx, lists, listcount * sizeof(*lists));
	if (stack != NULL)
		isc_mem_put(mctx, stack, stackcount * sizeof(*stack));

	INSIST(keycount == addrcount);

	*addrsp = addrs;
	*dscpsp = dscps;
	*keysp = keys;
	*countp = addrcount;

	return (ISC_R_SUCCESS);

 cleanup:
	if (addrs != NULL)
		isc_mem_put(mctx, addrs, addrcount * sizeof(isc_sockaddr_t));
	if (dscps != NULL)
		isc_mem_put(mctx, dscps, dscpcount * sizeof(isc_dscp_t));
	if (keys != NULL) {
		for (j = 0; j < i; j++) {
			if (keys[j] == NULL)
				continue;
			if (dns_name_dynamic(keys[j]))
				dns_name_free(keys[j], mctx);
			isc_mem_put(mctx, keys[j], sizeof(dns_name_t));
		}
		isc_mem_put(mctx, keys, keycount * sizeof(dns_name_t *));
	}
	if (lists != NULL)
		isc_mem_put(mctx, lists, listcount * sizeof(*lists));
	if (stack != NULL)
		isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
	return (result);
}