0bd6edd07aa0946c84f4ee756e097aed506d0552
[openwrt/openwrt.git] / package / base-files / files / bin / ipcalc.sh
1 #!/bin/sh
2
3 . /lib/functions/ipv4.sh
4
5 PROG="$(basename "$0")"
6
7 usage() {
8 echo "Usage: $PROG address/prefix [ start limit ]" >&2
9 exit 1
10 }
11
12 if [ $# -eq 0 ]; then
13 usage
14 fi
15
16 case "$1" in
17 */*.*)
18 str2ip ipaddr "${1%/*}" || exit 1
19 str2ip netmask "${1#*/}" || exit 1
20 shift
21 ;;
22 */*)
23 str2ip ipaddr "${1%/*}" || exit 1
24 prefix="${1#*/}"
25 assert_uint32 "$prefix" || exit 1
26 if [ "$prefix" -gt 32 ]; then
27 printf "Prefix out of range (%s)\n" "$prefix" >&2
28 exit 1
29 fi
30 netmask=$(((0xffffffff << (32 - prefix)) & 0xffffffff))
31 shift
32 ;;
33 *)
34 str2ip ipaddr "$1" || exit 1
35 str2ip netmask "$2" || exit 1
36 shift 2
37 ;;
38 esac
39
40 if [ $# -ne 0 ] && [ $# -ne 2 ]; then
41 usage
42 fi
43
44 if ! bitcount prefix "$netmask"; then
45 printf "Invalid netmask (%s)\n" "$netmask" >&2
46 exit 1
47 fi
48
49 # complement of the netmask, i.e. the hostmask
50 hostmask=$((netmask ^ 0xffffffff))
51 network=$((ipaddr & netmask))
52 broadcast=$((network | hostmask))
53
54 ip2str IP "$ipaddr"
55 ip2str NETMASK "$netmask"
56 ip2str NETWORK "$network"
57
58 echo "IP=$IP"
59 echo "NETMASK=$NETMASK"
60 if [ "$prefix" -le 30 ]; then
61 ip2str BROADCAST "$broadcast"
62 echo "BROADCAST=$BROADCAST"
63 fi
64 echo "NETWORK=$NETWORK"
65 echo "PREFIX=$prefix"
66
67 [ $# -eq 0 ] && exit 0
68
69 if [ "$prefix" -le 30 ]; then
70 lower=$((network + 1))
71 else
72 lower="$network"
73 fi
74
75 start="$1"
76 assert_uint32 "$start" || exit 1
77 start=$((network | (start & hostmask)))
78 [ "$start" -lt "$lower" ] && start="$lower"
79 [ "$start" -eq "$ipaddr" ] && start=$((start + 1))
80
81 if [ "$prefix" -le 30 ]; then
82 upper=$(((network | hostmask) - 1))
83 else
84 upper="$network"
85 fi
86
87 range="$2"
88 assert_uint32 "$range" || exit 1
89 end=$((start + range - 1))
90 [ "$end" -gt "$upper" ] && end="$upper"
91 [ "$end" -eq "$ipaddr" ] && end=$((end - 1))
92
93 if [ "$start" -gt "$end" ]; then
94 echo "network ($NETWORK/$prefix) too small" >&2
95 exit 1
96 fi
97
98 ip2str START "$start"
99 ip2str END "$end"
100
101 if [ "$start" -le "$ipaddr" ] && [ "$ipaddr" -le "$end" ]; then
102 echo "error: address $IP inside range $START..$END" >&2
103 exit 1
104 fi
105
106 echo "START=$START"
107 echo "END=$END"
108
109 exit 0