0037100e12
If we're being paranoid and quote all the arguments to ipcalc.sh, it's possible to pass in empty start and range arguments. This should be handled the same as their being absent. Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com> Link: https://github.com/openwrt/openwrt/pull/15946 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
144 lines
3.0 KiB
Bash
Executable File
144 lines
3.0 KiB
Bash
Executable File
#!/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
|