The script uses ipcalc for getting the network values from the network CIDR. It is able to get values for Network, Netmask, Address, Broadcast, HostMin, HostMax and the number of host addresses in the network.
Unit conversion from decimal to binary is done using bc. BASH is able to perform bitwise operations for AND, OR and XOR. The BASH operation of shift is also used in this script.
As always you can download this code along with all the others from this blog using GitLab.com Linux Code Snippets
#!/bin/bash # Given the network CIDR and two static IPs, calculate the lower and upper IPs for the DHCP pool. # This script uses ipcalc that may need to be installed. # https://stackoverflow.com/questions/40667382/how-to-perform-bitwise-operations-on-hexadecimal-numbers-in-bash # https://unix.stackexchange.com/questions/223338/convert-a-value-into-a-binary-number-in-a-shell-script # echo "obase=2; 34" | bc # https://unix.stackexchange.com/questions/65280/binary-to-hexadecimal-and-decimal-in-a-shell-script # echo $((2#101010101)) # printf "%x\n" "$((2#101010101))" # echo $((0xf8 ^ 0x1f)) XOR # echo $((0xf8 & 0x1f)) AND # echo $((0xf8 | 0x1f)) OR # echo $((0xf8 >> 3)) shift right 3 bits # echo $((0xf8 << 4)) shift left 3 bits function AddOne { IPCI= [ "$1" = "NS_ADDR" ] && IPCI=$(( NS_ADDR_INT + 1 )) [ "$1" = "GW_ADDR" ] && IPCI=$(( GW_ADDR_INT + 1 )) IPCB=$(echo "obase=2; $IPCI" | bc) Bin2Addr $(( 2#$B_ADDRESS_MASK | 2#$IPCB )) } function SubOne { IPCI= [ "$1" = "NS_ADDR" ] && IPCI=$(( NS_ADDR_INT - 1 )) [ "$1" = "GW_ADDR" ] && IPCI=$(( GW_ADDR_INT - 1 )) IPCB=$(echo "obase=2; $IPCI" | bc) Bin2Addr $(( 2#$B_ADDRESS_MASK | 2#$IPCB )) } function Bin2Addr { GA=$(echo "obase=2; $1" | bc) D_BLOCK=$(( 2#$GA & 2#11111111 )) GA=$( echo "obase=2; $(( 2#$GA >> 8 ))" | bc) C_BLOCK=$(( 2#$GA & 2#11111111 )) GA=$( echo "obase=2; $(( 2#$GA >> 8 ))" | bc) B_BLOCK=$(( 2#$GA & 2#11111111 )) GA=$( echo "obase=2; $(( 2#$GA >> 8 ))" | bc) A_BLOCK=$(( 2#$GA & 2#11111111 )) echo "built IP = '${A_BLOCK}.${B_BLOCK}.${C_BLOCK}.${D_BLOCK}'" } function NetCalcs { echo echo -------------------------------------------------- # set -x echo "NAMESERVER_IP=$NAMESERVER_IP, GATEWAY_IP=$GATEWAY_IP" NAMESERVER_NET=$(ipcalc -nb ${NETWORK_CIDR} | grep ^Network: | awk '{print $2}' ) #echo "NAMESERVER_NET=$NAMESERVER_NET" NETWORK_MASK=$(ipcalc -nb ${NETWORK_CIDR} | grep ^Netmask: | awk '{print $2}' ) #echo "NETWORK_MASK=$NETWORK_MASK" B_ADDRESS_MASK=$(ipcalc -n ${NETWORK_CIDR} | grep ^Address: | sed -e 's/\.//g' | awk '{print $(NF-1)$NF}' ) #echo "Binary ADDRESS_MASK=$B_ADDRESS_MASK" NETWORK_BROADCAST=$(ipcalc -nb ${NETWORK_CIDR} | grep ^Broadcast: | awk '{print $2}' ) #echo "NETWORK_BROADCAST=$NETWORK_BROADCAST" NET_MIN_IP=$(ipcalc -nb ${NETWORK_CIDR} | grep ^HostMin: | awk '{print $2}' ) #echo "NET_MIN_IP=$NET_MIN_IP" NET_MAX_IP=$(ipcalc -nb ${NETWORK_CIDR} | grep ^HostMax: | awk '{print $2}' ) #echo "NET_MAX_IP=$NET_MAX_IP" NET_MIN_BIN=$(ipcalc -n ${NETWORK_CIDR} | grep ^HostMin: | sed -e 's/\.//g' | awk '{print $NF}') #echo "NET_MIN_BIN=$NET_MIN_BIN" NET_MAX_BIN=$(ipcalc -n ${NETWORK_CIDR} | grep ^HostMax: | sed -e 's/\.//g' | awk '{print $NF}') #echo "NET_MAX_BIN=$NET_MAX_BIN" NS_ADDR_BIN=$(ipcalc -n ${NAMESERVER_IP}/${NETWORK_CIDR##*/} | grep ^Address: | sed -e 's/\.//g' | awk '{print $NF}') NS_ADDR_INT=$(( 2#$NS_ADDR_BIN )) #echo "NS_ADDR_BIN=$NS_ADDR_BIN" GW_ADDR_BIN=$(ipcalc -n ${GATEWAY_IP}/${NETWORK_CIDR##*/} | grep ^Address: | sed -e 's/\.//g' | awk '{print $NF}') GW_ADDR_INT=$(( 2#$GW_ADDR_BIN )) #echo "GW_ADDR_BIN=$GW_ADDR_BIN" read LOWEST HIGHEST <<< $( printf "%d " $(printf "%d\n" $(( 2#$GW_ADDR_BIN )) $(( 2#$NS_ADDR_BIN ))|sort -n)) LOWCOUNT=$(( LOWEST - $NET_MIN_BIN )) #echo "LOWCOUNT=$LOWCOUNT" # Mid IP pool size MIDCOUNT=$(( HIGHEST - LOWEST )) #echo "MIDCOUNT=$MIDCOUNT" # Upper IP pool size HICOUNT=$(( 2#$NET_MAX_BIN - HIGHEST )) #echo "HICOUNT=$HICOUNT" read JUNK LOWNET JUNK HIGHNET JUNK <<< $( echo $( (echo "$GW_ADDR_INT GW_ADDR"; echo "$NS_ADDR_INT NS_ADDR"; ) | sort -n) ) read JUNK POOL JUNK <<< $( (echo "$LOWCOUNT LOWCOUNT"; echo "$MIDCOUNT MIDCOUNT"; echo "$HICOUNT HICOUNT";) | sort -nr) #echo "NAMESER_IP=$NAMESERVER_IP GATEWAY_IP=$GATEWAY_IP LOWNET=$LOWNET HIGHNET=$HIGHNET POOL=$POOL" case $POOL in LOWCOUNT) echo "From $NET_MIN_IP to $(SubOne $LOWNET)";; MIDCOUNT) echo "From $(AddOne $LOWNET) to $(SubOne $HIGHNET)";; HICOUNT) echo "From $(AddOne $HIGHNET) to $NET_MAX_IP";; esac } clear NETWORK_CIDR="172.16.0.0/20" echo "NETWORK_CIDR=$NETWORK_CIDR" NAMESERVER_IP="172.16.1.2" GATEWAY_IP="172.16.1.1" NetCalcs NAMESERVER_IP="172.16.14.200" GATEWAY_IP="172.16.15.9" NetCalcs NAMESERVER_IP="172.16.1.22" GATEWAY_IP="172.16.1.22" NetCalcs NETWORK_CIDR="192.168.1.0/24" echo "NETWORK_CIDR=$NETWORK_CIDR" NAMESERVER_IP="192.168.1.2" GATEWAY_IP="192.168.1.1" NetCalcs NAMESERVER_IP="192.168.1.120" GATEWAY_IP="192.168.1.121" NetCalcs NAMESERVER_IP="192.168.1.2" GATEWAY_IP="192.168.1.1" NetCalcs