Теория: определение принадлежности ip к подсети.

cybersage

Новичок
Теория: определение принадлежности ip к подсети.

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

Имеется файл списка латвийских подсетей: http://www.nic.lv/local.net
задача написать функцию проверки принадлежности случайного ip-адреса к этим подсетям, т.е. LV или NOT LV.

Генерация делается следующим образом:

PHP:
$stat = array();
$start = time();
for( $i = 0; $i < 100000; $i++ )
{
    $ip = rand( 1,254 ).'.'.rand( 1,254 ).'.'.rand( 1,254 ).'.'.rand( 1,254 );
    $res = check_ip( $ip );
    $stat[ $res ] += 1;
}
$end = time();
print print_r( $stat, 1 )."\n".( $end - $start )."\n";
Вот функцию check_ip как бы и надо написать. Задание практического применения (в данной трактовке) не имеет, но для самопознания крайне необходимо.
Пробовал делать примерно как в этом топике, но немного не разобрался с unsignd. Вобщем, помогите, а?
 

dimagolov

Новичок
0. Преобразуем IP клиента в 32-битное число
Для каждой сети делаем слудующее.
1. Преобразуем IP сети в 32-битное число
2. делаем маску 32 бита из всех единиц
3. делаем сдвиг влево на размер маски сети из списка
4. делаем AND проверяемого IP и маски
5. если результат совпал с адресом сети - он из нее
 

Alexandre

PHPПенсионер
dimagolov - только вот вопрос - как узнать маску подсети?

судя по списку ...
#194.8.12.0/23
#213.182.220.0/22

преобразуем в два числа long (мин и мах)
далее строим упорядоченный массив (список по мин. числу.)
ищем элемент в массиве
если вып услови >=мин и <= мах следовательно элемент принадлежит данной подсети.
 

ys

отодвинутый новичок
Alexandre

Зачем?
Две операции сравнения разве быстрее CMP + AND?
 

ys

отодвинутый новичок
Wicked

Я пользую для SQL такую конструкцию:

'select `id` from `nets` where (`netmask` & ' . $ip . '=`network`) order by `masklen` desc limit 1';

естественно, все поля unsigned (о чем нужно позаботиться при insert).
В базе полный фид из bgp. Вроде нагрузка в пределах нормы.
 

ys

отодвинутый новичок
Wicked

А что делать.
Как сравнением поймать "more specific route" ?
 

Alexandre

PHPПенсионер
Зачем?
Две операции сравнения разве быстрее CMP + AND?
ys я не увидел масок в списке по ссылке ;)
мне их что, самому вычислять?
если все заложить в БД, то там вообще просто -
SELECT name from iptable WHERE ip BETWEEN maxip AND minip
естественно все ip в лонг формате
 

ys

отодвинутый новичок
Alexandre
> я не увидел масок в списке по ссылке мне их что, самому вычислять?
По любому, что-то считать надо, в Вашем случае - maxip.

> SELECT name from iptable WHERE ip BETWEEN maxip AND minip

Ммм. В этом случае будет две записи:
91.151.192.0/20
91.151.196.0/24
следовательно, нужно еще поле для order.

>естественно все ip в лонг формате
В unsigned int прекрасно лезет (4 байта).

Хотя, это уже флейм пошел...
 

ys

отодвинутый новичок
Wicked
>не поверишь, но в signed int тоже .-)
Там 4 байта - это да, но это:
sprintf('%u',ip2long("255.255.255.255"));
не влезет.
 

Alexandre

PHPПенсионер
SELECT name from iptable WHERE ip BETWEEN maxip AND minip

Ммм. В этом случае будет две записи:
91.151.192.0/20
91.151.196.0/24
следовательно, нужно еще поле для order.
не понял - зачем поле для order...
ЗАДАЧА:
у меня есть ИПи (к примеру ) 91.151.196.11 -
необходимо определить к какой подсети принадлежит этот ИПи...

РЕШЕНИЕ:
91.151.196.11 -> to long

Далее делаем простой вышеуказанный селект, и если сетка есть в БД, то получаем ее наименование.

Перевести to long указанный по линку список и загрузить в БД - дело одного часа максимум (я бы ответил 15 минут)
 

ys

отодвинутый новичок
Alexandre
> не понял - зачем поле для order...
Выбрать из нескольких подсетей, куда может входить ИП, самую маленькую.

91.151.196.11 входит и в 91.151.192.0/20 и в 91.151.196.0/24.
 

SiMM

Новичок
> нужно еще поле для order
> Выбрать из нескольких подсетей, куда может входить ИП, самую маленькую.
А поле-то зачем? :) ORDER BY maxip-minip не устраивает?
 

ys

отодвинутый новичок
SiMM
>А поле-то зачем? ORDER BY maxip-minip не устраивает?

А зачем оно? У меня же есть mask, и нет предлагаемого maxip.
Я считаю, что незачем его считать.
Вот по полю mask(unsigned int) и сортируюсь.

P.s: Кстати из всего топика вынес, что с полем masklen я ступил, можно сортироваться и по маске.
 
Сверху