Beispiel #1
0
/*%
 * Allocates a key structure and fills in some of the fields.
 */
static dst_key_t *
get_key_struct(dns_name_t *name, unsigned int alg,
	       unsigned int flags, unsigned int protocol,
	       unsigned int bits, dns_rdataclass_t rdclass,
	       dns_ttl_t ttl, isc_mem_t *mctx)
{
	dst_key_t *key;
	isc_result_t result;
	int i;

	key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t));
	if (key == NULL)
		return (NULL);

	memset(key, 0, sizeof(dst_key_t));

	key->key_name = isc_mem_get(mctx, sizeof(dns_name_t));
	if (key->key_name == NULL) {
		isc_mem_put(mctx, key, sizeof(dst_key_t));
		return (NULL);
	}

	dns_name_init(key->key_name, NULL);
	result = dns_name_dup(name, mctx, key->key_name);
	if (result != ISC_R_SUCCESS) {
		isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
		isc_mem_put(mctx, key, sizeof(dst_key_t));
		return (NULL);
	}

	result = isc_refcount_init(&key->refs, 1);
	if (result != ISC_R_SUCCESS) {
		dns_name_free(key->key_name, mctx);
		isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
		isc_mem_put(mctx, key, sizeof(dst_key_t));
		return (NULL);
	}
	isc_mem_attach(mctx, &key->mctx);
	key->key_alg = alg;
	key->key_flags = flags;
	key->key_proto = protocol;
	key->keydata.generic = NULL;
	key->key_size = bits;
	key->key_class = rdclass;
	key->key_ttl = ttl;
	key->func = dst_t_func[alg];
	key->fmt_major = 0;
	key->fmt_minor = 0;
	for (i = 0; i < (DST_MAX_TIMES + 1); i++) {
		key->times[i] = 0;
		key->timeset[i] = ISC_FALSE;
	}
	key->inactive = ISC_FALSE;
	key->magic = KEY_MAGIC;
	return (key);
}
Beispiel #2
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);
}
static isc_result_t
stub_dlz_create(const char *dlzname, unsigned int argc, char *argv[],
		void *driverarg, void **dbdata)
{

	config_data_t *cd;

	UNUSED(driverarg);

	if (argc < 4)
		return (ISC_R_FAILURE);
	/*
	 * Write info message to log
	 */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
		      "Loading '%s' using DLZ_stub driver. "
		      "Zone: %s, Name: %s IP: %s",
		      dlzname, argv[1], argv[2], argv[3]);

	cd = isc_mem_get(ns_g_mctx, sizeof(config_data_t));
	if ((cd) == NULL) {
		return (ISC_R_NOMEMORY);
	}

	memset(cd, 0, sizeof(config_data_t));

	cd->myzone = isc_mem_strdup(ns_g_mctx, argv[1]);
	if (cd->myzone == NULL) {
		isc_mem_put(ns_g_mctx, cd, sizeof(config_data_t));
		return (ISC_R_NOMEMORY);
	}

	cd->myname = isc_mem_strdup(ns_g_mctx, argv[2]);
	if (cd->myname == NULL) {
		isc_mem_put(ns_g_mctx, cd, sizeof(config_data_t));
		isc_mem_free(ns_g_mctx, cd->myzone);
		return (ISC_R_NOMEMORY);
	}

	cd->myip = isc_mem_strdup(ns_g_mctx, argv[3]);
	if (cd->myip == NULL) {
		isc_mem_put(ns_g_mctx, cd, sizeof(config_data_t));
		isc_mem_free(ns_g_mctx, cd->myname);
		isc_mem_free(ns_g_mctx, cd->myzone);
		return (ISC_R_NOMEMORY);
	}

	isc_mem_attach(ns_g_mctx, &cd->mctx);

	*dbdata = cd;

	return(ISC_R_SUCCESS);
}
Beispiel #4
0
static isc_result_t
set_state(unsigned int family, isc_uint32_t ipnum, const geoipv6_t *ipnum6,
	  isc_uint8_t scope, dns_geoip_subtype_t subtype, GeoIPRecord *record,
	  GeoIPRegion *region, char *name, const char *text, int id)
{
	geoip_state_t *state = NULL;
#ifdef ISC_PLATFORM_USETHREADS
	isc_result_t result;

	result = state_key_init();
	if (result != ISC_R_SUCCESS)
		return (result);

	state = (geoip_state_t *) isc_thread_key_getspecific(state_key);
	if (state == NULL) {
		state = (geoip_state_t *) isc_mem_get(state_mctx,
						      sizeof(geoip_state_t));
		if (state == NULL)
			return (ISC_R_NOMEMORY);
		memset(state, 0, sizeof(*state));

		result = isc_thread_key_setspecific(state_key, state);
		if (result != ISC_R_SUCCESS) {
			isc_mem_put(state_mctx, state, sizeof(geoip_state_t));
			return (result);
		}

		isc_mem_attach(state_mctx, &state->mctx);
	} else
		clean_state(state);
#else
	state = &saved_state;
	clean_state(state);
#endif

	if (family == AF_INET)
		state->ipnum = ipnum;
	else
		state->ipnum6 = *ipnum6;

	state->family = family;
	state->subtype = subtype;
	state->scope = scope;
	state->record = record;
	state->region = region;
	state->name = name;
	state->text = text;
	state->id = id;

	return (ISC_R_SUCCESS);
}
Beispiel #5
0
isc_result_t
dns_difftuple_create(isc_mem_t *mctx,
		     dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
		     dns_rdata_t *rdata, dns_difftuple_t **tp)
{
	dns_difftuple_t *t;
	unsigned int size;
	unsigned char *datap;

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

	/*
	 * Create a new tuple.  The variable-size wire-format name data and
	 * rdata immediately follow the dns_difftuple_t structure
	 * in memory.
	 */
	size = sizeof(*t) + name->length + rdata->length;
	t = isc_mem_allocate(mctx, size);
	if (t == NULL)
		return (ISC_R_NOMEMORY);
	t->mctx = NULL;
	isc_mem_attach(mctx, &t->mctx);
	t->op = op;

	datap = (unsigned char *)(t + 1);

	memmove(datap, name->ndata, name->length);
	dns_name_init(&t->name, NULL);
	dns_name_clone(name, &t->name);
	t->name.ndata = datap;
	datap += name->length;

	t->ttl = ttl;

	memmove(datap, rdata->data, rdata->length);
	dns_rdata_init(&t->rdata);
	dns_rdata_clone(rdata, &t->rdata);
	t->rdata.data = datap;
	datap += rdata->length;

	ISC_LINK_INIT(&t->rdata, link);
	ISC_LINK_INIT(t, link);
	t->magic = DNS_DIFFTUPLE_MAGIC;

	INSIST(datap == (unsigned char *)t + size);

	*tp = t;
	return (ISC_R_SUCCESS);
}
Beispiel #6
0
isc_result_t
dns_dbtable_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
		   dns_dbtable_t **dbtablep)
{
	dns_dbtable_t *dbtable;
	isc_result_t result;

	REQUIRE(mctx != NULL);
	REQUIRE(dbtablep != NULL && *dbtablep == NULL);

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

	dbtable->rbt = NULL;
	result = dns_rbt_create(mctx, dbdetach, NULL, &dbtable->rbt);
	if (result != ISC_R_SUCCESS)
		goto clean1;

	result = isc_mutex_init(&dbtable->lock);
	if (result != ISC_R_SUCCESS)
		goto clean2;

	result = isc_rwlock_init(&dbtable->tree_lock, 0, 0);
	if (result != ISC_R_SUCCESS)
		goto clean3;

	dbtable->default_db = NULL;
	dbtable->mctx = NULL;
	isc_mem_attach(mctx, &dbtable->mctx);
	dbtable->rdclass = rdclass;
	dbtable->magic = DBTABLE_MAGIC;
	dbtable->references = 1;

	*dbtablep = dbtable;

	return (ISC_R_SUCCESS);

 clean3:
	DESTROYLOCK(&dbtable->lock);

 clean2:
	dns_rbt_destroy(&dbtable->rbt);

 clean1:
	isc_mem_putanddetach(&mctx, dbtable, sizeof(*dbtable));

	return (result);
}
isc_result_t
dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
	dns_keytable_t *keytable;
	isc_result_t result;

	/*
	 * Create a keytable.
	 */

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

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

	keytable->table = NULL;
	result = dns_rbt_create(mctx, free_keynode, mctx, &keytable->table);
	if (result != ISC_R_SUCCESS)
		goto cleanup_keytable;

	result = isc_mutex_init(&keytable->lock);
	if (result != ISC_R_SUCCESS)
		goto cleanup_rbt;

	result = isc_rwlock_init(&keytable->rwlock, 0, 0);
	if (result != ISC_R_SUCCESS)
		goto cleanup_lock;

	keytable->mctx = NULL;
	isc_mem_attach(mctx, &keytable->mctx);
	keytable->active_nodes = 0;
	keytable->references = 1;
	keytable->magic = KEYTABLE_MAGIC;
	*keytablep = keytable;

	return (ISC_R_SUCCESS);

   cleanup_lock:
	DESTROYLOCK(&keytable->lock);

   cleanup_rbt:
	dns_rbt_destroy(&keytable->table);

   cleanup_keytable:
	isc_mem_putanddetach(&mctx, keytable, sizeof(*keytable));

	return (result);
}
Beispiel #8
0
void
dst__pkcs11_init(isc_mem_t *mctx, const char *engine) {
	CK_RV rv;

	RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);

	LOCK(&alloclock);
	if ((mctx != NULL) && (pk11_mctx == NULL) && (allocsize == 0))
		isc_mem_attach(mctx, &pk11_mctx);
	if (initialized) {
		UNLOCK(&alloclock);
		return;
	} else {
		LOCK(&sessionlock);
		initialized = ISC_TRUE;
		UNLOCK(&alloclock);
	}

	if (engine != NULL)
		lib_name = engine;

	/* Initialize the CRYPTOKI library */
	rv = pkcs_C_Initialize((CK_VOID_PTR) &pk11_init_args);

	if (rv != CKR_OK) {
		if (rv == 0xfe)
			FATAL_ERROR(__FILE__, __LINE__,
				    "Can't load or link module \"%s\"",
				    lib_name);
		else
			FATAL_ERROR(__FILE__, __LINE__,
				    "pkcs_C_Initialize: Error = 0x%.8lX", rv);
	}

	ISC_LIST_INIT(tokens);
	ISC_LIST_INIT(actives);

	choose_slots();
