PHPのip2longとMySQLのINET_ATON

Pocket

PHP関数のip2longとMySQL関数のINET_ATONについて。

MySQL関数: INET_ATON

MySQL関数のINET_ATONはIPv4形式のIPアドレスをアドレスの数値を表す整数をネットワークバイト順序 (ビッグエンディアン) で返す。
INET_ATONは引数としてIPv4形式の文字列が渡された時、0〜4294967295の整数の値を返す。
IPアドレスとして正しくない文字列が渡されたときはNULLを返す。


select inet_aton('0.0.0.0'); -- 0
select inet_aton('128.0.0.0'); -- 2147483648
select inet_aton('255.255.255.255'); -- 4294967295

PHP関数: ip2long

PHP関数のip2longはIPv4形式のIPアドレスを整数に変換する。
ip2longで生成される整数は符号付きで64bit環境で0〜4294967295。32bit環境では-2147483648〜2147483647になる。
またPHPのバージョンによってはIPv4形式ではない文字列が渡された場合に有効な数値を返すことがある。

64bit環境


echo ip2long('0.0.0.0'); // 0
echo ip2long('128.0.0.0'); // 2147483648
echo ip2long('255.255.255.255'); // 4294967295

32bit環境


echo ip2long('0.0.0.0'); // 0
echo ip2long('128.0.0.0'); // -2147483648
echo ip2long('255.255.255.255'); // -1

このように32bit環境では同じIPアドレスを変換しても INET_ATON とは異なる結果を返す。

PHPマニュアル:ip2long

注意:
PHP の整数型は符号付き形式であり、32 ビットアーキテクチャ上では 多くの IP アドレスが負の整数値になります。 そのため、符号なし IP アドレスを文字列形式で取得するには sprintf() や printf() で “%u” を使用する必要があります。
注意:
PHP 5 <= 5.0.2 では、IP 255.255.255.255 に対して ip2long() が FALSE を返します。 これは PHP 5.0.3 で -1 を返すように修正されています (PHP 4 と同じ動作です)。

ip2longをINET_ATONに対応させる方法

前述のように32bit環境ではip2longが返す値はINET_ATONと同じではない。
しかしPHPとMySQLで整数化されたIPアドレスを同じように扱うために、PHP側の動作をMySQLのINET_ATONに合わせることは可能である。

まずip2longはIPv4形式以外の値に対して有効な値を返すことがあるので、与えられる文字列がipv4形式になっているかチェックする必要がある。

次に、32bit環境のip2longで負の値が返ることについてはオーバーフローが原因なので、sprintfで”%u”リテラルを使って文字列に変換することで回避する。
※”%u”は引数を整数として扱い、符号無しの 10 進数として表現するリテラル。


echo sprintf('%u',ip2long('128.0.0.0')); // 2147483648

正の値を返すip2long関数(実際に返るのは文字列だけど)ipToLongと、ipToLongで得た文字列をIpv4形式に変換するlongToIp関数。


// 正の値を返すip2long
function ipToLong($ip){
    return sprintf("%u", ip2long($ip));
}

// ipToLongの返り値をIPv4形式にする
function longToIp($ip){
    $long = 4294967295 - ($ip - 1);
    return long2ip(-$long);
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です