]>
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() { |
13a6e69f | 25 | inetcalc -4 -c $@ && return ${EXIT_OK} || return ${EXIT_ERROR} |
05c234a8 MT |
26 | } |
27 | ||
1c6a4e30 | 28 | ipv4_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 | 39 | ipv4_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 | 48 | ipv4_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 | 67 | ipv4_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 |
78 | ipv4_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 | 87 | ipv4_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 | 103 | ipv4_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 | 214 | ipv4_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 | 238 | ipv4_get_network() { |
13a6e69f | 239 | ip_get_network $@ |
999d659b MT |
240 | } |
241 | ||
1c6a4e30 | 242 | ipv4_get_broadcast() { |
13a6e69f | 243 | inetcalc -4 -b $@ && return ${EXIT_OK} || return ${EXIT_ERROR} |
999d659b MT |
244 | } |
245 | ||
1c6a4e30 | 246 | ipv4_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 | 258 | ipv4_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 | 272 | ipv4_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 | 283 | ipv4_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 | 299 | ipv4_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 | 341 | ipv4_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 | 379 | ipv4_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 | 398 | ipv4_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 | } |