#ifdef PKCS11CRYPTO
	if (rand_token == NULL)
		FATAL_ERROR(__FILE__, __LINE__, "Can't find random service");
	if (digest_token == NULL)
		FATAL_ERROR(__FILE__, __LINE__, "Can't find digest service");
#endif /* PKCS11CRYPTO */
	UNLOCK(&sessionlock);
}
Beispiel #9
0
isc_result_t
dst_context_create4(dst_key_t *key, isc_mem_t *mctx,
		    isc_logcategory_t *category, isc_boolean_t useforsigning,
		    int maxbits, dst_context_t **dctxp)
{
	dst_context_t *dctx;
	isc_result_t result;

	REQUIRE(dst_initialized == ISC_TRUE);
	REQUIRE(VALID_KEY(key));
	REQUIRE(mctx != NULL);
	REQUIRE(dctxp != NULL && *dctxp == NULL);

	if (key->func->createctx == NULL &&
	    key->func->createctx2 == NULL)
		return (DST_R_UNSUPPORTEDALG);
	if (key->keydata.generic == NULL)
		return (DST_R_NULLKEY);

	dctx = isc_mem_get(mctx, sizeof(dst_context_t));
	if (dctx == NULL)
		return (ISC_R_NOMEMORY);
	memset(dctx, 0, sizeof(*dctx));
	dst_key_attach(key, &dctx->key);
	isc_mem_attach(mctx, &dctx->mctx);
	dctx->category = category;
	if (useforsigning)
		dctx->use = DO_SIGN;
	else
		dctx->use = DO_VERIFY;
	if (key->func->createctx2 != NULL)
		result = key->func->createctx2(key, maxbits, dctx);
	else
		result = key->func->createctx(key, dctx);
	if (result != ISC_R_SUCCESS) {
		if (dctx->key != NULL)
			dst_key_free(&dctx->key);
		isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(dst_context_t));
		return (result);
	}
	dctx->magic = CTX_MAGIC;
	*dctxp = dctx;
	return (ISC_R_SUCCESS);
}
Beispiel #10
0
isc_result_t
dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **ztp) {
	dns_zt_t *zt;
	isc_result_t result;

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

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

	zt->table = NULL;
	result = dns_rbt_create(mctx, auto_detach, zt, &zt->table);
	if (result != ISC_R_SUCCESS)
		goto cleanup_zt;

	result = isc_rwlock_init(&zt->rwlock, 0, 0);
	if (result != ISC_R_SUCCESS)
		goto cleanup_rbt;

	zt->mctx = NULL;
	isc_mem_attach(mctx, &zt->mctx);
	zt->references = 1;
	zt->flush = ISC_FALSE;
	zt->rdclass = rdclass;
	zt->magic = ZTMAGIC;
	zt->loaddone = NULL;
	zt->loaddone_arg = NULL;
	zt->loads_pending = 0;
	*ztp = zt;

	return (ISC_R_SUCCESS);

   cleanup_rbt:
	dns_rbt_destroy(&zt->table);

   cleanup_zt:
	isc_mem_put(mctx, zt, sizeof(*zt));

	return (result);
}
Beispiel #11
0
isc_result_t
dns_badcache_init(isc_mem_t *mctx, unsigned int size, dns_badcache_t **bcp) {
	isc_result_t result;
	dns_badcache_t *bc = NULL;

	REQUIRE(bcp != NULL && *bcp == NULL);
	REQUIRE(mctx != NULL);

	bc = isc_mem_get(mctx, sizeof(dns_badcache_t));
	if (bc == NULL)
		return (ISC_R_NOMEMORY);
	memset(bc, 0, sizeof(dns_badcache_t));

	isc_mem_attach(mctx, &bc->mctx);
	result = isc_mutex_init(&bc->lock);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	bc->table = isc_mem_get(bc->mctx, sizeof(*bc->table) * size);
	if (bc->table == NULL) {
		result = ISC_R_NOMEMORY;
		goto destroy_lock;
	}

	bc->size = bc->minsize = size;
	memset(bc->table, 0, bc->size * sizeof(dns_bcentry_t *));

	bc->count = 0;
	bc->sweep = 0;
	bc->magic = BADCACHE_MAGIC;

	*bcp = bc;
	return (ISC_R_SUCCESS);

 destroy_lock:
	DESTROYLOCK(&bc->lock);
 cleanup:
	isc_mem_putanddetach(&bc->mctx, bc, sizeof(dns_badcache_t));
	return (result);
}
Beispiel #12
0
isc_result_t
dns_fwdtable_create(isc_mem_t *mctx, dns_fwdtable_t **fwdtablep) {
	dns_fwdtable_t *fwdtable;
	isc_result_t result;

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

	fwdtable = isc_mem_get(mctx, sizeof(dns_fwdtable_t));
	if (fwdtable == NULL)
		return (ISC_R_NOMEMORY);

	fwdtable->table = NULL;
	result = dns_rbt_create(mctx, auto_detach, fwdtable, &fwdtable->table);
	if (result != ISC_R_SUCCESS)
		goto cleanup_fwdtable;

	result = isc_rwlock_init(&fwdtable->rwlock, 0, 0);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_rwlock_init() failed: %s",
				 isc_result_totext(result));
		result = ISC_R_UNEXPECTED;
		goto cleanup_rbt;
	}

	fwdtable->mctx = NULL;
	isc_mem_attach(mctx, &fwdtable->mctx);
	fwdtable->magic = FWDTABLEMAGIC;
	*fwdtablep = fwdtable;

	return (ISC_R_SUCCESS);

   cleanup_rbt:
	dns_rbt_destroy(&fwdtable->table);

   cleanup_fwdtable:
	isc_mem_put(mctx, fwdtable, sizeof(dns_fwdtable_t));

	return (result);
}
Beispiel #13
0
isc_result_t
isc_symtab_create(isc_mem_t *mctx, unsigned int size,
		  isc_symtabaction_t undefine_action,
		  void *undefine_arg,
		  isc_boolean_t case_sensitive,
		  isc_symtab_t **symtabp)
{
	isc_symtab_t *symtab;
	unsigned int i;

	REQUIRE(mctx != NULL);
	REQUIRE(symtabp != NULL && *symtabp == NULL);
	REQUIRE(size > 0);	/* Should be prime. */

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

	symtab->mctx = NULL;
	isc_mem_attach(mctx, &symtab->mctx);
	symtab->table = (eltlist_t *)isc_mem_get(mctx,
						 size * sizeof(eltlist_t));
	if (symtab->table == NULL) {
		isc_mem_putanddetach(&symtab->mctx, symtab, sizeof(*symtab));
		return (ISC_R_NOMEMORY);
	}
	for (i = 0; i < size; i++)
		INIT_LIST(symtab->table[i]);
	symtab->size = size;
	symtab->count = 0;
	symtab->maxload = size * 3 / 4;
	symtab->undefine_action = undefine_action;
	symtab->undefine_arg = undefine_arg;
	symtab->case_sensitive = case_sensitive;
	symtab->magic = SYMTAB_MAGIC;

	*symtabp = symtab;

	return (ISC_R_SUCCESS);
}
Beispiel #14
0
isc_result_t
mldap_new(isc_mem_t *mctx, mldapdb_t **mldapp) {
	isc_result_t result;
	mldapdb_t *mldap = NULL;

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

	CHECKED_MEM_GET_PTR(mctx, mldap);
	ZERO_PTR(mldap);
	isc_mem_attach(mctx, &mldap->mctx);

	CHECK(isc_refcount_init(&mldap->generation, 0));
	CHECK(metadb_new(mctx, &mldap->mdb));

	*mldapp = mldap;
	return result;

cleanup:
	metadb_destroy(&mldap->mdb);
	MEM_PUT_AND_DETACH(mldap);
	return result;
}
Beispiel #15
0
isc_result_t
dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
	isc_result_t result;
	dns_tsig_keyring_t *ring;

	REQUIRE(mctx != NULL);
	REQUIRE(ringp != NULL);
	REQUIRE(*ringp == NULL);

	ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
	if (ring == NULL)
		return (ISC_R_NOMEMORY);

	result = isc_rwlock_init(&ring->lock, 0, 0);
	if (result != ISC_R_SUCCESS) {
		isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
		return (result);
	}

	ring->keys = NULL;
	result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys);
	if (result != ISC_R_SUCCESS) {
		isc_rwlock_destroy(&ring->lock);
		isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
		return (result);
	}

	ring->writecount = 0;
	ring->mctx = NULL;
	ring->generated = 0;
	ring->maxgenerated = DNS_TSIG_MAXGENERATEDKEYS;
	ISC_LIST_INIT(ring->lru);
	isc_mem_attach(mctx, &ring->mctx);
	ring->references = 1;

	*ringp = ring;
	return (ISC_R_SUCCESS);
}
Beispiel #16
0
isc_result_t
new_ldap_cache(isc_mem_t *mctx, ldap_cache_t **cachep,
	       const char * const *argv)
{
	isc_result_t result;
	ldap_cache_t *cache = NULL;
	unsigned int cache_ttl;
	setting_t cache_settings[] = {
		{ "cache_ttl", default_uint(120) },
		end_of_settings
	};

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

	cache_settings[0].target = &cache_ttl;
	CHECK(set_settings(cache_settings, argv));

	CHECKED_MEM_GET_PTR(mctx, cache);
	ZERO_PTR(cache);
	isc_mem_attach(mctx, &cache->mctx);

	isc_interval_set(&cache->cache_ttl, cache_ttl, 0);

	if (cache_ttl) {
		CHECK(dns_rbt_create(mctx, cache_node_deleter, NULL,
				     &cache->rbt));
		CHECK(isc_mutex_init(&cache->mutex));
	}

	*cachep = cache;
	return ISC_R_SUCCESS;

cleanup:
	if (cache != NULL)
		destroy_ldap_cache(&cache);

	return result;
}
isc_result_t
dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp)
{
	dns_tkeyctx_t *tctx;

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

	tctx = isc_mem_get(mctx, sizeof(dns_tkeyctx_t));
	if (tctx == NULL)
		return (ISC_R_NOMEMORY);
	tctx->mctx = NULL;
	isc_mem_attach(mctx, &tctx->mctx);
	tctx->ectx = NULL;
	isc_entropy_attach(ectx, &tctx->ectx);
	tctx->dhkey = NULL;
	tctx->domain = NULL;
	tctx->gsscred = NULL;

	*tctxp = tctx;
	return (ISC_R_SUCCESS);
}
Beispiel #18
0
static isc_result_t
alloc_pool(isc_mem_t *mctx, unsigned int count, isc_pool_t **poolp) {
	isc_pool_t *pool;

	pool = isc_mem_get(mctx, sizeof(*pool));
	if (pool == NULL)
		return (ISC_R_NOMEMORY);
	pool->count = count;
	pool->free = NULL;
	pool->init = NULL;
	pool->initarg = NULL;
	pool->mctx = NULL;
	isc_mem_attach(mctx, &pool->mctx);
	pool->pool = isc_mem_get(mctx, count * sizeof(void *));
	if (pool->pool == NULL) {
		isc_mem_put(mctx, pool, sizeof(*pool));
		return (ISC_R_NOMEMORY);
	}
	memset(pool->pool, 0, count * sizeof(void *));

	*poolp = pool;
	return (ISC_R_SUCCESS);
}
Beispiel #19
0
/*%
 * Create methods
 */
