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 and prefix size to an address range for the network.
 *
 * This will take an IPv6 address and prefix and return the first and last address available for the network. 
 *
 * @param  string  $addr A valid IPv6 address
 * @param  integer $prefix The prefix size, an integer between 1 and 127 (inclusive)
 * @return array   An array with two strings containing the start and end address for the IPv6 network
 */
function inet6_to_range($addr, $prefix)
{
    $size = 128 - $prefix;
    $addr = gmp_init('0x' . str_replace(':', '', inet6_expand($addr)));
    $mask = gmp_init('0x' . str_replace(':', '', inet6_expand(inet6_prefix_to_mask($prefix))));
    $prefix = gmp_and($addr, $mask);
    $start = gmp_strval(gmp_add($prefix, '0x1'), 16);
    $end = '0b';
    for ($i = 0; $i < $size; $i++) {
        $end .= '1';
    }
    $end = gmp_strval(gmp_add($prefix, gmp_init($end)), 16);
    for ($i = 0; $i < 8; $i++) {
        $start_result .= substr($start, $i * 4, 4);
        if ($i != 7) {
            $start_result .= ':';
        }
    }
    // for
    for ($i = 0; $i < 8; $i++) {
        $end_result .= substr($end, $i * 4, 4);
        if ($i != 7) {
            $end_result .= ':';
        }
    }
    // for
    $result = array(inet6_compress($start_result), inet6_compress($end_result));
    return $result;
}