Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Расчёт маски подсети (обычная + CIDR) (http://forum.oszone.net/showthread.php?t=259471)

Anonymоus 26-04-2013 18:05 2140109

Расчёт маски подсети (обычная + CIDR)
 
Доработал один из своих старых скриптов, добавив в него поддержу CIDR-формата маски. Возможно, кому-то понадобится для решения сходной задачи, поэтому решил поделиться с сообществом.
Использование:
netmask <начальный IP диапазона> <конечный IP диапазона>
netmask <начальный IP диапазона> <конечный IP диапазона> cidr
Примеры:
netmask 195.189.120.0 195.189.123.255 = 255.255.252.0
netmask 195.189.120.0 195.189.123.255 CIDR = /22

Код:

@Echo Off
:: #
:: # Subnet mask from IP range v2.1
:: # Inquisitor, 2012-2013
:: # Distributed under GNU GPL v2 license
:: # http://www.gnu.org/licenses/gpl-2.0.html
:: #
:: # USAGE: NetMask.cmd first_ip_from_range last_ip_from_range
:: #        or, for display in CIDR format
:: #        NetMask.cmd first_ip_from_range last_ip_from_range cidr
:: #
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 "%*"=="" (
        For /F "tokens=1,* delims=#" %%A In ('FindStr /R /B "::.#" "%~dpnx0"') Do (
                Echo.%%B
        )
        GoTo :EOF
)

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

:CIDR
:: Трансформация маски в формат CIDR
Set BinMask=
Set i=0
:: Разбираем маску обратно на октеты
Set NetMask=!NetMask:.= !
For %%A In (!NetMask!) Do (
        Call :DEC2BIN %%A
        :: И собираем бинарную маску
        Set BinMask=!BinMask!!Result!
)
:: Удаляем из неё незначащие нули, а единицы разделяем пробелами
Set BinMask=!BinMask:0=!
Set BinMask=!BinMask:1=1 !
:: Считаем единицы
For %%A In (!BinMask!) Do (Set /A i+=1)
:: Устанавливаем значение
Set NetMask=/!i!
Exit /B



Время: 15:49.

Время: 15:49.
© OSzone.net 2001-