Войти

Показать полную графическую версию : [решено] Подсчет маски


Magenta
28-07-2012, 20:53
Уважаемые форумчане, помогите решить проблему!
У меня есть сервер с игрой, доступ в игру разрешен лишь белому списку, куда входят отдельные IP и подсети. Для пользователей с динамикой, использую программу whosip от нирсофта, которая показывает инфо о ип и диапазоне. Ситуация такая - есть ссылка, куда заходит пользователь, проверяется по геобазе на страны, а дальше его ип автоматом вносится в белый список с помощью php (если статика или локалка) или передается с помощью php батнику, который читает вывод whosip, если динамика. Но программа выдает подсеть в виде x.x.x.x - x.x.x.x, а для внесения в белый список мне нужна именно маска в формате IP/x.x.x.x. НЕ CIDR, обычная маска. Не нашел в сети ни одной консольной программы для такого подсчета, обращаюсь к вам, гуру.

Anonymоus
28-07-2012, 21:45
мне нужна именно маска в формате IP/x.x.x.x »
Допустим, у вас есть IP 85.17.28.149. Вы с помощью вашей утилиты выясняете, что у него диапазон адресов - от 85.17.28.0 до 85.17.30.255.
85.17.28.0 - это начальный адрес диапазона, он у вас идет вот сюда: 85.17.28.0/XXX.XXX.XXX.XXX
Далее, запускаете приведенный ниже скрипт вот таким кодом (или прямо из PHP, если вы говорите, что можете выполнять из него консольные утилиты или батники)
For /F %%A In ('netmask.cmd 85.17.28.0 85.17.30.255') Do Echo %%A
На выходе получаете маску 255.255.252.0, которая и завершает запись в нужном вам формате: 85.17.28.0/255.255.252.0

Собственно, сам скрипт получения маски подсети из диапазона адресов.

@Echo Off
:: Subnet mask from IP range
:: Inquisitor, 2012
:: Distributed under GNU GPL v2 license
:: http://www.gnu.org/licenses/gpl-2.0.html
SetLocal EnableDelayedExpansion
Set NetworkHostBoundary=false
Set NetMask=

:: Если вызывается не из консоли, а из другого батника,
:: вызывать нужно из цикла for для корректной работы
:: Пример:
rem For /F %%A In ('netmask.cmd 192.168.1.0 192.168.8.255') Do Echo %%A

:: Проверка на запуск с аргументами
:: Если без аргументов - пример использования и выход
If "%*"=="" (Echo USAGE: %~nx0 192.168.1.0 192.168.3.255&GoTo :EOF)

:: Разбор входящих аргументов, cравнение начального и конечного
:: адресов по октетам
For /F "tokens=1-8 delims=. " %%A In ("%*") Do (
Call :Mask %%A %%E
Call :Mask %%B %%F
Call :Mask %%C %%G
Call :Mask %%D %%H
)
:: Вывод в stdout результата и выход, раскомментировать нужное
:: Вывод _БЕЗ_ перевода строки
rem<Nul Set /P Echo=!NetMask!
:: Вывод _С_ переводом строки
Echo !NetMask!
GoTo :EOF


:DEC2BIN
:: Функция перевода числа из десятеричной системы в двоичную
:: Принимает один аргумент, результат возвращается в %Result%
Set Result=
Set Data=%~1
:d2b_loop
:: Проверяем, есть ли остаток от деления
Set /A x1=Data/2
Set /A x2=x1*2
If "%x2%"=="%Data%" (Set Mod=0) Else (Set Mod=1)
:: Устанавливаем в качестве входных данных результат деления
Set Data=%x1%
:: Пишем результат поразрядно, в обратном порядке
Set Result=%Mod%%Result%
:: Следующая итерация или выход после окончания
If Not "%x1%"=="0" GoTo d2b_loop
:: Перед выходом - дополнение ведущими нулями до двух в восьмой
:: Требуется для корректного сравнения двух чисел без сдвига
Call :LeadingZero %Result%
GoTo :EOF

:BIN2DEC
:: Функция перевода числа из двоичной системы в десятеричную
:: Принимает один аргумент, результат возвращается в %Result%
Set Result=
:: Значение -1 для начала значения счетчика с нуля
Set i=-1
Set Data=%1
:b2d_loop
:: Получаем текущий разряд числа
Set /A i+=1
Set x1=%Data:~-1%
:: Используем бинарный сдвиг для получения степени двойки
Set /A x2="x1 * (1 << i)"
:: Добавляем к результату
Set /A Result+=%x2%
:: Следующая итерация или выход после окончания
If Not "%Data:~,-1%"=="" (Set Data=%Data:~,-1%&GoTo b2d_loop)
GoTo :EOF

:LeadingZero
:: Дополнение ведушими нулями до двух в восьмой (один байт)
:: Принимает один аргумент, результат возвращается в %Result%
Set Result=
Set Data=%~1
For /L %%A In (1,1,8) Do (
If Not "!Data!"=="" (
Set Result=!Data:~-1!!Result!
Set Data=!Data:~,-1!
) Else (
Set Result=0!Result!
)
)
GoTo :EOF

:FastCompare
:: Быстрое сравнение, если найдены различия - вызывается функция
:: более детального сравнения для поиска самого различия
:: Принимает два аргумента, результат возвращается в %Result%
If Not !NetworkHostBoundary!==true (
If "%1"=="%2" (
Set Result=11111111
GoTo :EOF
) Else (
Call :Compare %1 %2
)
) Else (
Set Result=00000000
)
GoTo :EOF

:Compare
:: Сравнение двух однобайтных чисел поразрядно, локализация начала различий
:: и забивание всего после первого различия нулями
:: Принимает два аргумента, результат возвращается в %Result%
:: Ведущие нули у обоих чисел обязательны
Set x1=%1&Set x2=%2
Set Result=
For /L %%A In (1,1,8) Do (
:: Получение ведущего разряда от каждого из чисел
Set n1=!x1:~,1!
Set n2=!x2:~,1!
:: Сравнение двух чисел и инвертирование бита
Set /A Data="1 ^ (n1 ^ n2)"
:: Установка флага начала различия
If !Data!==0 Set NetworkHostBoundary=true
:: Обнуление всех последующих после различия разрядов
If !NetworkHostBoundary!==true Set Data=0
:: Поразрядная запись результата
Set Result=!Result!!Data!
:: Устанавливаем остаток в качестве входных данных для следующей итерации
Set x1=!x1:~1!
Set x2=!x2:~1!
)
GoTo :EOF

:Mask
:: Генерация одного октета маски
:: Принимает два аргумента, результат дописывается к %NetMask%
Call :DEC2BIN %1&&Set From=!Result!
Call :DEC2BIN %2&&Set To=!Result!
Call :FastCompare !From! !To!
Call :BIN2DEC !Result!
If "!NetMask!"=="" (Set NetMask=!Result!) Else (Set NetMask=!NetMask!.!Result!)
GoTo :EOF

Отдельное спасибо Iska за вот это (http://forum.oszone.net/showpost.php?p=1953268) сообщение, без которого я вряд ли бы обратил внимание на такие замечательные возможности Set /A, как двоичные операторы.

Magenta
28-07-2012, 22:20
Спасибо, работает :)




© OSzone.net 2001-2012