e6592e2b4a417630d0e0a9b617099697c1653e03
[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 # hook for library function
8 _ip2str() {
9 local var="$1" n="$2"
10 assert_uint32 "$n" || exit 1
11
12 if [ "$decimal" -ne 0 ]; then
13 export -- "$var=$n"
14 elif [ "$hexadecimal" -ne 0 ]; then
15 export -- "$var=$(printf "%x" "$n")"
16 else
17 ip2str "$@"
18 fi
19 }
20
21 usage() {
22 echo "Usage: $PROG [ -d | -x ] address/prefix [ start limit ]" >&2
23 exit 1
24 }
25
26 decimal=0
27 hexadecimal=0
28 if [ "$1" = "-d" ]; then
29 decimal=1
30 shift
31 elif [ "$1" = "-x" ]; then
32 hexadecimal=1
33 shift
34 fi
35
36 if [ $# -eq 0 ]; then
37 usage
38 fi
39
40 case "$1" in
41 */*.*)
42 str2ip ipaddr "${1%/*}" || exit 1
43 str2ip netmask "${1#*/}" || exit 1
44 shift
45 ;;
46 */*)
47 str2ip ipaddr "${1%/*}" || exit 1
48 prefix="${1#*/}"
49 assert_uint32 "$prefix" || exit 1
50 if [ "$prefix" -gt 32 ]; then
51 printf "Prefix out of range (%s)\n" "$prefix" >&2
52 exit 1
53 fi
54 netmask=$(((0xffffffff << (32 - prefix)) & 0xffffffff))
55 shift
56 ;;
57 *)
58 str2ip ipaddr "$1" || exit 1
59 str2ip netmask "$2" || exit 1
60 shift 2
61 ;;
62 esac
63
64 if [ $# -ne 0 ] && [ $# -ne 2 ]; then
65 usage
66 fi
67
68 if ! bitcount prefix "$netmask"; then
69 printf "Invalid netmask (%s)\n" "$netmask" >&2
70 exit 1
71 fi
72
73 # complement of the netmask, i.e. the hostmask
74 hostmask=$((netmask ^ 0xffffffff))
75 network=$((ipaddr & netmask))
76 broadcast=$((network | hostmask))
77
78 _ip2str IP "$ipaddr"
79 _ip2str NETMASK "$netmask"
80 _ip2str NETWORK "$network"
81
82 echo "IP=$IP"
83 echo "NETMASK=$NETMASK"
84 if [ "$prefix" -le 30 ]; then
85 _ip2str BROADCAST "$broadcast"
86 echo "BROADCAST=$BROADCAST"
87 fi
88 echo "NETWORK=$NETWORK"
89 echo "PREFIX=$prefix"
90
91 [ $# -eq 0 ] && exit 0
92
93 if [ "$prefix" -le 30 ]; then
94 lower=$((network + 1))
95 else
96 lower="$network"
97 fi
98
99 start="$1"
100 assert_uint32 "$start" || exit 1
101 start=$((network | (start & hostmask)))
102 [ "$start" -lt "$lower" ] && start="$lower"
103 [ "$start" -eq "$ipaddr" ] && start=$((start + 1))
104
105 if [ "$prefix" -le 30 ]; then
106 upper=$(((network | hostmask) - 1))
107 else
108 upper="$network"
109 fi
110
111 range="$2"
112 assert_uint32 "$range" || exit 1
113 end=$((start + range - 1))
114 [ "$end" -gt "$upper" ] && end="$upper"
115 [ "$end" -eq "$ipaddr" ] && end=$((end - 1))
116
117 if [ "$start" -gt "$end" ]; then
118 echo "network ($NETWORK/$prefix) too small" >&2
119 exit 1
120 fi
121
122 _ip2str START "$start"
123 _ip2str END "$end"
124
125 if [ "$start" -le "$ipaddr" ] && [ "$ipaddr" -le "$end" ]; then
126 echo "error: address $IP inside range $START..$END" >&2
127 exit 1
128 fi
129
130 echo "START=$START"
131 echo "END=$END"
132
133 exit 0