static isc_result_t
create_stats(isc_mem_t *mctx, dns_statstype_t	type, int ncounters,
	     dns_stats_t **statsp)
{
	dns_stats_t *stats;
	isc_result_t result;

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

	stats->counters = NULL;
	stats->references = 1;

	result = isc_mutex_init(&stats->lock);
	if (result != ISC_R_SUCCESS)
		goto clean_stats;

	result = isc_stats_create(mctx, &stats->counters, ncounters);
	if (result != ISC_R_SUCCESS)
		goto clean_mutex;

	stats->magic = DNS_STATS_MAGIC;
	stats->type = type;
	stats->mctx = NULL;
	isc_mem_attach(mctx, &stats->mctx);
	*statsp = stats;

	return (ISC_R_SUCCESS);

  clean_mutex:
	DESTROYLOCK(&stats->lock);
  clean_stats:
	isc_mem_put(mctx, stats, sizeof(*stats));

	return (result);
}
Beispiel #20
0
/**
 * Allocate new set of settings, fill it with values from specified default set
 * and (optionally) link the new set of settings to its parent set.
 *
 * @param[in] default_settings   Array with pre-filled setting structures.
 * @param[in] default_set_length Default set length in bytes.
 * @param[in] set_name		 Human readable name for this set of settings.
 *
 * @pre target != NULL && *target == NULL
 * @pre default_settings != NULL
 * @pre default_set_length > 0, default_set_length <= sizeof(default_settings)
 *
 * @retval ISC_R_SUCCESS
 * @retval ISC_R_NOMEMORY
 *
 * @note How to create local_settings which overrides default_settings:
 * @code
 * const setting_t default_settings[] = {
 *	{ "connections",	default_uint(2)		},
 * }
 * const settings_set_t default_settings_set = {
 *	NULL,
 *	NULL,
 *	(setting_t *) &default_settings[0]
 * };
 * const setting_t local_settings[] = {
 *	{ "connections",	no_default_uint		},
 * }
 *
 * settings_set_t *local_settings = NULL;
 * result = settings_set_create(mctx, default_settings,
 * 				sizeof(default_settings), &default_settings_set,
 *				&local_settings);
 * @endcode
 */
