Mi piace molto questo problema, ho dato un'occhiata ieri sera e ho deciso di provarlo. A questo punto ho un proof of concept script script che funziona.
responsabilità:
- Questa è una prova di concetto solo
- I tipi di reinventato la ruota qui come non ho usato qualsiasi libreria TCP/IP
- non ha attuato input validation
- Questo codice potrebbe essere molto più veloce se scritto in un linguaggio di programmazione piuttosto che bash, sebbene per questo specifico intervallo di rete non sia così lento
Un altro aspetto degno di nota è che la mia comprensione:
IPv4 networks should have as short subnet-mask as possible.
è che dovremmo cercare da bit riservati collegare in rete fino al più grande cidr fornito, in questo caso .
OK, vediamo lo script in azione:
[[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
sotto il codice:
#! /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
Modifica E 'probabilmente una buona idea per spiegare quali siano tali variabili sono:
- snet_cidr: avvio netto in notazione Cidr
- enet_cidr: Rete fine a cidr
- snet_dec: net start in decimali
- enet_dec: netta di fine in decimali
- sbc_ip: Inizia trasmissione ip
- ebc_ip: fine trasmissione ip
- sbc_dec: inizio trasmissione ip
- ebc_dec: fine trasmissione ip
e dovunque si vede TNET o da confermare è al netto di temperatura, temperatura trasmissione, temperatura perché è insid e il ciclo.
Spiega 'Le reti IPv4 dovrebbero avere una maschera di sottorete più corta possibile. – hek2mgl
@ hek2mgl Ciò significa che i prefissi IPv4 dovrebbero essere il più grandi possibile. Per esempio l'intervallo di rete '10.11.3.128-10.11.51.255' può essere presentato in notazione CIDR con' 10.11.3.128/25' e quindi da '10.11.4.0/24' a' 10.11.51.0/24' usando/24 prefissi mentre in realtà quelli '/ 24' possono essere aggregati. – Martin
o da '10.11.3.128/0' a' 10.11.51.255/0' usando un prefisso di 32 bit che è in realtà il più grande prefisso possibile per IPV4 .. è per questo che sto chiedendo .. – hek2mgl