рассчитать диапазон IP, используя PHP и CIDR

Я видел различные вопросы и ответы на этом сайте, и у меня все еще есть трудности, обертывающие мою голову вокруг этой проблемы (может быть, потому что я простудился). Несмотря на это, я пытаюсь создать небольшое веб-приложение, которое создаст таблицы IP-адресов для каждого из наших офисов.

Например, если я создаю новую область для 10.1.10.0/4, она создаст массив (который я могу затем распечатать в таблице):

10.1.10.0 network ID 10.1.10.1 gateway 10.1.10.2 usable 10.1.10.3 broadcast 

(не то, чтобы он вставлял описания автоматически, но это то, что мы будем делать).

Я уверен, что я буду использовать ip2long / long2ip для хранения адресов как целых чисел, но все же.

Как вы уже отметили, все адреса IPv4 могут быть преобразованы в номера с помощью ip2long() и преобразованы обратно с помощью long2ip() . Критический дополнительный бит, я не уверен, что вы заметили, что последовательные IP-адреса соответствуют порядковым номерам, поэтому вы можете манипулировать этими цифрами!

Учитывая префикс CIDR (например, $prefix = 30 для вашего диапазона), вы можете рассчитать количество IP-адресов в этом диапазоне с помощью оператора смены битов :

 $ip_count = 1 << (32 - $prefix); 

Затем пройдите через все IP-адреса в этом диапазоне, используя:

 $start = ip2long($start_ip); for ($i = 0; $i < $ip_count; $i++) { $ip = long2ip($start + $i); // do stuff with $ip... } 

Я использую следующую функцию, чтобы дать мне сеть, 1-й годный для использования, последний год использования и широковещательный адрес вместе со всеми хостами:

 function ipv4Breakout ($ip_address, $ip_nmask) { $hosts = array(); //convert ip addresses to long form $ip_address_long = ip2long($ip_address); $ip_nmask_long = ip2long($ip_nmask); //caculate network address $ip_net = $ip_address_long & $ip_nmask_long; //caculate first usable address $ip_host_first = ((~$ip_nmask_long) & $ip_address_long); $ip_first = ($ip_address_long ^ $ip_host_first) + 1; //caculate last usable address $ip_broadcast_invert = ~$ip_nmask_long; $ip_last = ($ip_address_long | $ip_broadcast_invert) - 1; //caculate broadcast address $ip_broadcast = $ip_address_long | $ip_broadcast_invert; foreach (range($ip_first, $ip_last) as $ip) { array_push($hosts, $ip); } $block_info = array(array("network" => "$ip_net"), array("first_host" => "$ip_first"), array("last_host" => "$ip_last"), array("broadcast" => "$ip_broadcast"), $hosts); return $block_info; } 

Я также заметил, что вы просите рассчитать на основе нотации CIDR. Вот функция, которую я использую для преобразования из CIDR в десятичное число:

 function v4CIDRtoMask($cidr) { $cidr = explode('/', $cidr); return array($cidr[0], long2ip(-1 << (32 - (int)$cidr[1]))); } 

Я занимаюсь главным образом десятичной точкой, а не с записью CIDR. Функция ipv4Breakout возвращает многомерный массив со всей необходимой информацией через длинный формат. Вам нужно будет использовать long2ip (), если вам нужен фактический десятичный IP-адрес. Для функции требуется IP-адрес и маска подсети через десятичный десятичный формат.

Надеюсь, это поможет вам или кому-то еще.

Моя версия поможет вам использовать переменные.

 <?php $ip_address = "192.168.0.2"; $ip_nmask = "255.255.255.0"; ipv4Breakout(); function ipv4Breakout () { global $ip_address; global $ip_nmask; //convert ip addresses to long form $ip_address_long = ip2long($ip_address); $ip_nmask_long = ip2long($ip_nmask); //caculate network address $ip_net = $ip_address_long & $ip_nmask_long; //caculate first usable address $ip_host_first = ((~$ip_nmask_long) & $ip_address_long); $ip_first = ($ip_address_long ^ $ip_host_first) + 1; //caculate last usable address $ip_broadcast_invert = ~$ip_nmask_long; $ip_last = ($ip_address_long | $ip_broadcast_invert) - 1; //caculate broadcast address $ip_broadcast = $ip_address_long | $ip_broadcast_invert; //Output $ip_net_short = long2ip($ip_net); $ip_first_short = long2ip($ip_first); $ip_last_short = long2ip($ip_last); $ip_broadcast_short = long2ip($ip_broadcast); echo "Network - " . $ip_net_short . "<br>"; echo "First usable - " . $ip_first_short . "<br>"; echo "Last usable - " . $ip_last_short . "<br>"; echo "Broadcast - " . $ip_broadcast_short . "<br>"; }