isc_result_t
settings_set_create(isc_mem_t *mctx, const setting_t default_settings[],
		    const unsigned int default_set_length, const char *set_name,
		    const settings_set_t *const parent_set,
		    settings_set_t **target) {
	isc_result_t result = ISC_R_FAILURE;
	settings_set_t *new_set = NULL;

	REQUIRE(target != NULL && *target == NULL);
	REQUIRE(default_settings != NULL);
	REQUIRE(default_set_length > 0);

	CHECKED_MEM_ALLOCATE(mctx, new_set, default_set_length);
	ZERO_PTR(new_set);
	isc_mem_attach(mctx, &new_set->mctx);

	CHECKED_MEM_GET_PTR(mctx, new_set->lock);
	result = isc_mutex_init(new_set->lock);
	INSIST(result == ISC_R_SUCCESS);

	new_set->parent_set = parent_set;

	CHECKED_MEM_ALLOCATE(mctx, new_set->first_setting, default_set_length);
	memcpy(new_set->first_setting, default_settings, default_set_length);

	CHECKED_MEM_ALLOCATE(mctx, new_set->name, strlen(set_name) + 1);
	strcpy(new_set->name, set_name);

	*target = new_set;
	result = ISC_R_SUCCESS;

cleanup:
	if (result != ISC_R_SUCCESS)
		settings_set_free(&new_set);

	return result;
}
Beispiel #21
0
isc_result_t
dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg,
		isc_mem_t *mctx, dns_dbimplementation_t **dbimp)
{
	dns_dbimplementation_t *imp;

	REQUIRE(name != NULL);
	REQUIRE(dbimp != NULL && *dbimp == NULL);

	RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);

	RWLOCK(&implock, isc_rwlocktype_write);
	imp = impfind(name);
	if (imp != NULL) {
		RWUNLOCK(&implock, isc_rwlocktype_write);
		return (ISC_R_EXISTS);
	}

	imp = isc_mem_get(mctx, sizeof(dns_dbimplementation_t));
	if (imp == NULL) {
		RWUNLOCK(&implock, isc_rwlocktype_write);
		return (ISC_R_NOMEMORY);
	}
	imp->name = name;
	imp->create = create;
	imp->mctx = NULL;
	imp->driverarg = driverarg;
	isc_mem_attach(mctx, &imp->mctx);
	ISC_LINK_INIT(imp, link);
	ISC_LIST_APPEND(implementations, imp, link);
	RWUNLOCK(&implock, isc_rwlocktype_write);

	*dbimp = imp;

	return (ISC_R_SUCCESS);
}
Beispiel #22
0
isc_result_t
isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, isc_uint8_t bits) {
	isc_ht_t *ht = NULL;
	size_t i;

	REQUIRE(htp != NULL && *htp == NULL);
	REQUIRE(mctx != NULL);
	REQUIRE(bits >= 1 && bits <= (sizeof(size_t)*8 - 1));

	ht = isc_mem_get(mctx, sizeof(struct isc_ht));
	if (ht == NULL) {
		return (ISC_R_NOMEMORY);
	}

	ht->mctx = NULL;
	isc_mem_attach(mctx, &ht->mctx);

	ht->size = ((size_t)1<<bits);
	ht->mask = ((size_t)1<<bits)-1;
	ht->count = 0;

	ht->table = isc_mem_get(ht->mctx, ht->size * sizeof(isc_ht_node_t*));
	if (ht->table == NULL) {
		isc_mem_putanddetach(&ht->mctx, ht, sizeof(struct isc_ht));
		return (ISC_R_NOMEMORY);
	}

	for (i = 0; i < ht->size; i++) {
		ht->table[i] = NULL;
	}

	ht->magic = ISC_HT_MAGIC;

	*htp = ht;
	return (ISC_R_SUCCESS);
}
Beispiel #23
0
static isc_result_t
cache_node_create(ldap_cache_t *cache, ldapdb_rdatalist_t rdatalist,
		  cache_node_t **nodep)
{
	isc_result_t result;
	cache_node_t *node;

	REQUIRE(cache != NULL);
	REQUIRE(nodep != NULL && *nodep == NULL);

	CHECKED_MEM_GET_PTR(cache->mctx, node);
	ZERO_PTR(node);
	isc_mem_attach(cache->mctx, &node->mctx);
	node->rdatalist = rdatalist;
	CHECK(isc_time_nowplusinterval(&node->valid_until, &cache->cache_ttl));

	*nodep = node;
	return ISC_R_SUCCESS;

cleanup:
	SAFE_MEM_PUT_PTR(cache->mctx, node);

	return result;
}
Beispiel #24
0
static isc_result_t
listener_create(isc_mem_t *mctx, ns_lwresd_t *lwresd,
		ns_lwreslistener_t **listenerp)
{
	ns_lwreslistener_t *listener;
	isc_result_t result;

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

	listener = isc_mem_get(mctx, sizeof(ns_lwreslistener_t));
	if (listener == NULL)
		return (ISC_R_NOMEMORY);

	result = isc_mutex_init(&listener->lock);
	if (result != ISC_R_SUCCESS) {
		isc_mem_put(mctx, listener, sizeof(ns_lwreslistener_t));
		return (result);
	}

	listener->magic = LWRESLISTENER_MAGIC;
	listener->refs = 1;

	listener->sock = NULL;

	listener->manager = NULL;
	ns_lwdmanager_attach(lwresd, &listener->manager);

	listener->mctx = NULL;
	isc_mem_attach(mctx, &listener->mctx);

	ISC_LINK_INIT(listener, link);
	ISC_LIST_INIT(listener->cmgrs);

	*listenerp = listener;
	return (ISC_R_SUCCESS);
}
isc_result_t
dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **tablep) {
	isc_result_t result;
	dns_ssutable_t *table;

	REQUIRE(tablep != NULL && *tablep == NULL);
	REQUIRE(mctx != NULL);

	table = isc_mem_get(mctx, sizeof(dns_ssutable_t));
	if (table == NULL)
		return (ISC_R_NOMEMORY);
	result = isc_mutex_init(&table->lock);
	if (result != ISC_R_SUCCESS) {
		isc_mem_put(mctx, table, sizeof(dns_ssutable_t));
		return (result);
	}
	table->references = 1;
	table->mctx = NULL;
	isc_mem_attach(mctx, &table->mctx);
	ISC_LIST_INIT(table->rules);
	table->magic = SSUTABLEMAGIC;
	*tablep = table;
	return (ISC_R_SUCCESS);
}
Beispiel #26
0
isc_result_t
isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
		    isc_httpdclientok_t *client_ok,
		    isc_httpdondestroy_t *ondestroy, void *cb_arg,
		    isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdp)
{
	isc_result_t result;
	isc_httpdmgr_t *httpd;

	REQUIRE(mctx != NULL);
	REQUIRE(sock != NULL);
	REQUIRE(task != NULL);
	REQUIRE(tmgr != NULL);
	REQUIRE(httpdp != NULL && *httpdp == NULL);

	httpd = isc_mem_get(mctx, sizeof(isc_httpdmgr_t));
	if (httpd == NULL)
		return (ISC_R_NOMEMORY);

	result = isc_mutex_init(&httpd->lock);
	if (result != ISC_R_SUCCESS) {
		isc_mem_put(mctx, httpd, sizeof(isc_httpdmgr_t));
		return (result);
	}
	httpd->mctx = NULL;
	isc_mem_attach(mctx, &httpd->mctx);
	httpd->sock = NULL;
	isc_socket_attach(sock, &httpd->sock);
	httpd->task = NULL;
	isc_task_attach(task, &httpd->task);
	httpd->timermgr = tmgr; /* XXXMLG no attach function? */
	httpd->client_ok = client_ok;
	httpd->ondestroy = ondestroy;
	httpd->cb_arg = cb_arg;

	ISC_LIST_INIT(httpd->running);
	ISC_LIST_INIT(httpd->urls);

	/* XXXMLG ignore errors on isc_socket_listen() */
	result = isc_socket_listen(sock, SOMAXCONN);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_socket_listen() failed: %s",
				 isc_result_totext(result));
		goto cleanup;
	}

	(void)isc_socket_filter(sock, "httpready");

	result = isc_socket_accept(sock, task, isc_httpd_accept, httpd);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	httpd->render_404 = render_404;
	httpd->render_500 = render_500;

	*httpdp = httpd;
	return (ISC_R_SUCCESS);

  cleanup:
	isc_task_detach(&httpd->task);
	isc_socket_detach(&httpd->sock);
	isc_mem_detach(&httpd->mctx);
	(void)isc_mutex_destroy(&httpd->lock);
	isc_mem_put(mctx, httpd, sizeof(isc_httpdmgr_t));
	return (result);
}
Beispiel #27
0
isc_result_t
isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
		   unsigned int default_quantum, isc_taskmgr_t **managerp)
{
	isc_result_t result;
	unsigned int i, started = 0;
	isc_taskmgr_t *manager;

	/*
	 * Create a new task manager.
	 */

	REQUIRE(workers > 0);
	REQUIRE(managerp != NULL && *managerp == NULL);

#ifndef ISC_PLATFORM_USETHREADS
	UNUSED(i);
	UNUSED(started);
	UNUSED(workers);

	if (taskmgr != NULL) {
		taskmgr->refs++;
		*managerp = taskmgr;
		return (ISC_R_SUCCESS);
	}
#endif /* ISC_PLATFORM_USETHREADS */

	manager = isc_mem_get(mctx, sizeof(*manager));
	if (manager == NULL)
		return (ISC_R_NOMEMORY);
	manager->magic = TASK_MANAGER_MAGIC;
	manager->mctx = NULL;
	result = isc_mutex_init(&manager->lock);
	if (result != ISC_R_SUCCESS)
		goto cleanup_mgr;

#ifdef ISC_PLATFORM_USETHREADS
	manager->workers = 0;
	manager->threads = isc_mem_allocate(mctx,
					    workers * sizeof(isc_thread_t));
	if (manager->threads == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup_lock;
	}
	if (isc_condition_init(&manager->work_available) != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_condition_init() %s",
				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
						ISC_MSG_FAILED, "failed"));
		result = ISC_R_UNEXPECTED;
		goto cleanup_threads;
	}
	if (isc_condition_init(&manager->exclusive_granted) != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_condition_init() %s",
				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
						ISC_MSG_FAILED, "failed"));
		result = ISC_R_UNEXPECTED;
		goto cleanup_workavailable;
	}
