2013-04-12 3 views
1

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

Как сказать, если я создаю новую область для 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 для хранения адресов как целых чисел, но все же.

+0

'10.1.10.0/4' составляет 1/16 всего диапазона IPv4 (268 миллионов адресов). Эти четыре адреса: '10.1.10.0/28'. – duskwuff

+0

да вместо 10.1.10.0/4 i означает 10.1.10.0/30. Как я уже сказал, в то время мне было холодно, и я не очень четко думал. Хотя мне все еще нужна помощь при разработке метода, который будет генерировать IP-массив. Проблема: сформировать массив IP-адресов на основе пользовательского ввода битовой маски ID сети/CIDR. так, что если пользователь вводит 10.1.10.0/30, он будет генерировать массив: массива [0] 10.1.10.1 массива [1] 10.1.10.2 массива [2] 10.1.10.3 Так он может быть хранится в базе данных SQLite. – greentiger

+0

Это не конкретный вопрос, вы даете программные требования. Что вы пробовали? Что не работает? –

ответ

8

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

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

$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... 
} 
+0

Спасибо, я собираюсь попробовать код сейчас :-) – greentiger

+0

ОК, это в основном работает, однако я не понимаю 1 << (префикс 32 - $); бит. Когда я вхожу в 30 как битовая маска, он возвращает значения 10.1.10.0 - 10.1.10.29. Что такое << делать? – greentiger

+0

ОК, я понял, как я хотел это сделать: \t $ bitmask = 30; \t $ ipaddr = "10.1.10.0"; \t функция buildArray ($ IPADDR, $ битовая маска) { \t \t $ ipcount = пау (2, (32 - $ битовая маска)); \t \t $ start = ip2long ($ ipaddr); \t \t для ($ биений = 0; $ такт <$ ipcount; $ биений ++) {\t \t \t \t $ iparr [$ биений] = long2ip ($ + $ начать бить); \t \t \t} \t \t return $ iparr; \t \t} \t $ sample = buildArray ($ ipaddr, $ bitmask); \t Еогеасп ($ образец, как $ значения) { \t \t печати "$ значение
\ п"; \t \t} – greentiger

3

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

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-адрес и маска подсети через десятичный десятичный формат.

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

+0

Я пробовал этот код, используя соответственно «123.234.123.234» в качестве IP и «255.255.255.255» в качестве сетевой маски. Для выполнения кода требуется много времени, а затем сбой «Разрешенный объем памяти исчерпан». Есть ли ошибка в этом коде, или это просто очень неэффективно? – vrijdenker

+0

Также: с netmask 255.255.255.255, я ожидал бы, что оба ip_first и ip_last будут одинаковыми, но это не так. Это верно? Не понимаю ли я это? – vrijdenker

1

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

<?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>"; 
} 
Смежные вопросы