Aqui estão alguns bits para você. Primeiro, um script no Bash, então não é muito eficiente. Não faz exatamente o que você quer, porque só verifica um par de sub-redes e relata a sobreposição. Abaixo do script, seguem alguns comandos aproximados do shell, embora o resultado não seja apresentado na forma desejada. Então você precisa integrar e ajustar todo o grupo às suas necessidades, ou tratá-los como um esboço que ilustra a lógica.
#!/usr/bin/env bash
subnet1="$1"
subnet2="$2"
# calculate min and max of subnet1
# calculate min and max of subnet2
# find the common range (check_overlap)
# print it if there is one
read_range () {
IFS=/ read ip mask <<<"$1"
IFS=. read -a octets <<< "$ip";
set -- "${octets[@]}";
min_ip=$(($1*256*256*256 + $2*256*256 + $3*256 + $4));
host=$((32-mask))
max_ip=$(($min_ip+(2**host)-1))
printf "%d-%d\n" "$min_ip" "$max_ip"
}
check_overlap () {
IFS=- read min1 max1 <<<"$1";
IFS=- read min2 max2 <<<"$2";
if [ "$max1" -lt "$min2" ] || [ "$max2" -lt "$min1" ]; then return; fi
[ "$max1" -ge "$max2" ] && max="$max2" || max="$max1"
[ "$min1" -le "$min2" ] && min="$min2" || min="$min1"
printf "%s-%s\n" "$(to_octets $min)" "$(to_octets $max)"
}
to_octets () {
first=$(($1>>24))
second=$((($1&(256*256*255))>>16))
third=$((($1&(256*255))>>8))
fourth=$(($1&255))
printf "%d.%d.%d.%d\n" "$first" "$second" "$third" "$fourth"
}
range1="$(read_range $subnet1)"
range2="$(read_range $subnet2)"
overlap="$(check_overlap $range1 $range2)"
[ -n "$overlap" ] && echo "Overlap $overlap of $subnet1 and $subnet2"
O uso e o resultado são estes:
$ ./overlap.bash 194.33.26.0/26 194.33.24.0/22
Overlap 194.33.26.0-194.33.26.63 of 194.33.26.0/26 and 194.33.24.0/22
Agora, considerando que sua primeira lista de sub-redes está no arquivo list
e as sub-redes a serem verificadas estão no arquivo to_check
, você pode usar o script para encontrar todas as sobreposições.
$ while read l; do list+=("$l"); done < list
$ while read t; do to_check+=("$t"); done < to_check
$ for i in "${list[@]}"; do for j in "${to_check[@]}"; do \
./overlap.bash "$i" "$j"; done; done
Este é o resultado:
Overlap 194.33.26.0-194.33.26.63 of 194.33.24.0/22 and 194.33.26.0/26
Overlap 188.115.195.88-188.115.195.95 of 188.115.195.80/28 and 188.115.195.88/29
Overlap 41.202.219.32-41.202.219.63 of 41.202.219.32/27 and 41.202.219.0/24
Overlap 41.202.219.128-41.202.219.135 of 41.202.219.128/29 and 41.202.219.0/24
Overlap 41.202.219.208-41.202.219.223 of 41.202.219.208/28 and 41.202.219.0/24
Overlap 41.202.219.136-41.202.219.143 of 41.202.219.136/29 and 41.202.219.0/24
Overlap 197.157.209.128-197.157.209.143 of 197.157.209.0/24 and 197.157.209.128/28
Como você pode ver, 41.202.219.0/24
tem quatro sobreposições, ao contrário das suas expectativas em sua pergunta.
Para obter apenas as sub-redes sem sobreposições na primeira lista, o script seria muito mais curto. Você não precisa da função to_octets
e a função check_overlap
já pode dar resultado nesta linha:
if [ "$max1" -lt "$min2" ] || [ "$max2" -lt "$min1" ]; then return; fi
Além disso, as duas últimas linhas podem ser alteradas (com a última completamente removida).
Quanto à lógica de integração, há espaço para o curto-circuito da verificação em relação à primeira lista, pois nem todas as combinações precisam ser verificadas. Um negativo é suficiente.