#endif /* ISC_PLATFORM_USETHREADS */
	if (default_quantum == 0)
		default_quantum = DEFAULT_DEFAULT_QUANTUM;
	manager->default_quantum = default_quantum;
	INIT_LIST(manager->tasks);
	INIT_LIST(manager->ready_tasks);
	manager->tasks_running = 0;
	manager->exclusive_requested = ISC_FALSE;
	manager->exiting = ISC_FALSE;

	isc_mem_attach(mctx, &manager->mctx);

#ifdef ISC_PLATFORM_USETHREADS
	LOCK(&manager->lock);
	/*
	 * Start workers.
	 */
	for (i = 0; i < workers; i++) {
		if (isc_thread_create(run, manager,
				      &manager->threads[manager->workers]) ==
		    ISC_R_SUCCESS) {
			manager->workers++;
			started++;
		}
	}
	UNLOCK(&manager->lock);

	if (started == 0) {
		manager_free(manager);
		return (ISC_R_NOTHREADS);
	}
	isc_thread_setconcurrency(workers);
#else /* ISC_PLATFORM_USETHREADS */
	manager->refs = 1;
	taskmgr = manager;
#endif /* ISC_PLATFORM_USETHREADS */

	*managerp = manager;

	return (ISC_R_SUCCESS);

