Bash 在两个IPv4地址之间以CIDR表示法查找IPv4网络的算法
我想找出这两个网络之间所有采用CIDR表示法的IPv4网络:Bash 在两个IPv4地址之间以CIDR表示法查找IPv4网络的算法,bash,networking,subnet,Bash,Networking,Subnet,我想找出这两个网络之间所有采用CIDR表示法的IPv4网络: 10.11.3.64-10.11.3.127 10.11.52.0-10.11.52.255 IPv4网络应具有尽可能短的子网掩码 将10.11.3.127转换为二进制、添加1并转换回十进制非常容易,以便获得网络的第一个地址。然后将10.11.52.0转换为二进制,减去1并转换回十进制,以获得网络的最后地址。但是,有没有建议哪种算法更适合用于找出10.11.3.128-10.11.51.255范围内的CIDR块?我只想提出一个建议,
10.11.3.64-10.11.3.127
10.11.52.0-10.11.52.255
IPv4网络应具有尽可能短的子网掩码
将
10.11.3.127
转换为二进制、添加1
并转换回十进制非常容易,以便获得网络的第一个地址。然后将10.11.52.0
转换为二进制,减去1
并转换回十进制,以获得网络的最后地址。但是,有没有建议哪种算法更适合用于找出10.11.3.128-10.11.51.255
范围内的CIDR块?我只想提出一个建议,我希望哪一个方向就足够了:)如果你想要最短的掩码(最大的网络),从最低的地址(10.11.3.128)开始,然后放上可能最小的掩码,从下一个地址开始,然后放上可能最小的掩码,等等。只是不要超过范围内的最大地址:
所有IP地址的计算都需要以二进制进行。点十进制表示法对于人类可读性来说很好,但不应该用于尝试IP地址计算。我非常喜欢这个问题,昨晚我看了一下,决定试一试。在这一点上,我有一个概念验证shell脚本正在工作 免责声明:
IPv4网络应具有尽可能短的子网掩码。
我们应该尝试从为网络保留的8位到提供的最大cidr,在本例中为25
好的,让我们看看正在运行的脚本:
[root@TIAGO-TEST2 tmp]# time bash ip.sh 10.11.3.64/25 10.11.52.0/24
10.11.3.128/25
10.11.4.0/22
10.11.8.0/21
10.11.16.0/20
10.11.32.0/20
10.11.48.0/22
real 0m48.376s
user 0m6.174s
sys 0m34.644s
代码如下:
#! /bin/bash
function split_octet {
sed -re "s/\./ /g" <<< "$1"
}
function dec2bin {
perl -e 'printf "%0'"$1"'b\n",'"$2"';'
}
function bin2dec {
perl -le 'print 0b'"$1"';'
}
function ip2bin {
str=""
for octet in $(split_octet $1); do
str="${str}$(dec2bin 8 $octet)"
done
echo "$str"
}
function bin2ip {
str=""
for octet in $(grep -Eo '.{8}' <<< $1); do
dec=$(bin2dec $octet)
str="${str}.${dec}"
done
echo "$str" | sed -re 's/^\.|\.$//g'
}
function ip2dec {
ip=$1
bin2dec $(ip2bin $ip )
}
function dec2ip {
dec=$1
bin2ip $(dec2bin 32 $dec )
}
function AND {
perl -e ' $a=0b'"$1"' & 0b'"$2"';
printf "%032b\n",$a
'
}
function OR {
perl -e ' $a=0b'"$1"' | 0b'"$2"';
printf "%032b\n",$a
'
}
function NOT {
perl -le ' $a= (~ 0b'"$1"') & 0xFFFFFFFF;
printf "%032b\n",$a
'
}
function get_network {
ip=$1; mask=$2;
if [ -n "$ip" -a -n "$mask" ];then
echo $(bin2ip $(AND $(ip2bin $ip) $(ip2bin $mask)))
return
fi
grep -qP "\d+\.\d+\.\d+.\d+/\d+" <<< "$ip"
if [ "$?" == 0 ];then
ip=$(get_ip_from_cidr $1 )
mask=$(get_mask_from_cidr $1)
echo $( bin2ip $(AND $(ip2bin $ip) $(ip2bin $mask)))
fi
}
function get_broadcast {
ip=$1; mask=$2;
if [ -n "$ip" -a -n "$mask" ];then
echo $( bin2ip $(OR $(ip2bin $ip) $(NOT $(ip2bin $mask) ) ))
return
fi
grep -qP "\d+\.\d+\.\d+.\d+/\d+" <<< "$ip"
if [ "$?" == 0 ];then
ip=$(get_ip_from_cidr $1 )
mask=$(get_mask_from_cidr $1)
echo $( bin2ip $(OR $(ip2bin $ip) $(NOT $(ip2bin $mask) ) ))
fi
}
function get_ip_from_cidr {
awk -F/ '{print $1}' <<< "$1"
}
function get_mask_from_cidr {
mask=$(awk -F/ '{print $2}' <<< "$1")
mask=$(cidr $mask)
mask=$(bin2ip $mask)
echo $mask
}
function cidr {
perl -e '
$n='"$1"';
$diff=32-$n;
print "1"x$n . "0"x$diff;
'
}
snet_cidr=$1
enet_cidr=$2
largest_cidr=$(echo -e "$snet_cidr\n$enet_cidr"| awk -F/ '{print $2}' | sort -rn | head -1 )
snet_dec=$( ip2dec $(get_ip_from_cidr $snet_cidr))
enet_dec=$( ip2dec $(get_ip_from_cidr $enet_cidr))
sbc_ip=$(get_broadcast $snet_cidr)
ebc_ip=$(get_broadcast $enet_cidr)
sbc_dec=$(ip2dec $sbc_ip)
ebc_dec=$(ip2dec $ebc_ip)
counter=$sbc_dec
while [ $counter -lt $enet_dec ];do
tip=$(dec2ip $counter)
for cidr in $(seq 8 $largest_cidr) ; do
tnet_ip=$(get_network $tip/$cidr)
tnet_cidr=$tnet_ip/$cidr
tbc_ip=$(get_broadcast $tnet_cidr)
tnet_dec=$( ip2dec $(get_ip_from_cidr $tnet_cidr))
tbc_dec=$(ip2dec $tbc_ip)
if [ $sbc_dec -lt $tnet_dec -a $enet_dec -gt $tbc_dec ];then
echo $tnet_cidr
counter=$tbc_dec
break
fi
done
let counter++
done
#/bin/bash
函数分裂八位组{
sed-re“s/\.//g”解释IPv4网络应具有尽可能短的子网掩码。
@hek2mgl这意味着IPv4前缀应尽可能大。例如,网络范围10.11.3.128-10.11.51.255
可以用CIDR表示法表示为10.11.3.128/25
,然后从10.11.4.0/24
到10.11.51.0/24
使用/24前缀,而实际上那些/24
可以聚合。或者从10.11.3.128/0
到10.11.51.255/0
使用32位前缀,这实际上是IPV4最大的前缀。这就是为什么我在问。@hek2mgl在我看来IPV4网络应该有尽可能短的子网掩码。
句子是单音的。这意味着网络掩码部分应该尽可能短,即包含尽可能小的部分。好的,明白了。对不起,我的错。现在这是一个有趣的问题。。。