Объяснение преобразователя cidr в сетевую маску в оболочке linux netmask2cdir и cdir2netmask [закрыто]
Я нашел следующие функции оболочки из этого темы
mask2cdr ()
{
# Assumes there's no "255." after a non-255 byte in the mask
local x=${1##*255.}
set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) ${x%%.*}
x=${1%%*}
echo $(( + (${#x}/4) ))
}
cdr2mask ()
{
# Number of args to shift, 255..255, first non-255 byte, zeroes
set -- $(( 5 - ( / 8) )) 255 255 255 255 $(( (255 << (8 - ( % 8))) & 255 )) 0 0 0
[ -gt 1 ] && shift || shift
echo ${1-0}.${2-0}.${3-0}.${4-0}
}
не могли бы вы подробно объяснить, как эти функции преобразуют cidr в сетевую маску и сетевую маску в cidr? В частности, вызовы set
расширение параметр ${#…}
, и арифметическое разложение $((…))
довольно подавляющим.
1 ответов
mask2cdr()
чтобы получить префикс CIDR из точечно-десятичной маски сети, как эта:
255.255.192.0
сначала вам нужно преобразовать четыре октета в двоичный, а затем подсчитать наиболее значимые биты (т. е. количество ведущих):
11111111.11111111.11000000.00000000 # 18 ones = /18 in CIDR
эта функция делает это довольно изобретательно. Во-первых, мы снимаем все ведущие 255
октеты (т. е. октеты, которые все в двоичном формате) и хранить результаты в переменной x
:
local x=${1##*255.}
этот шаг использует расширения параметр, на который в значительной степени опирается весь сценарий. Если мы продолжим наш пример netmask 255.255.192.0
, теперь у нас есть следующие значения:
: 255.255.192.0
$x: 192.0
Далее мы устанавливаем три переменные: ,
и
. Они называются позиционные параметры; они очень похожи на обычные именованные переменные, но обычно устанавливаются при передаче аргументов скрипту или функция. Мы можем установить значения напрямую, используя
set --
, например:
set -- foo bar # = foo, = bar
я предпочитаю использовать именованные переменные над позиционными параметрами, так как это упрощает чтение и отладку скриптов, но конечный результат тот же. Мы установили в:
0^^^128^192^224^240^248^252^254^
это действительно просто таблица для преобразования определенных десятичных значений в двоичные и подсчета числа 1
бит. Мы вернемся к этому позже.
мы к
$(( (${#1} - ${#x})*2 ))
это называется Арифметические Расширения. Это выглядит сложным, но на самом деле это просто подсчет количества 1
биты мы сняли в первой команде. Он распадается на это:
(number of chars in - number of chars in $x) * 2
, который в нашем случае составляет
(13 - 5) * 2 = 16
мы сняли два октета, так что мы получаем 16. Обретать смысл.
мы в:
${x%%.*}
значение $x
все после первый .
снял. В нашем случае это 192
.
нам нужно преобразовать это число в двоичный код и подсчитать количество 1
бит в нем, поэтому давайте вернемся к нашей "таблице преобразования."Мы можем разделить таблицу на равные куски по четыре символа:
0^^^ 128^ 192^ 224^ 240^ 248^ 252^ 254^
в двоичном формате вышеуказанные числа:
00000000 10000000 11000000 11100000 11110000 11111000 11111100 11111110
# 0 ones 1 one 2 ones 3 ones ...
если считать с левой, в каждом из четырех блок символа в таблице соответствует дополнительному 1
бит в двоичном. Мы попытка преобразовать 192
, поэтому давайте сначала отрежем самую правую часть стола, от 192
on, и хранить его в x
:
x=${1%%*}
значение $x
теперь
0^^^128^
который содержит два четырехсимвольных блока или два 1
биты в двоичном формате.
теперь нам просто нужно сложить 1
биты от нашего ведущего 255
октеты (всего 16, хранятся в переменной ) и
1
биты с предыдущего шага (2 итого):
echo $(( + (${#x}/4) ))
здесь
${#x}/4
- количество символов в $x
делится на четыре, т. е. количество четырехсимвольных блоков в $x
.
выход:
18
cdr2mask()
давайте продолжим работать с нашим предыдущим примером, который имел префикс CIDR 18
.
мы используем:set --
для установки позиционных параметров $1 - $9:
: $(( 5 - ( / 8) )) # 5 - (18 / 8) = 3 [integer math]
: 255
: 255
: 255
: 255
: $(( (255 << (8 - ( % 8))) & 255 )) # (255 << (8 - (18 % 8))) & 255 = 192
: 0
: 0
: 0
рассмотрим формулы используется для установки и
немного ближе.
установлено:
$(( 5 - ( / 8) ))
максимальное и минимальное возможные значения для префикса CIDR-32 для netmask
11111111.11111111.11111111.11111111
и 0 для маски
00000000.00000000.00000000.00000000
в приведенной выше формуле используется целочисленное деление, поэтому возможные результаты варьируются от 1 до 5:
5 - (32 / 8) = 1
5 - ( 0 / 8) = 5
установлено:
$(( (255 << (8 - ( % 8))) & 255 ))
давайте разберем это для нашего примера префикса CIDR 18
. Сначала мы возьмите модуль и сделайте некоторое вычитание:
8 - (18 % 8) = 6
Далее мы побитовый сдвиг 255 на это значение:
255 << 6
это то же самое, что нажать шесть 0
бит на конец 255 в двоичном формате:
11111111000000
наконец, мы побитовые и это значение с 255:
11111111000000 &
00000011111111 # 255
что дает
00000011000000
или просто
11000000
знакомо? Это третий октет в нашем Маска в binary:
11111111.11111111.11000000.00000000
^------^
в десятичном формате значение равно 192.
Далее мы сдвигаем позиционные параметры на основе значения :
[ -gt 1 ] && shift || shift
в нашем случае значение равно 3, поэтому мы смещаем позиционные параметры 3 влево. Предыдущее значение
становится новым значением
, Предыдущее значение
становится значением
и так:
: 255
: 255
: 192
: 0
: 0
: 0
эти значения должны выглядеть знакомыми: они являются десятичными октетами из нашей сетевой маски (с парой дополнительных нулей, прикрепленных в конце). Чтобы получить сетевую маску, мы просто распечатываем первые четыре с точками между ними:
echo ${1-0}.${2-0}.${3-0}.${4-0}
на -0
после каждого параметра, что надо использовать 0
как значение по умолчанию, если параметр не задан.
выход:
255.255.192.0