function ip_in_network6($ip, $net_addr, $net_mask = false)
{
    if (!$net_mask && strpos($net_addr, "/") !== false) {
        $cidr_arr = explode("/", $net_addr);
        $net_addr = $cidr_arr[0];
        $net_mask = $cidr_arr[1];
    }
    $ip = inet6_expand($ip);
    $net_addr = inet6_expand($net_addr);
    $net_mask_hex = inet6_expand(inet6_prefix_to_mask($net_mask));
    $ip_dec_arr = inet6_to_int64($ip);
    $net_dec_arr = inet6_to_int64($net_addr);
    $mask_dec_arr = inet6_to_int64($net_mask_hex);
    // Need to handle >64 bit net masks
    if ($net_mask > 64) {
        $net_mask_64_arr[0] = 64;
        $net_mask_64_arr[1] = 64 - (128 - $net_mask);
    } else {
        $net_mask_64_arr[0] = $net_mask;
        $net_mask_64_arr[1] = false;
    }
    if ((substr(gmp_convert($ip_dec_arr[0], 10, 2), 0, $net_mask_64_arr[0]) & substr(gmp_convert($mask_dec_arr[0], 10, 2), 0, $net_mask_64_arr[0])) == substr(gmp_convert($net_dec_arr[0], 10, 2), 0, $net_mask_64_arr[0])) {
        if ($net_mask_64_arr[1]) {
            if ((substr(gmp_convert($ip_dec_arr[1], 10, 2), 0, $net_mask_64_arr[1]) & substr(gmp_convert($mask_dec_arr[1], 10, 2), 0, $net_mask_64_arr[1])) != substr(gmp_convert($net_dec_arr[1], 10, 2), 0, $net_mask_64_arr[1])) {
                return false;
            }
        }
        return true;
    }
}
/**
 * Convert an IPv6 address to two 64-bit integers.
 *
 * This will translate an IPv6 address into two 64-bit integer values for storage in an SQL database. 
 *
 * @param  string  $addr A valid IPv6 address
 * @return array   An array with two strings containing the 64-bit interger values
 */
function inet6_to_int64($addr)
{
    /* Expand the address if necessary */
    if (strlen($addr) != 39) {
        $addr = inet6_expand($addr);
        if ($addr == false) {
            return false;
        }
    }
    // if
    $addr = str_replace(':', '', $addr);
    $p1 = '0x' . substr($addr, 0, 16);
    $p2 = '0x' . substr($addr, 16);
    $p1 = gmp_init($p1);
    $p2 = gmp_init($p2);
    $result = array(gmp_strval($p1), gmp_strval($p2));
    return $result;
}
 // Ensure this is a valid IPv6 prefix
 $prefix_split_arr = explode("/", $prefix);
 if (!filter_var($prefix_split_arr[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
     $ip_arr = explode(".", substr($qname, 0, strlen($qname) - 9));
     $ip_arr = array_reverse($ip_arr);
     for ($i = 0; $i < 32; $i++) {
         $qname_ip .= $ip_arr[$i] ? $ip_arr[$i] : '0';
         if ($i % 4 == 3 && $i != 31) {
             $qname_ip .= ":";
         }
     }
     if (ip_in_network6($qname_ip, $prefix)) {
         switch ($query['parameters']['qtype']) {
             case 'SOA':
                 // Generate SOA name from prefix
                 $prefix_expanded = inet6_expand($prefix_split_arr[0]);
                 $prefix_expanded = str_replace(':', '', $prefix_expanded);
                 $prefix_arr = str_split($prefix_expanded);
                 $octets = floor($prefix_split_arr[1] / 4);
                 for ($i = $octets - 1; $i >= 0; $i--) {
                     $prefix_soa_qname .= $prefix_arr[$i] . '.';
                 }
                 $prefix_soa_qname .= 'ip6.arpa';
                 if (ip_in_network6($qname_ip, $prefix) || $prefix_soa_qname == $qname) {
                     $result = array('result' => array(array('qtype' => 'SOA', 'qname' => $query['parameters']['qname'], 'content' => implode(" ", $soa), 'ttl' => $soa[6])));
                 }
                 break;
             case 'NS':
                 break;
             default:
                 $ip_arr = explode(".", substr($qname, 0, strlen($qname) - 9));