Tôi thực sự thích vấn đề này, tôi đã xem qua đêm qua và quyết định cho nó một shot. Tại thời điểm này tôi có một bằng chứng về kịch bản shell script làm việc.
Disclaimer:
- Đây là một bằng chứng của khái niệm chỉ
- tôi loại được tái phát minh ra bánh xe ở đây vì tôi không sử dụng bất kỳ/thư viện TCP IP
- tôi đã không thực hiện xác nhận đầu vào
- Mã này có thể nhanh hơn nhiều nếu được viết bằng ngôn ngữ lập trình thay vì bash, mặc dù phạm vi mạng specif này không quá chậm
Một điều đáng nói là sự hiểu biết của tôi về:
IPv4 networks should have as short subnet-mask as possible.
là chúng ta nên cố gắng từ bit dành cho mạng lên đến cidr lớn nhất cung cấp, trong trường hợp này .
OK, chúng ta hãy xem các kịch bản trong hành động:
[[email protected] 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
Dưới mã:
#! /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
Sửa Nó có thể là một ý tưởng tốt để giải thích những gì các biến là:
- snet_cidr: bắt đầu lưới trong ký hiệu cidr
- enet_cidr: cuối ròng trong cidr
- snet_dec: bắt đầu ròng trong thập phân
- enet_dec: cuối ròng trong thập phân
- sbc_ip: bắt đầu phát sóng ip
- ebc_ip: cuối phát sóng ip
- sbc_dec: bắt đầu phát sóng ip
- ebc_dec: cuối phát sóng ip
Và bất cứ nơi nào bạn nhìn thấy tnet hoặc tbc là net tạm thời, tạm thời quảng bá, tạm thời vì nó insid e vòng lặp.
Giải thích 'Mạng IPv4 phải có mặt nạ mạng con ngắn càng tốt.' – hek2mgl
@ hek2mgl Điều này có nghĩa là tiền tố IPv4 phải càng lớn càng tốt. Ví dụ phạm vi mạng '10.11.3.128-10.11.51.255' có thể được trình bày trong ký hiệu CIDR với' 10.11.3.128/25' và sau đó từ '10.11.4.0/24' thành' 10.11.51.0/24' bằng cách sử dụng/24 tiền tố trong khi thực sự những '/ 24' đó có thể được tổng hợp. – Martin
hoặc từ '10.11.3.128/0' đến' 10.11.51.255/0' bằng tiền tố 32 bit thực sự là tiền tố lớn nhất có thể cho IPV4 .. đó là lý do tôi hỏi .. – hek2mgl