| #!/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 "error: address $IP inside range $START..$END" >&2 | 
 |     exit 1 | 
 | fi | 
 |  | 
 | echo "START=$START" | 
 | echo "END=$END" | 
 |  | 
 | exit 0 |