[ PHP ] IPv4, IPv6 アドレス(文字列)の妥当性検証 ( ip2long / long2ip )

Pocket

ここでは、文字列で与えられた IPv4 と IPv6 アドレスの妥当性を検証するサンプルコードを掲載しています。

スポンサーリンク

IPv4 アドレスの妥当性を検証する

IPv4 アドレスの妥当性検証には PHP マニュアルにも記載があるように long2ip 関数と ip2long 関数を使用することが一般的であると思います。以下は Zend Framework による IPv4 アドレスの妥当性を検証する実装です。

/*
 * IPv4 アドレスの妥当性検証
 */
function validateIPv4($value)
{
    $ip2long = ip2long($value);
    if($ip2long === false) {
        return false;
    }

    /*
     * 変換した数値を再度 IP アドレスに変換し、入力値と比較する。
     */
    $long2ip = long2ip($ip2long);

    return $value == long2ip($ip2long);
}

var_dump(validateIPv4('127.0.0.1')); // true

var_dump(validateIPv4('127.0.0.256')); // false

注意点としては、127.020.0.1 のような入力は不正な IP アドレスの入力値として扱われます。long2ip 関数内で 020 を 8進数として扱い 127.16.0.1 に変換されてしまい、入力文字列と long2ip 関数のリターン値は異なってしまうためです。従って 020 のような入力を認める場合には、事前に 020 を 20 に編集する処理が必要になります。

IPv6 アドレスの妥当性を検証する

Zend Framework による IPv6 アドレスの妥当性を検証する実装になります。詳細はコメントを参照ください。

function validateIPv6($value) 
{
    // 未指定アドレス
    if (strlen($value) < 3) {
        return $value == '::';
    }

    // IPv4互換アドレス(廃止)やIPv4射影アドレス
    if (strpos($value, '.')) {
        $lastcolon = strrpos($value, ':');
        if (!($lastcolon && validateIPv4(substr($value, $lastcolon + 1)))) {
            return false;
        }

        $value = substr($value, 0, $lastcolon) . ':0:0';
    }

    // 省略表記なし
    if (strpos($value, '::') === false) {
        return preg_match('/\A(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}\z/i', $value);
    }

    // 省略表記あり
    $colonCount = substr_count($value, ':');
    if ($colonCount < 8) {
        return preg_match('/\A(?::|(?:[a-f0-9]{1,4}:)+):(?:(?:[a-f0-9]{1,4}:)*[a-f0-9]{1,4})?\z/i', $value);
    }

    // special case with ending or starting double colon(原文のまま)
    if ($colonCount == 8) {
        return preg_match('/\A(?:::)?(?:[a-f0-9]{1,4}:){6}[a-f0-9]{1,4}(?:::)?\z/i', $value);
    }

    return false;
}
参考
スポンサーリンク


Pocket

Leave a Comment

Your email address will not be published. Required fields are marked *