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%%$3*}
echo $(( $2 + (${#x}/4) ))
}
cdr2mask ()
{
# Number of args to shift, 255..255, first non-255 byte, zeroes
set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0
[ $1 -gt 1 ] && shift $1 || shift
echo ${1-0}.${2-0}.${3-0}.${4-0}
}
你能详细解释一下这些函数如何将cidr转换为网络掩码,将网络掩码转换为cidr?具体来说,调用set,参数扩展${#…}和算术扩展$((…))是非常压倒性的.
解决方法:
mask2cdr()
要获得像这样的点十进制网络掩码的CIDR前缀:
255.255.192.0
首先必须将四个八位字节转换为二进制,然后计算最高有效位(即前导位数):
11111111.11111111.11000000.00000000 # 18 ones = /18 in CIDR
这个功能相当创造性地做到了.首先,我们剥离所有前导的255个八位字节(即所有二进制的八位字节)并将结果存储在变量x中:
local x=${1##*255.}
此步骤使用parameter expansion,整个脚本非常依赖.如果我们继续使用255.255.192.0的示例网络掩码,我们现在具有以下值:
$1: 255.255.192.0
$x: 192.0
接下来我们设置三个变量:$1,$2和$3.这些被称为positional parameters;它们与普通命名变量非常相似,但通常在将参数传递给脚本或函数时设置.我们可以使用set – 直接设置值,例如:
set -- foo bar # $1 = foo, $2 = bar
我更喜欢使用命名变量而不是位置参数,因为它使脚本更易于阅读和调试,但最终结果是相同的.我们设置$1到:
0^^^128^192^224^240^248^252^254^
这实际上只是一个将某些十进制值转换为二进制值并计算1位数的表.我们稍后再回过头来看看.
我们设置2美元
$(( (${#1} - ${#x})*2 ))
这被称为Arithmetic Expansion.它看起来很复杂,但它实际上只是计算我们在第一个命令中剥离的1位数.它分解为:
(number of chars in $1 - number of chars in $x) * 2
在我们的案例中,这是有用的
(13 - 5) * 2 = 16
我们剥离了两个八位字节,所以我们得到了16个.
我们将3美元设置为:
${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开始关闭表格的最右边部分,并将其存储在x中:
x=${1%%$3*}
$x的值现在是
0^^^128^
它包含两个四字符块,或两个1位二进制.
现在我们只需要从我们的前导255个八位字节(总共16个,存储在变量$2中)和前一个步骤中的1个位(总共2个)中加1位:
echo $(( $2 + (${#x}/4) ))
哪里
${#x}/4
是$x中的字符数除以4,即$x中的四字符块的数量.
输出:
18
cdr2mask()
让我们继续运行前面的例子,它的CIDR前缀是18.
我们使用set – 来设置位置参数$1到$9:
$1: $(( 5 - ($1 / 8) )) # 5 - (18 / 8) = 3 [integer math]
$2: 255
$3: 255
$4: 255
$5: 255
$6: $(( (255 << (8 - ($1 % 8))) & 255 )) # (255 << (8 - (18 % 8))) & 255 = 192
$7: 0
$8: 0
$9: 0
让我们来看看用于设置1美元和6美元的公式. $1设置为:
$(( 5 - ($1 / 8) ))
对于网络掩码,CIDR前缀的最大和最小可能值为32
11111111.11111111.11111111.11111111
和0表示网络掩码
00000000.00000000.00000000.00000000
上面的公式使用整数除法,因此可能的结果范围从1到5:
5 - (32 / 8) = 1
5 - ( 0 / 8) = 5
$6设定为:
$(( (255 << (8 - ($1 % 8))) & 255 ))
让我们为我们的示例CIDR前缀18分解.首先我们取模数并做一些减法:
8 - (18 % 8) = 6
接下来,我们按位移位255:
255 << 6
这与在二进制中将六个0位推到255的末尾相同:
11111111000000
最后,我们用255按位AND这个值:
11111111000000 &
00000011111111 # 255
这使
00000011000000
或者干脆
11000000
看起来熟悉?这是我们二进制网络掩码中的第三个八位字节:
11111111.11111111.11000000.00000000
^------^
在十进制中,值为192.
接下来,我们根据$1的值移动位置参数:
[ $1 -gt 1 ] && shift $1 || shift
在我们的例子中,$1的值是3,所以我们将位置参数3移到左边.之前的$4值变为$1的新值,之前的$5值变为$2的值,依此类推:
$1: 255
$2: 255
$3: 192
$4: 0
$5: 0
$6: 0
这些值应该看起来很熟悉:它们是来自我们网络掩码的十进制八位字节(最后添加了几个额外的零).为了获得网络掩码,我们只需在它们之间用点打印出前四个:
echo ${1-0}.${2-0}.${3-0}.${4-0}
如果未设置参数,则每个参数后面的-0表示使用0作为默认值.
输出:
255.255.192.0
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。