#ifdef ISC_PLATFORM_USETHREADS
 cleanup_workavailable:
	(void)isc_condition_destroy(&manager->work_available);
 cleanup_threads:
	isc_mem_free(mctx, manager->threads);
 cleanup_lock:
	DESTROYLOCK(&manager->lock);
#endif
 cleanup_mgr:
	isc_mem_put(mctx, manager, sizeof(*manager));
	return (result);
}
Beispiel #28
0
ISC_TIMERFUNC_SCOPE isc_result_t
isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
	isc__timermgr_t *manager;
	isc_result_t result;

	/*
	 * Create a timer manager.
	 */

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

#ifdef USE_SHARED_MANAGER
	if (timermgr != NULL) {
		timermgr->refs++;
		*managerp = (isc_timermgr_t *)timermgr;
		return (ISC_R_SUCCESS);
	}
#endif /* USE_SHARED_MANAGER */

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

	manager->common.impmagic = TIMER_MANAGER_MAGIC;
	manager->common.magic = ISCAPI_TIMERMGR_MAGIC;
	manager->common.methods = (isc_timermgrmethods_t *)&timermgrmethods;
	manager->mctx = NULL;
	manager->done = ISC_FALSE;
	INIT_LIST(manager->timers);
	manager->nscheduled = 0;
	isc_time_settoepoch(&manager->due);
	manager->heap = NULL;
	result = isc_heap_create(mctx, sooner, set_index, 0, &manager->heap);
	if (result != ISC_R_SUCCESS) {
		INSIST(result == ISC_R_NOMEMORY);
		isc_mem_put(mctx, manager, sizeof(*manager));
		return (ISC_R_NOMEMORY);
	}
	result = isc_mutex_init(&manager->lock);
	if (result != ISC_R_SUCCESS) {
		isc_heap_destroy(&manager->heap);
		isc_mem_put(mctx, manager, sizeof(*manager));
		return (result);
	}
	isc_mem_attach(mctx, &manager->mctx);
#ifdef USE_TIMER_THREAD
	if (isc_condition_init(&manager->wakeup) != ISC_R_SUCCESS) {
		isc_mem_detach(&manager->mctx);
		DESTROYLOCK(&manager->lock);
		isc_heap_destroy(&manager->heap);
		isc_mem_put(mctx, manager, sizeof(*manager));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_condition_init() %s",
				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
						ISC_MSG_FAILED, "failed"));
		return (ISC_R_UNEXPECTED);
	}
	if (isc_thread_create(run, manager, &manager->thread) !=
	    ISC_R_SUCCESS) {
		isc_mem_detach(&manager->mctx);
		(void)isc_condition_destroy(&manager->wakeup);
		DESTROYLOCK(&manager->lock);
		isc_heap_destroy(&manager->heap);
		isc_mem_put(mctx, manager, sizeof(*manager));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_thread_create() %s",
				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
						ISC_MSG_FAILED, "failed"));
		return (ISC_R_UNEXPECTED);
	}
#endif
#ifdef USE_SHARED_MANAGER
	manager->refs = 1;
	timermgr = manager;
#endif /* USE_SHARED_MANAGER */

	*managerp = (isc_timermgr_t *)manager;

	return (ISC_R_SUCCESS);
}
Beispiel #29
0
/*
 * Handle lwresd manager objects
 */
