PHP - 文法 - IP アドレス範囲


 クラウディア


1. 概要
2. プログラム
3. 試験
4. 参考サイト

1. 概要

 これは、分類のしようがなかったんだな。  以前に、「PHP - よく使う関数」のネットワークの項で、「160.19.64.0 - 160.19.91.255」てな、「IPv4」のアドレス範囲を与えると、「160.19.64.0/20」「160.19.80.0/21」「160.19.88.0/22」てな、「CIDR」形式に変換するプログラムを書きましたが。  ここでは、「160.19.64-91.」てな、「ucspi-tcp」でルールチェックに使う形式に変換するプログラムを書いてみます。

2. プログラム

 「ChatGPT」くんの提案するがままですが。

<?php
/**
 * ipRangeToTcpserver
 *
 * 開始IP・終了IPを与えて tcpserver 用の簡潔なルール文字列を返す
 *
 * ルール:
 *  - 各オクテットは単一値 (e.g. 104) または範囲 (e.g. 18-63)
 *  - 最後のオクテットが 0-255 の完全範囲なら、そのオクテットは省略して末尾に '.' を付ける
 *
 * 例:
 *   ipRangeToTcpserver("104.129.18.0", "104.129.63.255") => "104.129.18-63."
 */
function ipRangeToTcpserver(string $startIp, string $endIp): string
{
	/**   are?


	**/
    if (!filter_var($startIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
	{
        throw new InvalidArgumentException("startIp is not a valid IPv4 address: $startIp");
    }

    if (!filter_var($endIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
	{
        throw new InvalidArgumentException("endIp is not a valid IPv4 address: $endIp");
    }

    $sOct = array_map('intval', explode('.', $startIp));
    $eOct = array_map('intval', explode('.', $endIp));

    // 開始 <= 終了 であることを確認
    $sLong = ip2long($startIp);
    $eLong = ip2long($endIp);

    if ($sLong === false || $eLong === false || $sLong > $eLong)
	{
        throw new InvalidArgumentException("Invalid IP range: $startIp - $endIp");
    }

    $parts = [];
    for ($i = 0; $i < 4; $i++)
	{
        $a = $sOct[$i];
        $b = $eOct[$i];

        if ($a === $b)
		{
            $parts[$i] = (string)$a;
        }
		else
		{
            $parts[$i] = $a . '-' . $b;
        }
    }

    // もし最後のオクテットが完全に 0-255 をカバーしているなら、最後のオクテットは省略して末尾に "." を付ける
    if ($parts[3] === '0-255')
	{
        // ただし、前のオクテットが全て固定 or 範囲でもそのまま使う
        $ruleParts = array_slice($parts, 0, 3);
        return implode('.', $ruleParts) . '.';
    } else
	{
        return implode('.', $parts);
    }
}
 てな感じになります。  ほぼ、もらったままなので、解説もできませんが。

3. 試験

 下記の呼び出し用のソースを書いて試験してみます。

<?php

$examples = [
	["104.129.18.0", "104.129.63.255"],
	["192.0.2.4", "192.0.2.4"],
	["10.0.0.0", "10.0.255.255"],
	["10.0.1.0", "10.0.1.255"],
	["172.16.5.10", "172.16.5.20"],
	["160.19.64.0", "160.19.91.255"],
];

foreach ($examples as $ex)
{
	echo $ex[0] . " - " . $ex[1] . " => " . ipRangeToTcpserver($ex[0], $ex[1]) . PHP_EOL;
}
 結果は。

104.129.18.0 - 104.129.63.255 => 104.129.18-63.
192.0.2.4 - 192.0.2.4 => 192.0.2.4
10.0.0.0 - 10.0.255.255 => 10.0.0-255.
10.0.1.0 - 10.0.1.255 => 10.0.1.
172.16.5.10 - 172.16.5.20 => 172.16.5.10-20
160.19.64.0 - 160.19.91.255 => 160.19.64-91.
 意図通りに動いているようです。

4. 参考サイト

 本ページは、「ChatGPT」くんを参考にさせていただきました

AbemaTV 無料体験