Skip to content

Instantly share code, notes, and snippets.

@ar45
Created February 19, 2017 19:52
Show Gist options
  • Save ar45/c0541cd7b249dbec374dae5963c49b6d to your computer and use it in GitHub Desktop.
Save ar45/c0541cd7b249dbec374dae5963c49b6d to your computer and use it in GitHub Desktop.
Pure shell IPv4 subnet calculations
#!/bin/sh
exit_error()
{
echo "$1" >&2 && exit 1
}
valid_ip()
{
local ip=$1
local stat=0
echo $ip | grep -qE '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' || stat=1
if [ $stat -eq 0 ]; then
OIFS=$IFS
IFS='.'
set -- $ip
IFS=$OIFS
[ $1 -le 255 ] && [ $2 -le 255 ] \
&& [ $3 -le 255 ] && [ $4 -le 255 ] || stat=1
fi
return $stat
}
netmask2cidr ()
{
# Assumes there's no "255." after a non-255 byte in the mask
local x=${1##*255.}
set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) ${x%%.*}
x=${1%%$3*}
echo $(( $2 + (${#x}/4) ))
}
cidr2netmask ()
{
# Number of args to shift, 255..255, first non-255 byte, zeroes
set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0
[ $1 -gt 1 ] && shift $1 || shift
echo ${1-0}.${2-0}.${3-0}.${4-0}
}
_addr_helper ()
{
local ip cidr mask gateway
ip=${1%%/*}
cidr=${1##*/}
# Convert it to mask format
mask=`cidr2netmask $cidr 2>/dev/null` || true
mask=${mask:-$cidr}
OLDIFS=$IFS
IFS=.
set -- $mask $ip
local netid bcast gateway
netid=$(( $1 & $5 )).$(( $2 & $6 )).$(( $3 & $7 )).$(( $4 & $8 ))
set -- $mask $netid
bcast=$(( $5 + 255 - $1 )).$(( $6 + 255 - $2 )).$(( $7 + 255 - $3 )).$(( $8 + 255 - $4 ))
set -- $mask $netid $bcast
IFS=$OLDIFS
local min_host=$(( $8 + 1 ))
if [ $min_host -lt ${12} ]; then
gateway=$5.$6.$7.$min_host
fi
echo "$netid"
echo "$bcast"
echo "$gateway"
}
guess_default_gateway()
{
set -- `_addr_helper $@`
echo $3
}
broadcast_addr()
{
set -- `_addr_helper $@`
echo $2
}
network_addr()
{
set -- `_addr_helper $@`
echo $1
}
case $1 in
valid_ip)
valid_ip $2
;;
gateway)
guess_default_gateway $2
;;
broadcast)
broadcast_addr $2
;;
netmask)
cidr2netmask $2
;;
network)
network_addr $2
;;
cidr)
netmask2cidr $2
;;
*)
echo "Invalid command!" >&2 && exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment