]> git.ipfire.org Git - people/stevee/network.git/blame - src/functions/functions.ipv4
Replace ipcalc by inetcalc
[people/stevee/network.git] / src / functions / functions.ipv4
CommitLineData
05c234a8
MT
1#!/bin/bash
2###############################################################################
3# #
4# IPFire.org - A linux based firewall #
5# Copyright (C) 2010 Michael Tremer & Christian Schmidt #
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
21
e617226b
MT
22IP_SUPPORTED_PROTOCOLS="${IP_SUPPORTED_PROTOCOLS} ipv4"
23
1c6a4e30 24ipv4_is_valid() {
13a6e69f 25 inetcalc -4 -c $@ && return ${EXIT_OK} || return ${EXIT_ERROR}
05c234a8
MT
26}
27
1c6a4e30 28ipv4_prefix_is_valid() {
cb965348 29 local prefix=${1}
ab70371d
MT
30
31 isset prefix || return ${EXIT_FALSE}
cb965348
MT
32
33 [ ${prefix} -le 0 ] && return ${EXIT_FALSE}
34 [ ${prefix} -gt 32 ] && return ${EXIT_FALSE}
35
36 return ${EXIT_TRUE}
37}
38
1c6a4e30 39ipv4_netmask_is_valid() {
ccbc0dd4
MT
40 local netmask="${1}"
41
42 # XXX this check could be much better by checking
43 # if the netmask only contains leading ones
44
45 ipv4_is_valid "${netmask}"
46}
47
1c6a4e30 48ipv4_detect_duplicate() {
05c234a8
MT
49 local device=${1}
50 local address=${2}
51
52 assert isset address
53 assert isset device
54 assert device_exists ${device}
55
785afa13
MT
56 # Don't check on PPP devices.
57 device_is_ppp ${device} && return ${EXIT_ERROR}
58
05c234a8
MT
59 if ! arping -q -c 2 -w 3 -D -I ${device} ${address}; then
60 log DEBUG "Detected duplicate address '${address}' on device '${device}'."
9eebfc55 61 return ${EXIT_OK}
05c234a8
MT
62 fi
63
9eebfc55 64 return ${EXIT_ERROR}
05c234a8
MT
65}
66
1c6a4e30 67ipv4_update_neighbours() {
05c234a8
MT
68 local device=${1}
69 local address=${2}
70
785afa13
MT
71 # Don't do anything on PPP devices.
72 device_is_ppp ${device} && return ${EXIT_OK}
73
05c234a8
MT
74 arping -q -A -c 1 -I ${device} ${address}
75 ( sleep 2; arping -q -U -c 1 -I ${device} ${address} ) >/dev/null 2>&1 </dev/null &
76}
d5bace8d 77
13a6e69f
MT
78ipv4_calculate_prefix() {
79 assert [ $# -eq 2 ]
ab70371d 80
13a6e69f
MT
81 local address="${1}"
82 local broadcast="${2}"
ab70371d 83
13a6e69f 84 inetcalc -4 -p "${address}" "${broadcast}"
ab70371d
MT
85}
86
1c6a4e30 87ipv4_flush_device() {
e9ea243e
MT
88 #
89 # Flushes all routes, addresses from the device
90 # and clears the ARP cache.
91 #
92
93 local device=${1}
94 assert isset device
95
96 ip -4 addr flush dev ${device} >/dev/null 2>&1
97 ip -4 route flush dev ${device} >/dev/null 2>&1
98 ip -4 neigh flush dev ${device} >/dev/null 2>&1
99
100 return 0
c7b93f70 101}
6f49dbac 102
1c6a4e30 103ipv4_prefix2netmask() {
13a6e69f 104 local prefix="${1}"
785afa13
MT
105
106 case "${prefix}" in
13a6e69f
MT
107 32)
108 echo "255.255.255.255"
109 ;;
110 31)
111 echo "255.255.255.254"
112 ;;
113 30)
114 echo "255.255.255.252"
115 ;;
116 29)
117 echo "255.255.255.248"
118 ;;
119 28)
120 echo "255.255.255.240"
121 ;;
122 27)
123 echo "255.255.255.224"
124 ;;
125 26)
126 echo "255.255.255.192"
127 ;;
128 25)
129 echo "255.255.255.128"
130 ;;
785afa13
MT
131 24)
132 echo "255.255.255.0"
133 ;;
13a6e69f
MT
134 23)
135 echo "255.255.254.0"
136 ;;
137 22)
138 echo "255.255.252.0"
139 ;;
140 21)
141 echo "255.255.248.0"
142 ;;
143 20)
144 echo "255.255.240.0"
145 ;;
146 19)
147 echo "255.255.224.0"
148 ;;
149 18)
150 echo "255.255.192.0"
151 ;;
152 17)
153 echo "255.255.128.0"
154 ;;
155 16)
156 echo "255.255.0.0"
157 ;;
158 15)
159 echo "255.254.0.0"
160 ;;
161 14)
162 echo "255.252.0.0"
163 ;;
164 13)
165 echo "255.248.0.0"
166 ;;
167 12)
168 echo "255.240.0.0"
169 ;;
170 11)
171 echo "255.224.0.0"
172 ;;
173 10)
174 echo "255.192.0.0"
175 ;;
176 9)
177 echo "255.128.0.0"
178 ;;
179 8)
180 echo "255.0.0.0"
181 ;;
182 7)
183 echo "254.0.0.0"
184 ;;
185 6)
186 echo "252.0.0.0"
187 ;;
188 5)
189 echo "248.0.0.0"
190 ;;
191 4)
192 echo "240.0.0.0"
193 ;;
194 3)
195 echo "224.0.0.0"
196 ;;
197 2)
198 echo "192.0.0.0"
199 ;;
200 1)
201 echo "128.0.0.0"
202 ;;
203 0)
204 echo "0.0.0.0"
205 ;;
785afa13 206 *)
13a6e69f 207 return ${EXIT_ERROR}
785afa13
MT
208 ;;
209 esac
13a6e69f
MT
210
211 return ${EXIT_OK}
e9ea243e 212}
999d659b 213
1c6a4e30 214ipv4_netmask2prefix() {
ccbc0dd4
MT
215 local netmask="${1}"
216 assert isset netmask
217
218 local mask=0
219
220 local field
221 for field in ${netmask//\./ }; do
222 mask=$(( $(( ${mask} << 8 )) | ${field} ))
223 done
224
225 local cidr=0
226 local x="$(( 128 << 24 ))" # 0x80000000
227
228 while [ $(( ${x} & ${mask} )) -ne 0 ]; do
229 [ ${mask} -eq ${x} ] && mask=0 || mask=$(( ${mask} << 1 ))
230 cidr=$(( ${cidr} + 1 ))
231 done
232
233 assert [ $(( ${mask} & 2147483647 )) -eq 0 ]
234
235 print "${cidr}"
236}
237
1c6a4e30 238ipv4_get_network() {
13a6e69f 239 ip_get_network $@
999d659b
MT
240}
241
1c6a4e30 242ipv4_get_broadcast() {
13a6e69f 243 inetcalc -4 -b $@ && return ${EXIT_OK} || return ${EXIT_ERROR}
999d659b
MT
244}
245
1c6a4e30 246ipv4_encode() {
999d659b
MT
247 local addr=${1}
248 local int=0
249
250 local field
251 for field in ${addr//./ }; do
252 int=$(( $(( ${int} << 8 )) | ${field} ))
253 done
254
255 print "${int}"
256}
257
1c6a4e30 258ipv4_decode() {
999d659b
MT
259 local int=${1}
260
261 local addr=$(( ${int} & 255 ))
262
263 local i
264 for i in 1 2 3; do
265 int=$(( ${int} >> 8 ))
266 addr="$(( ${int} & 255 )).${addr}"
267 done
268
269 print "${addr}"
270}
271
1c6a4e30 272ipv4_addr_eq() {
ab70371d
MT
273 local addr1=${1}
274 assert isset addr1
275
276 local addr2=${2}
277 assert isset addr2
278
279 [[ "${addr1}" = "${addr2}" ]] \
280 && return ${EXIT_TRUE} || return ${EXIT_FALSE}
281}
282
1c6a4e30 283ipv4_addr_gt() {
ab70371d
MT
284 local addr1=${1}
285 assert isset addr1
286
287 local addr2=${2}
288 assert isset addr2
289
290 local addr
291 for addr in addr1 addr2; do
292 printf -v ${addr} "%s" "$(ip_encode ${!addr})"
293 done
294
295 [[ ${addr1} -gt ${addr2} ]] \
296 && return ${EXIT_TRUE} || return ${EXIT_FALSE}
297}
298
1c6a4e30 299ipv4_range() {
999d659b
MT
300 local range=${1}
301
302 local first=${1%-*}
303 local last=${1#*-}
304
305 _ipv4_range "$(ipv4_encode ${first})" "$(ipv4_encode ${last})"
306}
307
1c6a4e30 308_ipv4_range() {
999d659b
MT
309 local first=${1}
310 local last=${2}
311
312 if [ ${first} -gt ${last} ]; then
313 local range="$(ipv4_decode ${first})-$(ipv4_decode ${last})"
314
315 error "Invalid IPv4 address range: ${range}"
316 return ${EXIT_ERROR}
317 fi
318
319 last=$(( ${last} + 1 ))
320
321 local prefix
322 local x y z
323 while [ ${last} -gt ${first} ]; do
324 prefix=
325 x=31
326 y=2
327 z=1
328
329 while [ $(( ${first} % ${y} )) -eq 0 ] && [ ${last} -gt $(( ${first} + ${y} )) ]; do
330 prefix="/${x}"
331 x=$(( ${x} - 1 ))
332 z=${y}
333 y=$(( ${y} * 2 ))
334 done
335
336 print "$(ipv4_decode ${first})${prefix}"
337 first=$(( ${first} + ${z} ))
338 done
339}
340
1c6a4e30 341ipv4_range_explicit() {
999d659b
MT
342 local range=${1}
343
344 local first last
345
346 case "${range}" in
347 *.*.*.*-*.*.*.*)
348 first=${range%-*}
349 last=${range#*-}
350 ;;
351 *.*.*.*/*)
352 first=$(ipv4_get_network ${range})
13a6e69f 353 first="$(ip_split_prefix "${range}")"
999d659b 354 last=$(ipv4_get_broadcast ${range})
13a6e69f 355 last="$(ip_split_prefix "${range}")"
999d659b
MT
356 ;;
357 esac
358
359 _ipv4_range_explicit "$(ipv4_encode ${first})" "$(ipv4_encode ${last})"
360}
361
1c6a4e30 362_ipv4_range_explicit() {
999d659b
MT
363 local first=${1}
364 local last=${2}
365
366 if [ ${first} -gt ${last} ]; then
367 local range="$(ipv4_decode ${first})-$(ipv4_decode ${last})"
368
369 error "Invalid IPv4 address range: ${range}"
370 return ${EXIT_ERROR}
371 fi
372
373 while [ ${first} -le ${last} ]; do
374 ipv4_decode ${first}
375 first=$(( ${first} + 1 ))
376 done
377}
ab70371d 378
1c6a4e30 379ipv4_in_subnet() {
ab70371d
MT
380 local addr=${1}
381 assert isset addr
382
383 local subnet=${2}
384 assert isset subnet
385
386 local subnet_first=$(ipv4_get_network_encoded ${subnet})
387 local subnet_last=$(ipv4_get_broadcast_encoded ${subnet})
388
389 addr=$(ipv4_encode ${addr})
390
391 if [[ "${addr}" -ge "${subnet_first}" ]] && [[ "${addr}" -le "${subnet_last}" ]]; then
392 return ${EXIT_TRUE}
393 fi
394
395 return ${EXIT_FALSE}
396}
ef953be2 397
1c6a4e30 398ipv4_ttl_valid() {
ef953be2
MT
399 local ttl="${1}"
400
401 isinteger ttl || return ${EXIT_FALSE}
402
403 # Must be between 10 and 255.
404 [ "${ttl}" -lt 10 ] && return ${EXIT_FALSE}
405 [ "${ttl}" -gt 255 ] && return ${EXIT_FALSE}
406
407 return ${EXIT_TRUE}
408}