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));