forked from Openwrt/openwrt
The call to 'ipcalc' is used in 'dnsmasq' init script to create the
configuration. If the 'ipaddr' is in the configured range then 'ipcalc' exited
with an error whereby the START/STOP variables are unavailable.
This behaviour has changed during 'ipcalc' refactoring and now leads to a
problem when starting 'dnsmasq' if the 'ipaddr' is inside this range. To
restore the old behaviour, only a warning is issued as before and the
required variables for the 'dnsmasq' are still set.
Fixes: 854739b32c
(base-files: ipcalc.sh: Rewrite in pure shell)
Signed-off-by: Florian Eckert <fe@dev.tdt.de>
Link: https://github.com/openwrt/openwrt/pull/18641
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
143 lines
3.0 KiB
Bash
Executable File
143 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 "warning: address $IP inside range $START..$END" >&2
|
|
fi
|
|
|
|
echo "START=$START"
|
|
echo "END=$END"
|
|
|
|
exit 0
|