Find free ip
From Lolly's Wiki
Jump to navigationJump to search
#!/bin/bash
#
# $Id: find_free_ip.sh,v 1.2 2019/09/06 14:33:32 lollypop Exp $
# $Source: /var/cvs/lollypop/scripts/linux/find_free_ip.sh,v $
#
# Written in 2019 by Lars Timmann <L@rs.Timmann.de>
#
function usage () {
printf "Usage: ${0} <ip address>[/(<CIDR suffix>|<netmask>)]\n\n"
printf " This script searches a range of IP addresses for ones that have no reverse DNS.\n"
printf " Default range if no CIDR suffix or netmask is given is a class C (/24) range of 256 addresses.\n"
printf " address : This has to be a IPv4 address. Zero octets can be omittet.\n"
printf " For example 192.168 is sufficient for 192.168.0.0 .\n"
printf " CIDR suffix : This describes the nomber of bits set to 1 from left in the netmask.\n"
printf " netmask : Four octets representing the netmask.\n"
printf "\n"
}
case ${1} in
""|--help|-h)
usage
exit 1
;;
*)
input=${1}
;;
esac
case $(uname -s) in
Linux)
PING='ping -4 -c 1 -n -q -W 1 ${ip}'
;;
SunOS)
PING='ping -s -A inet -n -t 1 ${ip} 56 1'
;;
esac
IFS='/' read -ra parts <<< "${input}"
address=${parts[0]}
suffix=${parts[1]:-24}
# build binary notation from CIDR suffix
function ones2bin () {
ones=${1}
printf "%0.s1" $(seq 1 ${ones})
[ ${ones} -lt 32 ] && printf "%0.s0" $(seq 1 $[ 32 - ${ones} ])
}
function bin2ones () {
bin=${1}
ones=0
for((i=0;i<${#bin};i++))
do
bit=${bin:$i:1}
[ ${bit} -eq 0 ] && break
ones=$[ ones + 1 ]
done
echo ${ones}
}
# dezimal number to octets
# for example: 2130706689 -> 127.0.1.1
function dec2ipv4 () {
ipdec=${1}
octets=()
for((i=24;i>=0;i-=8))
do
octet=$((${ipdec} >> ${i}))
octets+=(${octet})
ipdec=$(( ${ipdec} - ( ${octet} << ${i} ) ))
done
echo $(IFS=.;echo "${octets[*]}")
}
# ipv4 to decimal
function ipv42dec () {
ipv4=$1
dec=0
IFS='.' read -ra octets <<< "${ipv4}"
for ((i=0;i<4;i++))
do
dec=$(( dec + ${octets[i]} * ( 256 ** ( 3 - i ) ) ))
done
echo ${dec}
}
# decimal to binary
function dec2bin () {
dec=$1
bin=""
for((i=${dec};i>0;i>>=1))
do
bin=$(( ${i} % 2 ))${bin}
done
echo ${bin}
}
# binary to decimal : dec = $(( 2#010001010001 ))
# binary complement
function binaryComplement () {
unset complement
binary=$1
for((i=0;i<${#binary};i++))
do
complement+=$(( ${binary:${i}:1} ^ 1 ))
done
echo $complement
}
# Add missing octets
function fillOctets () {
IFS='.' read -ra octets <<< "${1}"
for ((i=${#octets[@]};i<4;++i))
do
octets+=(0)
done
echo "$(IFS=. ; echo "${octets[*]}")"
}
if [[ ${suffix} =~ ^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$ ]]
then
suffixbin=$(dec2bin $(ipv42dec $(fillOctets ${suffix})))
else
suffixbin=$(ones2bin ${suffix})
fi
address=$(fillOctets ${address})
firstipdec=$(( ( $(ipv42dec ${address}) & 2#${suffixbin} ) ))
network=$(dec2ipv4 ${firstipdec})
lastipdec=$(( ( $(ipv42dec ${address}) & 2#${suffixbin} ) | 2#$(binaryComplement ${suffixbin}) ))
broadcast=$(dec2ipv4 ${lastipdec})
netmask=$(dec2ipv4 $(( 2#${suffixbin} )) )
printf "Your request:\t${address}/$(bin2ones ${suffixbin})\nNetwork:\t${network}\nBroadcast:\t${broadcast}\nNetmask:\t${netmask}\nSearching in:\t${network}-${broadcast}\n"
printf "%0.s-" $(seq 1 80) ; echo
count=1
bool=( yes no )
for((i=${firstipdec};i<=${lastipdec};i++))
do
ip=$(dec2ipv4 ${i})
info=$(getent hosts ${ip})
if [ "_${info}_" == "__" ]
then
eval ${PING} ${ip} >/dev/null 2>&1 ; pingable=$?
case ${ip} in
${network})
remark="This is the network IP."
;;
${broadcast})
remark="This is the network IP."
;;
*)
remark=""
;;
esac
printf "%s\tfrei\t%d\t( got a pong: %s )\t%s\n" "${ip}" "${count}" "${bool[${pingable}]}" "${remark}"
count=$[ ${count} + 1 ]
else
printf "%s\n" "${info}"
count=1
fi
done