]>
Commit | Line | Data |
---|---|---|
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 |
22 | IP_SUPPORTED_PROTOCOLS="${IP_SUPPORTED_PROTOCOLS} ipv4" |
23 | ||
1c6a4e30 | 24 | ipv4_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 | 42 | ipv4_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 |
54 | ipv4_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 | 63 | ipv4_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 | 72 | ipv4_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 | 91 | ipv4_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 |
102 | ipv4_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 | 111 | ipv4_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 | 127 | ipv4_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 | 238 | ipv4_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 | 262 | ipv4_get_network() { |
2212045f | 263 | ip_get_network "$@" |
999d659b MT |
264 | } |
265 | ||
1c6a4e30 | 266 | ipv4_get_broadcast() { |
2212045f | 267 | inetcalc -4 -b "$@" && return ${EXIT_OK} || return ${EXIT_ERROR} |
999d659b MT |
268 | } |
269 | ||
1c6a4e30 | 270 | ipv4_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 | 282 | ipv4_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 | 296 | ipv4_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 | 307 | ipv4_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 | 317 | ipv4_addr_ge() { |
2212045f | 318 | ipv4_addr_eq "$@" || ipv4_addr_gt "$@" |
ae02c40e MT |
319 | } |
320 | ||
321 | ipv4_addr_lt() { | |
2212045f | 322 | ! ipv4_addr_eq "$@" && ! ipv4_addr_gt "$@" |
ae02c40e MT |
323 | } |
324 | ||
325 | ipv4_addr_le() { | |
2212045f | 326 | ipv4_addr_eq "$@" || ! ipv4_addr_gt "$@" |
ae02c40e MT |
327 | } |
328 | ||
1c6a4e30 | 329 | ipv4_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 | 371 | ipv4_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}) | |
13a6e69f | 383 | first="$(ip_split_prefix "${range}")" |
999d659b | 384 | last=$(ipv4_get_broadcast ${range}) |
13a6e69f | 385 | last="$(ip_split_prefix "${range}")" |
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 | 409 | ipv4_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 | 428 | ipv4_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 | } |