由於 IPv4 可以轉成十進位用推移的運算,但是 IPv6 要轉成十進位的話,會超過有效位數的顯示,另外由於ipv6本身是用十六進位表示,沒必要換成10進位。所以要用更漂亮的作法。我把他寫成 class = =!!:
函式
/** * ipv6 class by axer@ms1.boe.tcc.edu.tw */ class ipv6{ /** * ExpandIPv6Notation2Bin()- Convert an ipv6 address to bin string * @param string $ip6 - an ipv6 address * @return return the binary string of an ipv6 address if parameter ip6 is an ipv6 address, * else it return an empty string. */ public function ExpandIPv6Notation2Bin($ip6) { if (strpos($ip6, '::') !== false) $ip6 = str_replace('::', str_repeat(':0', 8 - substr_count($ip6, ':')).':', $ip6); $ip6parts = explode(':', $ip6); $res=""; foreach ($ip6parts as $part) $res .= str_pad(base_convert( $part, 16, 2), 16, 0, STR_PAD_LEFT); return $res; } /** * MatchCIDR6 -- Check if an ipv6 address is in the CDIR6 subnet. * @param string $cidr6 - an ipv6 subnet, ex 2001:288:5400/39 or 2001:288:5432:/64 or 2001:288:5478::/64.. * @param string $chkipv6 - an ipv6 address, ex ::1, 2001:288:5200::1, :: ,etc. * @return return true if $chkipv6 is inside the $cidr6 subnet, or return false. */ public function MatchCIDR6( $cidr6, $chkipv6) { list($ip6, $prefixlen) = explode('/', $cidr6); $cidrbin= substr( $this->ExpandIPv6Notation2Bin($ip6), 0, $prefixlen); $chkip6bin= substr( $this->ExpandIPv6Notation2Bin($chkipv6), 0, $prefixlen); if(! strcmp($cidrbin,$chkip6bin))return true; return false; } }
用法
$cidr6 = "2001:288:5400/39"; $ip6= "2001:288:5300:000::72A:4BE7"; $o_ipv6 = new ipv6(); // 檢查是ip6 是否在網段內 if( $o_ipv6->MatchCIDR6($cidr6,$ip6)) print "Inside"; else print "Outside";
備註:有參考別人的程式,不過來源佚失了
相關連結
原文 2009-11-26