| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- #!/bin/sh
- . /lib/functions/ipv4.sh
- PROG="$(basename "$0")"
- # wrapper to convert an integer to an address, unless we're using
- # decimal output format.
- # hook for library function
- _ip2str() {
- local var="$1" n="$2"
- assert_uint32 "$n" || exit 1
- if [ "$decimal" -ne 0 ]; then
- export -- "$var=$n"
- elif [ "$hexadecimal" -ne 0 ]; then
- export -- "$var=$(printf "%x" "$n")"
- else
- ip2str "$@"
- fi
- }
- usage() {
- echo "Usage: $PROG [ -d | -x ] address/prefix [ start limit ]" >&2
- exit 1
- }
- decimal=0
- hexadecimal=0
- if [ "$1" = "-d" ]; then
- decimal=1
- shift
- elif [ "$1" = "-x" ]; then
- hexadecimal=1
- shift
- fi
- if [ $# -eq 0 ]; then
- usage
- fi
- case "$1" in
- */*.*)
- # data is n.n.n.n/m.m.m.m format, like on a Cisco router
- str2ip ipaddr "${1%/*}" || exit 1
- str2ip netmask "${1#*/}" || exit 1
- netmask2prefix prefix "$netmask" || exit 1
- shift
- ;;
- */*)
- # more modern prefix notation of n.n.n.n/p
- str2ip ipaddr "${1%/*}" || exit 1
- prefix="${1#*/}"
- assert_uint32 "$prefix" || exit 1
- if [ "$prefix" -gt 32 ]; then
- printf "Prefix out of range (%s)\n" "$prefix" >&2
- exit 1
- fi
- prefix2netmask netmask "$prefix" || exit 1
- shift
- ;;
- *)
- # address and netmask as two separate arguments
- str2ip ipaddr "$1" || exit 1
- str2ip netmask "$2" || exit 1
- netmask2prefix prefix "$netmask" || exit 1
- shift 2
- ;;
- esac
- # we either have no arguments left, or we have a range start and length
- if [ $# -ne 0 ] && [ $# -ne 2 ]; then
- usage
- fi
- # complement of the netmask, i.e. the hostmask
- hostmask=$((netmask ^ 0xffffffff))
- network=$((ipaddr & netmask))
- broadcast=$((network | hostmask))
- count=$((hostmask + 1))
- _ip2str IP "$ipaddr"
- _ip2str NETMASK "$netmask"
- _ip2str NETWORK "$network"
- echo "IP=$IP"
- echo "NETMASK=$NETMASK"
- # don't include this-network or broadcast addresses
- if [ "$prefix" -le 30 ]; then
- _ip2str BROADCAST "$broadcast"
- echo "BROADCAST=$BROADCAST"
- fi
- echo "NETWORK=$NETWORK"
- echo "PREFIX=$prefix"
- echo "COUNT=$count"
- # if there's no range, we're done
- [ $# -eq 0 ] && exit 0
- [ -z "$1$2" ] && exit 0
- if [ "$prefix" -le 30 ]; then
- lower=$((network + 1))
- else
- lower="$network"
- fi
- start="$1"
- assert_uint32 "$start" || exit 1
- start=$((network | (start & hostmask)))
- [ "$start" -lt "$lower" ] && start="$lower"
- [ "$start" -eq "$ipaddr" ] && start=$((start + 1))
- if [ "$prefix" -le 30 ]; then
- upper=$(((network | hostmask) - 1))
- elif [ "$prefix" -eq 31 ]; then
- upper=$((network | hostmask))
- else
- upper="$network"
- fi
- range="$2"
- assert_uint32 "$range" || exit 1
- end=$((start + range - 1))
- [ "$end" -gt "$upper" ] && end="$upper"
- [ "$end" -eq "$ipaddr" ] && end=$((end - 1))
- if [ "$start" -gt "$end" ]; then
- echo "network ($NETWORK/$prefix) too small" >&2
- exit 1
- fi
- _ip2str START "$start"
- _ip2str END "$end"
- if [ "$start" -le "$ipaddr" ] && [ "$ipaddr" -le "$end" ]; then
- echo "warning: address $IP inside range $START..$END" >&2
- fi
- echo "START=$START"
- echo "END=$END"
- exit 0
|