dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate)
{
	struct dns64_env* dns64_env = (struct dns64_env*)super->env->modinfo[id];
	struct reply_info *rep, *cp;
	size_t i, s;
	struct packed_rrset_data* fd, *dd;
	struct ub_packed_rrset_key* fk, *dk;

	verbose(VERB_ALGO, "converting A answers to AAAA answers");

	log_assert(super->region);
	log_assert(qstate->return_msg);
	log_assert(qstate->return_msg->rep);

	/* If dns64-synthall is enabled, return_msg is not initialized */
	if(!super->return_msg) {
		super->return_msg = (struct dns_msg*)regional_alloc(
		    super->region, sizeof(struct dns_msg));
		if(!super->return_msg)
			return;
		memset(super->return_msg, 0, sizeof(*super->return_msg));
		super->return_msg->qinfo = super->qinfo;
	}

	rep = qstate->return_msg->rep;

	/*
	 * Build the actual reply.
	 */
	cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount,
		rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
		rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
		rep->rrset_count, rep->security);
	if(!cp)
		return;

	/* allocate ub_key structures special or not */
	if(!reply_info_alloc_rrset_keys(cp, NULL, super->region)) {
		return;
	}

	/* copy everything and replace A by AAAA */
	for(i=0; i<cp->rrset_count; i++) {
		fk = rep->rrsets[i];
		dk = cp->rrsets[i];
		fd = (struct packed_rrset_data*)fk->entry.data;
		dk->rk = fk->rk;
		dk->id = fk->id;

		if(i<rep->an_numrrsets && fk->rk.type == htons(LDNS_RR_TYPE_A)) {
			/* also sets dk->entry.hash */
			dns64_synth_aaaa_data(fk, fd, dk, &dd, super->region, dns64_env);
			if(!dd)
				return;
			/* Delete negative AAAA record from cache stored by
			 * the iterator module */
			rrset_cache_remove(super->env->rrset_cache, dk->rk.dname, 
					   dk->rk.dname_len, LDNS_RR_TYPE_AAAA, 
					   LDNS_RR_CLASS_IN, 0);
			/* Delete negative AAAA in msg cache for CNAMEs,
			 * stored by the iterator module */
			if(i != 0) /* if not the first RR */
			    msg_cache_remove(super->env, dk->rk.dname,
				dk->rk.dname_len, LDNS_RR_TYPE_AAAA,
				LDNS_RR_CLASS_IN, 0);
		} else {
			dk->entry.hash = fk->entry.hash;
			dk->rk.dname = (uint8_t*)regional_alloc_init(super->region,
				fk->rk.dname, fk->rk.dname_len);

			if(!dk->rk.dname)
				return;

			s = packed_rrset_sizeof(fd);
			dd = (struct packed_rrset_data*)regional_alloc_init(
				super->region, fd, s);

			if(!dd)
				return;
		}

		packed_rrset_ptr_fixup(dd);
		dk->entry.data = (void*)dd;
	}

	/* Commit changes. */
	super->return_msg->rep = cp;
}
dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate)
{
	struct dns64_env* dns64_env = (struct dns64_env*)super->env->modinfo[id];
	struct reply_info *rep, *cp;
	size_t i, s;
	struct packed_rrset_data* fd, *dd;
	struct ub_packed_rrset_key* fk, *dk;

	verbose(VERB_ALGO, "converting A answers to AAAA answers");

	log_assert(super->region);
	log_assert(qstate->return_msg);
	log_assert(qstate->return_msg->rep);

	 
	if(!super->return_msg) {
		super->return_msg = (struct dns_msg*)regional_alloc(
		    super->region, sizeof(struct dns_msg));
		if(!super->return_msg)
			return;
		memset(super->return_msg, 0, sizeof(*super->return_msg));
		super->return_msg->qinfo = super->qinfo;
	}

	rep = qstate->return_msg->rep;

	 
	cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount,
		rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
		rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
		rep->rrset_count, rep->security);
	if(!cp)
		return;

	 
	if(!reply_info_alloc_rrset_keys(cp, NULL, super->region)) {
		return;
	}

	 
	for(i=0; i<cp->rrset_count; i++) {
		fk = rep->rrsets[i];
		dk = cp->rrsets[i];
		fd = (struct packed_rrset_data*)fk->entry.data;
		dk->rk = fk->rk;
		dk->id = fk->id;

		if(i<rep->an_numrrsets && fk->rk.type == htons(LDNS_RR_TYPE_A)) {
			 
			dns64_synth_aaaa_data(fk, fd, dk, &dd, super->region, dns64_env);
			if(!dd)
				return;
			 
			rrset_cache_remove(super->env->rrset_cache, dk->rk.dname, 
					   dk->rk.dname_len, LDNS_RR_TYPE_AAAA, 
					   LDNS_RR_CLASS_IN, 0);
			 
			if(i != 0)  
			    msg_cache_remove(super->env, dk->rk.dname,
				dk->rk.dname_len, LDNS_RR_TYPE_AAAA,
				LDNS_RR_CLASS_IN, 0);
		} else {
			dk->entry.hash = fk->entry.hash;
			dk->rk.dname = (uint8_t*)regional_alloc_init(super->region,
				fk->rk.dname, fk->rk.dname_len);

			if(!dk->rk.dname)
				return;

			s = packed_rrset_sizeof(fd);
			dd = (struct packed_rrset_data*)regional_alloc_init(
				super->region, fd, s);

			if(!dd)
				return;
		}

		packed_rrset_ptr_fixup(dd);
		dk->entry.data = (void*)dd;
	}

	 
	super->return_msg->rep = cp;
}