handle_ipv6_ptr(struct module_qstate* qstate, int id)
{
    struct dns64_env* dns64_env = (struct dns64_env*)qstate->env->modinfo[id];
    struct module_qstate* subq = NULL;
    struct query_info qinfo;
    struct sockaddr_in6 sin6;

    /* Convert the PTR query string to an IPv6 address. */
    memset(&sin6, 0, sizeof(sin6));
    sin6.sin6_family = AF_INET6;
    if (!ptr_to_ipv6((char*)qstate->qinfo.qname, sin6.sin6_addr.s6_addr,
	sizeof(sin6.sin6_addr.s6_addr)))
        return module_wait_module;  /* Let other module handle this. */

    /*
     * If this IPv6 address is not part of our DNS64 prefix, then we don't need
     * to do anything. Let another module handle the query.
     */
    if (addr_in_common((struct sockaddr_storage*)&sin6, 128,
                &dns64_env->prefix_addr, dns64_env->prefix_net,
                (socklen_t)sizeof(sin6)) != dns64_env->prefix_net)
        return module_wait_module;

    verbose(VERB_ALGO, "dns64: rewrite PTR record");

    /*
     * Create a new PTR query info for the domain name corresponding to the IPv4
     * address corresponding to the IPv6 address corresponding to the original
     * PTR query domain name.
     */
    qinfo = qstate->qinfo;
    if (!(qinfo.qname = regional_alloc(qstate->region, MAX_PTR_QNAME_IPV4)))
        return module_error;
    qinfo.qname_len = ipv4_to_ptr(extract_ipv4(sin6.sin6_addr.s6_addr,
		sizeof(sin6.sin6_addr.s6_addr), dns64_env->prefix_net),
		(char*)qinfo.qname, MAX_PTR_QNAME_IPV4);

    /* Create the new sub-query. */
    fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
    if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0, 0,
                &subq))
        return module_error;
    if (subq) {
        subq->curmod = id;
        subq->ext_state[id] = module_state_initial;
	subq->minfo[id] = NULL;
    }

    return module_wait_subquery;
}
handle_ipv6_ptr(struct module_qstate* qstate, int id)
{
    struct dns64_env* dns64_env = (struct dns64_env*)qstate->env->modinfo[id];
    struct module_qstate* subq = NULL;
    struct query_info qinfo;
    struct sockaddr_in6 sin6;

     
    memset(&sin6, 0, sizeof(sin6));
    sin6.sin6_family = AF_INET6;
    if (!ptr_to_ipv6((char*)qstate->qinfo.qname, sin6.sin6_addr.s6_addr,
	sizeof(sin6.sin6_addr.s6_addr)))
        return module_wait_module;   

     
    if (addr_in_common((struct sockaddr_storage*)&sin6, 128,
                &dns64_env->prefix_addr, dns64_env->prefix_net,
                (socklen_t)sizeof(sin6)) != dns64_env->prefix_net)
        return module_wait_module;

    verbose(VERB_ALGO, "dns64: rewrite PTR record");

     
    qinfo = qstate->qinfo;
    if (!(qinfo.qname = regional_alloc(qstate->region, MAX_PTR_QNAME_IPV4)))
        return module_error;
    qinfo.qname_len = ipv4_to_ptr(extract_ipv4(sin6.sin6_addr.s6_addr,
		sizeof(sin6.sin6_addr.s6_addr), dns64_env->prefix_net),
		(char*)qinfo.qname, MAX_PTR_QNAME_IPV4);

     
    fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
    if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0, 0,
                &subq))
        return module_error;
    if (subq) {
        subq->curmod = id;
        subq->ext_state[id] = module_state_initial;
	subq->minfo[id] = NULL;
    }

    return module_wait_subquery;
}