ipv4-static: Update hook
[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
05c234a8 24function ipv4_is_valid() {
fa6df98c 25 ipcalc --ipv4 -c $@ >/dev/null 2>&1
05c234a8 26
fa6df98c
MT
27 case "$?" in
28 0)
29 return ${EXIT_OK}
30 ;;
31 *)
38f61548 32 return ${EXIT_ERROR}
fa6df98c
MT
33 ;;
34 esac
05c234a8
MT
35}
36
cb965348
MT
37function ipv4_prefix_is_valid() {
38 local prefix=${1}
ab70371d
MT
39
40 isset prefix || return ${EXIT_FALSE}
cb965348
MT
41
42 [ ${prefix} -le 0 ] && return ${EXIT_FALSE}
43 [ ${prefix} -gt 32 ] && return ${EXIT_FALSE}
44
45 return ${EXIT_TRUE}
46}
47
ccbc0dd4
MT
48function ipv4_netmask_is_valid() {
49 local netmask="${1}"
50
51 # XXX this check could be much better by checking
52 # if the netmask only contains leading ones
53
54 ipv4_is_valid "${netmask}"
55}
56
05c234a8
MT
57function ipv4_detect_duplicate() {
58 local device=${1}
59 local address=${2}
60
61 assert isset address
62 assert isset device
63 assert device_exists ${device}
64
785afa13
MT
65 # Don't check on PPP devices.
66 device_is_ppp ${device} && return ${EXIT_ERROR}
67
05c234a8
MT
68 if ! arping -q -c 2 -w 3 -D -I ${device} ${address}; then
69 log DEBUG "Detected duplicate address '${address}' on device '${device}'."
9eebfc55 70 return ${EXIT_OK}
05c234a8
MT
71 fi
72
9eebfc55 73 return ${EXIT_ERROR}
05c234a8
MT
74}
75
76function ipv4_update_neighbours() {
77 local device=${1}
78 local address=${2}
79
785afa13
MT
80 # Don't do anything on PPP devices.
81 device_is_ppp ${device} && return ${EXIT_OK}
82
05c234a8
MT
83 arping -q -A -c 1 -I ${device} ${address}
84 ( sleep 2; arping -q -U -c 1 -I ${device} ${address} ) >/dev/null 2>&1 </dev/null &
85}
d5bace8d
MT
86
87function ipv4_get_netaddress() {
88 local address=${1}
89 assert isset address
90
91 local prefix=$(ip_get_prefix ${address})
1dbb6df4
MT
92 isset prefix || prefix="32"
93
94 # Assume host-only address if no prefix has been given.
95 if [ "${prefix}" = "32" ]; then
96 echo "${address}/${prefix}"
97 return ${EXIT_OK}
98 fi
d5bace8d
MT
99
100 local NETWORK
101 eval $(ipcalc --network ${address})
102 assert isset NETWORK
103
104 echo "${NETWORK}/${prefix}"
d5bace8d
MT
105 return ${EXIT_OK}
106}
e9ea243e
MT
107
108function ipv4_get_prefix() {
109 local address=${1}
110 local broadcast=${2}
111
112 assert isset address
113 assert isset broadcast
114
115 local PREFIX
116 eval $(ipcalc --prefix ${address} ${broadcast})
117 assert isset PREFIX
118
119 echo "${PREFIX}"
120 return ${EXIT_OK}
121}
122
ab70371d
MT
123function ipv4_get_netmask() {
124 local address=${1}
125 assert isset address
126
127 # Add prefix if none given.
128 local prefix=$(ip_get_prefix ${address})
129 isset prefix || address="${address}/32"
130
131 local NETMASK
132 eval $(ipcalc --netmask ${address})
133 assert isset NETMASK
134
135 print "${NETMASK}"
136 return ${EXIT_OK}
137}
138
e9ea243e
MT
139function ipv4_flush_device() {
140 #
141 # Flushes all routes, addresses from the device
142 # and clears the ARP cache.
143 #
144
145 local device=${1}
146 assert isset device
147
148 ip -4 addr flush dev ${device} >/dev/null 2>&1
149 ip -4 route flush dev ${device} >/dev/null 2>&1
150 ip -4 neigh flush dev ${device} >/dev/null 2>&1
151
152 return 0
c7b93f70 153}
6f49dbac 154
785afa13
MT
155function ipv4_prefix2netmask() {
156 local prefix=${1}
157 shift
158
159 assert isinteger prefix
160
161 # XXX this function is a stub
162
163 case "${prefix}" in
164 24)
165 echo "255.255.255.0"
166 ;;
167 *)
168 assert false NOT IMPLEMENTED
169 ;;
170 esac
e9ea243e 171}
999d659b 172
ccbc0dd4
MT
173function ipv4_netmask2prefix() {
174 local netmask="${1}"
175 assert isset netmask
176
177 local mask=0
178
179 local field
180 for field in ${netmask//\./ }; do
181 mask=$(( $(( ${mask} << 8 )) | ${field} ))
182 done
183
184 local cidr=0
185 local x="$(( 128 << 24 ))" # 0x80000000
186
187 while [ $(( ${x} & ${mask} )) -ne 0 ]; do
188 [ ${mask} -eq ${x} ] && mask=0 || mask=$(( ${mask} << 1 ))
189 cidr=$(( ${cidr} + 1 ))
190 done
191
192 assert [ $(( ${mask} & 2147483647 )) -eq 0 ]
193
194 print "${cidr}"
195}
196
999d659b 197function ipv4_get_network() {
ab70371d
MT
198 local network=$(ipv4_get_network $@)
199
200 ipv4_decode ${network}
201}
202
203function ipv4_get_network_encoded() {
999d659b
MT
204 local net=${1}
205
206 local prefix=$(ip_get_prefix ${net})
207 isset prefix || prefix=32
208
209 local mask=0
210 if [ ${prefix} -ne 0 ]; then
211 mask=$(( -1 << $(( 32 - ${prefix} )) ))
212 fi
213
214 local addr=$(ip_split_prefix ${net})
215 addr=$(ipv4_encode ${addr})
216
ab70371d 217 print "%d" $(( ${addr} & ${mask} ))
999d659b
MT
218}
219
220function ipv4_get_broadcast() {
ab70371d
MT
221 local broadcast=$(ipv4_get_broadcast_encoded $@)
222
223 ipv4_decode ${broadcast}
224}
225
226function ipv4_get_broadcast_encoded() {
999d659b
MT
227 local net=${1}
228
229 local prefix=$(ip_get_prefix ${net})
230 assert isset prefix
231
232 prefix=$(( 32 - ${prefix} ))
233
234 local netmask=0
235 local broadcast=-1
236 if [ ${prefix} -eq 32 ]; then
237 :
238 else
239 netmask=$(( -1 << ${prefix} ))
240 broadcast=$(( $(( 1 << ${prefix} )) - 1))
241 fi
242
243 local addr=$(ip_split_prefix ${net})
244 addr=$(ipv4_encode ${addr})
245
ab70371d 246 print "%d" $(( $(( ${addr} & ${netmask} )) | ${broadcast} ))
999d659b
MT
247}
248
249function ipv4_encode() {
250 local addr=${1}
251 local int=0
252
253 local field
254 for field in ${addr//./ }; do
255 int=$(( $(( ${int} << 8 )) | ${field} ))
256 done
257
258 print "${int}"
259}
260
261function ipv4_decode() {
262 local int=${1}
263
264 local addr=$(( ${int} & 255 ))
265
266 local i
267 for i in 1 2 3; do
268 int=$(( ${int} >> 8 ))
269 addr="$(( ${int} & 255 )).${addr}"
270 done
271
272 print "${addr}"
273}
274
ab70371d
MT
275function ipv4_addr_eq() {
276 local addr1=${1}
277 assert isset addr1
278
279 local addr2=${2}
280 assert isset addr2
281
282 [[ "${addr1}" = "${addr2}" ]] \
283 && return ${EXIT_TRUE} || return ${EXIT_FALSE}
284}
285
286function ipv4_addr_gt() {
287 local addr1=${1}
288 assert isset addr1
289
290 local addr2=${2}
291 assert isset addr2
292
293 local addr
294 for addr in addr1 addr2; do
295 printf -v ${addr} "%s" "$(ip_encode ${!addr})"
296 done
297
298 [[ ${addr1} -gt ${addr2} ]] \
299 && return ${EXIT_TRUE} || return ${EXIT_FALSE}
300}
301
999d659b
MT
302function ipv4_range() {
303 local range=${1}
304
305 local first=${1%-*}
306 local last=${1#*-}
307
308 _ipv4_range "$(ipv4_encode ${first})" "$(ipv4_encode ${last})"
309}
310
311function _ipv4_range() {
312 local first=${1}
313 local last=${2}
314
315 if [ ${first} -gt ${last} ]; then
316 local range="$(ipv4_decode ${first})-$(ipv4_decode ${last})"
317
318 error "Invalid IPv4 address range: ${range}"
319 return ${EXIT_ERROR}
320 fi
321
322 last=$(( ${last} + 1 ))
323
324 local prefix
325 local x y z
326 while [ ${last} -gt ${first} ]; do
327 prefix=
328 x=31
329 y=2
330 z=1
331
332 while [ $(( ${first} % ${y} )) -eq 0 ] && [ ${last} -gt $(( ${first} + ${y} )) ]; do
333 prefix="/${x}"
334 x=$(( ${x} - 1 ))
335 z=${y}
336 y=$(( ${y} * 2 ))
337 done
338
339 print "$(ipv4_decode ${first})${prefix}"
340 first=$(( ${first} + ${z} ))
341 done
342}
343
344function ipv4_range_explicit() {
345 local range=${1}
346
347 local first last
348
349 case "${range}" in
350 *.*.*.*-*.*.*.*)
351 first=${range%-*}
352 last=${range#*-}
353 ;;
354 *.*.*.*/*)
355 first=$(ipv4_get_network ${range})
356 last=$(ipv4_get_broadcast ${range})
357 ;;
358 esac
359
360 _ipv4_range_explicit "$(ipv4_encode ${first})" "$(ipv4_encode ${last})"
361}
362
363function _ipv4_range_explicit() {
364 local first=${1}
365 local last=${2}
366
367 if [ ${first} -gt ${last} ]; then
368 local range="$(ipv4_decode ${first})-$(ipv4_decode ${last})"
369
370 error "Invalid IPv4 address range: ${range}"
371 return ${EXIT_ERROR}
372 fi
373
374 while [ ${first} -le ${last} ]; do
375 ipv4_decode ${first}
376 first=$(( ${first} + 1 ))
377 done
378}
ab70371d
MT
379
380function ipv4_in_subnet() {
381 local addr=${1}
382 assert isset addr
383
384 local subnet=${2}
385 assert isset subnet
386
387 local subnet_first=$(ipv4_get_network_encoded ${subnet})
388 local subnet_last=$(ipv4_get_broadcast_encoded ${subnet})
389
390 addr=$(ipv4_encode ${addr})
391
392 if [[ "${addr}" -ge "${subnet_first}" ]] && [[ "${addr}" -le "${subnet_last}" ]]; then
393 return ${EXIT_TRUE}
394 fi
395
396 return ${EXIT_FALSE}
397}
ef953be2
MT
398
399function ipv4_ttl_valid() {
400 local ttl="${1}"
401
402 isinteger ttl || return ${EXIT_FALSE}
403
404 # Must be between 10 and 255.
405 [ "${ttl}" -lt 10 ] && return ${EXIT_FALSE}
406 [ "${ttl}" -gt 255 ] && return ${EXIT_FALSE}
407
408 return ${EXIT_TRUE}
409}