isc_result_t
ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres,
		     ns_lwresd_t **lwresdp)
{
	ns_lwresd_t *lwresd;
	const char *vname;
	dns_rdataclass_t vclass;
	const cfg_obj_t *obj, *viewobj, *searchobj;
	const cfg_listelt_t *element;
	isc_result_t result;

	INSIST(lwresdp != NULL && *lwresdp == NULL);

	lwresd = isc_mem_get(mctx, sizeof(ns_lwresd_t));
	if (lwresd == NULL)
		return (ISC_R_NOMEMORY);

	lwresd->mctx = NULL;
	isc_mem_attach(mctx, &lwresd->mctx);
	lwresd->view = NULL;
	lwresd->search = NULL;
	lwresd->refs = 1;

	obj = NULL;
	(void)cfg_map_get(lwres, "ndots", &obj);
	if (obj != NULL)
		lwresd->ndots = cfg_obj_asuint32(obj);
	else
		lwresd->ndots = 1;

	RUNTIME_CHECK(isc_mutex_init(&lwresd->lock) == ISC_R_SUCCESS);

	lwresd->shutting_down = ISC_FALSE;

	viewobj = NULL;
	(void)cfg_map_get(lwres, "view", &viewobj);
	if (viewobj != NULL) {
		vname = cfg_obj_asstring(cfg_tuple_get(viewobj, "name"));
		obj = cfg_tuple_get(viewobj, "class");
		result = ns_config_getclass(obj, dns_rdataclass_in, &vclass);
		if (result != ISC_R_SUCCESS)
			goto fail;
	} else {
		vname = "_default";
		vclass = dns_rdataclass_in;
	}

	result = dns_viewlist_find(&ns_g_server->viewlist, vname, vclass,
				   &lwresd->view);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
			      "couldn't find view %s", vname);
		goto fail;
	}

	searchobj = NULL;
	(void)cfg_map_get(lwres, "search", &searchobj);
	if (searchobj != NULL) {
		lwresd->search = NULL;
		result = ns_lwsearchlist_create(lwresd->mctx,
						&lwresd->search);
		if (result != ISC_R_SUCCESS) {
			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
				      NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
				      "couldn't create searchlist");
			goto fail;
		}
		for (element = cfg_list_first(searchobj);
		     element != NULL;
		     element = cfg_list_next(element))
		{
			const cfg_obj_t *search;
			const char *searchstr;
			isc_buffer_t namebuf;
			dns_fixedname_t fname;
			dns_name_t *name;

			search = cfg_listelt_value(element);
			searchstr = cfg_obj_asstring(search);

			dns_fixedname_init(&fname);
			name = dns_fixedname_name(&fname);
			isc_buffer_init(&namebuf, searchstr,
					strlen(searchstr));
			isc_buffer_add(&namebuf, strlen(searchstr));
			result = dns_name_fromtext(name, &namebuf,
						   dns_rootname, 0, NULL);
			if (result != ISC_R_SUCCESS) {
				isc_log_write(ns_g_lctx,
					      NS_LOGCATEGORY_GENERAL,
					      NS_LOGMODULE_LWRESD,
					      ISC_LOG_WARNING,
					      "invalid name %s in searchlist",
					      searchstr);
				continue;
			}

			result = ns_lwsearchlist_append(lwresd->search, name);
			if (result != ISC_R_SUCCESS) {
				isc_log_write(ns_g_lctx,
					      NS_LOGCATEGORY_GENERAL,
					      NS_LOGMODULE_LWRESD,
					      ISC_LOG_WARNING,
					      "couldn't update searchlist");
				goto fail;
			}
		}
	}

	lwresd->magic = LWRESD_MAGIC;

	*lwresdp = lwresd;
	return (ISC_R_SUCCESS);

 fail:
	if (lwresd->view != NULL)
		dns_view_detach(&lwresd->view);
	if (lwresd->search != NULL)
		ns_lwsearchlist_detach(&lwresd->search);
	if (lwresd->mctx != NULL)
		isc_mem_detach(&lwresd->mctx);
	isc_mem_put(mctx, lwresd, sizeof(ns_lwresd_t));
	return (result);
}
Beispiel #30
0
static isc_result_t
xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
		  dns_name_t *qname, dns_rdatatype_t qtype,
		  dns_rdataclass_t qclass, dns_zone_t *zone,
		  dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
		  rrstream_t *stream, dns_tsigkey_t *tsigkey,
		  isc_buffer_t *lasttsig, unsigned int maxtime,
		  unsigned int idletime, isc_boolean_t many_answers,
		  xfrout_ctx_t **xfrp)
{
	xfrout_ctx_t *xfr;
	isc_result_t result;
	unsigned int len;
	void *mem;

	INSIST(xfrp != NULL && *xfrp == NULL);
	xfr = isc_mem_get(mctx, sizeof(*xfr));
	if (xfr == NULL)
		return (ISC_R_NOMEMORY);
	xfr->mctx = NULL;
	isc_mem_attach(mctx, &xfr->mctx);
	xfr->client = NULL;
	ns_client_attach(client, &xfr->client);
	xfr->id = id;
	xfr->qname = qname;
	xfr->qtype = qtype;
	xfr->qclass = qclass;
	xfr->zone = NULL;
	xfr->db = NULL;
	xfr->ver = NULL;
	if (zone != NULL)	/* zone will be NULL if it's DLZ */
		dns_zone_attach(zone, &xfr->zone);
	dns_db_attach(db, &xfr->db);
	dns_db_attachversion(db, ver, &xfr->ver);
	xfr->end_of_stream = ISC_FALSE;
	xfr->tsigkey = tsigkey;
	xfr->lasttsig = lasttsig;
	xfr->txmem = NULL;
	xfr->txmemlen = 0;
	xfr->nmsg = 0;
	xfr->many_answers = many_answers,
	xfr->sends = 0;
	xfr->shuttingdown = ISC_FALSE;
	xfr->mnemonic = NULL;
	xfr->buf.base = NULL;
	xfr->buf.length = 0;
	xfr->txmem = NULL;
	xfr->txmemlen = 0;
	xfr->stream = NULL;
	xfr->quota = NULL;

	/*
	 * Allocate a temporary buffer for the uncompressed response
	 * message data.  The size should be no more than 65535 bytes
	 * so that the compressed data will fit in a TCP message,
	 * and no less than 65535 bytes so that an almost maximum-sized
	 * RR will fit.  Note that although 65535-byte RRs are allowed
	 * in principle, they cannot be zone-transferred (at least not
	 * if uncompressible), because the message and RR headers would
	 * push the size of the TCP message over the 65536 byte limit.
	 */
	len = 65535;
	mem = isc_mem_get(mctx, len);
	if (mem == NULL) {
		result = ISC_R_NOMEMORY;
		goto failure;
	}
	isc_buffer_init(&xfr->buf, mem, len);

	/*
	 * Allocate another temporary buffer for the compressed
	 * response message and its TCP length prefix.
	 */
	len = 2 + 65535;
	mem = isc_mem_get(mctx, len);
	if (mem == NULL) {
		result = ISC_R_NOMEMORY;
		goto failure;
	}
	isc_buffer_init(&xfr->txlenbuf, mem, 2);
	isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2);
	xfr->txmem = mem;
	xfr->txmemlen = len;

	CHECK(dns_timer_setidle(xfr->client->timer,
				maxtime, idletime, ISC_FALSE));

	/*
	 * Register a shutdown callback with the client, so that we
	 * can stop the transfer immediately when the client task
	 * gets a shutdown event.
	 */
	xfr->client->shutdown = xfrout_client_shutdown;
	xfr->client->shutdown_arg = xfr;
	/*
	 * These MUST be after the last "goto failure;" / CHECK to
	 * prevent a double free by the caller.
	 */
	xfr->quota = quota;
	xfr->stream = stream;

	*xfrp = xfr;
	return (ISC_R_SUCCESS);

failure:
	xfrout_ctx_destroy(&xfr);
	return (result);
}