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